249 lines
13 KiB
C#
249 lines
13 KiB
C#
// WL813c_Probe.cs — #813 전투 패드 · 보스 HP 바 실측 덤프 (에디트 모드 · Play 불필요 · 저장하지 않는다)
|
|
// unity command run_script --file AgentScripts/WL813c_Probe.cs --entry WL813c_Probe.DumpPad (발주서 ⓑ · 부채꼴 좌표 + 미러 2회)
|
|
// unity command run_script --file AgentScripts/WL813c_Probe.cs --entry WL813c_Probe.DumpBossEvents (발주서 ⓒ · 가짜 이벤트 → 바 갱신)
|
|
// unity command run_script --file AgentScripts/WL813c_Probe.cs --entry WL813c_Probe.DumpPrefab (발주서 ⓓ · 저장된 프리팹 노드 상태)
|
|
// unity command run_script --file AgentScripts/WL813c_Probe.cs --entry WL813c_Probe.DumpOverride (발주서 ⓓ · WLIngameUiOverride 대상 경로 회귀)
|
|
// 덤프는 Logs/WL813c_probe_*.txt 에도 남긴다(콘솔 잘림 대비).
|
|
using System.IO;
|
|
using System.Text;
|
|
using UnityEditor;
|
|
using UnityEditor.SceneManagement;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
public static class WL813c_Probe
|
|
{
|
|
// run_script 는 파일마다 독립 어셈블리로 컴파일된다 — WL813c_Apply 의 상수를 참조할 수 없어 여기 다시 둔다(값 동일).
|
|
public const string NewGameUIPath = "Assets/Res_Addr/MainUI/NewGameUI.prefab";
|
|
public const string PadPath = "IngameUIs/BattleUI";
|
|
public const string HudPath = "IngameUIs/WL_HUD";
|
|
public const string BossBarName = "WL_BossHpBar";
|
|
const string LogDir = "Logs";
|
|
|
|
static string Save(string name, string body)
|
|
{
|
|
Directory.CreateDirectory(LogDir);
|
|
var path = Path.Combine(LogDir, "WL813c_probe_" + name + ".txt");
|
|
File.WriteAllText(path, body, new System.Text.UTF8Encoding(false));
|
|
return body + "\n(저장: " + path + ")";
|
|
}
|
|
|
|
static Transform FindByPath(Transform root, string path)
|
|
{
|
|
var cur = root;
|
|
foreach (var part in path.Split('/'))
|
|
{
|
|
Transform next = null;
|
|
for (int i = 0; i < cur.childCount; i++)
|
|
if (cur.GetChild(i).name == part) { next = cur.GetChild(i); break; }
|
|
if (next == null) return null;
|
|
cur = next;
|
|
}
|
|
return cur;
|
|
}
|
|
|
|
/// <summary>발주서 ⓑ — 실제 NewGameUI 프리팹 계층에서 배치를 적용하고 좌표를 덤프한다(저장 안 함 · 미러 2회).</summary>
|
|
public static object DumpPad()
|
|
{
|
|
var sb = new StringBuilder();
|
|
var s = WL.UI.WLHudLayoutSettings.Instance;
|
|
if (s == null) return "🔴 WLHudLayoutSettings 없음";
|
|
bool origMirror = s.mirrorLeftHanded;
|
|
|
|
var root = PrefabUtility.LoadPrefabContents(NewGameUIPath);
|
|
try
|
|
{
|
|
var pad = FindByPath(root.transform, PadPath);
|
|
if (pad == null) return "🔴 " + PadPath + " 없음";
|
|
var layout = pad.GetComponent<WL.UI.WLBattlePadLayout>();
|
|
if (layout == null) return "🔴 WLBattlePadLayout 없음 — Apply 먼저";
|
|
|
|
var canvas = pad.GetComponentInParent<Canvas>();
|
|
var scaler = canvas != null ? canvas.GetComponent<CanvasScaler>() : null;
|
|
sb.AppendLine("Canvas=" + (canvas != null ? canvas.name : "없음") +
|
|
" scaleMode=" + (scaler != null ? scaler.uiScaleMode.ToString() : "-") +
|
|
" refRes=" + (scaler != null ? scaler.referenceResolution.ToString() : "-") +
|
|
" matchMode=" + (scaler != null ? scaler.screenMatchMode.ToString() : "-") +
|
|
" match=" + (scaler != null ? scaler.matchWidthOrHeight.ToString("F2") : "-"));
|
|
sb.AppendLine("SafeAreaFitter on pad = " + (pad.GetComponent<WL.UI.SafeAreaFitter>() != null) +
|
|
" · WL_HUD 형제 fitter = " + (FindByPath(root.transform, HudPath) != null &&
|
|
FindByPath(root.transform, HudPath).GetComponent<WL.UI.SafeAreaFitter>() != null));
|
|
sb.AppendLine();
|
|
|
|
s.mirrorLeftHanded = false;
|
|
sb.AppendLine("── 1회차 mirror=false ──────────────────────────────");
|
|
sb.AppendLine(layout.Apply());
|
|
sb.AppendLine(layout.Dump());
|
|
|
|
s.mirrorLeftHanded = true;
|
|
sb.AppendLine("── 2회차 mirror=true ───────────────────────────────");
|
|
sb.AppendLine(layout.Apply());
|
|
sb.AppendLine(layout.Dump());
|
|
}
|
|
finally
|
|
{
|
|
PrefabUtility.UnloadPrefabContents(root); // 저장하지 않는다 = 프리팹 무변경
|
|
s.mirrorLeftHanded = origMirror; // 에셋 값 원복(파일 저장 안 함)
|
|
}
|
|
return Save("pad", sb.ToString());
|
|
}
|
|
|
|
/// <summary>발주서 ⓒ — 임시 씬에 살아 있는 BossHpBar 를 만들고 가짜 전투 이벤트를 실제 CombatEvents 경로로 발행한다.</summary>
|
|
public static object DumpBossEvents()
|
|
{
|
|
var sb = new StringBuilder();
|
|
var s = WL.UI.WLHudLayoutSettings.Instance;
|
|
if (s == null) return "🔴 WLHudLayoutSettings 없음";
|
|
|
|
// 배치모드 에디터는 "제목 없는 미저장 씬"이 열려 있어 Additive 새 씬을 못 만든다.
|
|
// → 현재 씬에 임시 오브젝트를 만들고 끝나면 지운다(저장하지 않는다).
|
|
GameObject cgo = null;
|
|
try
|
|
{
|
|
// NewGameUI 와 같은 캔버스 규격(실측: Expand · 참조 1920x1080 · match 0)
|
|
cgo = new GameObject("WL813cProbeCanvas", typeof(Canvas), typeof(CanvasScaler));
|
|
var canvas = cgo.GetComponent<Canvas>();
|
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
var sc = cgo.GetComponent<CanvasScaler>();
|
|
sc.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
sc.referenceResolution = new Vector2(1920f, 1080f);
|
|
sc.screenMatchMode = CanvasScaler.ScreenMatchMode.Expand;
|
|
sc.matchWidthOrHeight = 0f;
|
|
|
|
var hud = new GameObject("WL_HUD", typeof(RectTransform), typeof(WL.UI.SafeAreaFitter));
|
|
var hrt = (RectTransform)hud.transform;
|
|
hrt.SetParent(cgo.transform, false);
|
|
hrt.anchorMin = Vector2.zero; hrt.anchorMax = Vector2.one;
|
|
hrt.offsetMin = Vector2.zero; hrt.offsetMax = Vector2.zero;
|
|
|
|
int beforeSpawned = WL.Combat.Core.CombatEvents.Spawned.Count;
|
|
var bgo = new GameObject(BossBarName, typeof(RectTransform));
|
|
((RectTransform)bgo.transform).SetParent(hrt, false);
|
|
var bar = bgo.AddComponent<WL.UI.BossHpBar>();
|
|
// 에디트 모드에서는 OnEnable 이 불리지 않는다 → OnEnable 본체(Initialize)를 직접 부른다(런타임과 같은 경로).
|
|
sb.AppendLine("Initialize: " + bar.Initialize());
|
|
|
|
sb.AppendLine("구독 전/후 Spawned 구독자 = " + beforeSpawned + " → " + WL.Combat.Core.CombatEvents.Spawned.Count);
|
|
sb.AppendLine("초기: " + bar.Dump());
|
|
|
|
// ⓪ 비보스 스폰은 바를 켜지 않아야 한다(발주서 §1-2 "이벤트 미도착/무관 = 미표시")
|
|
sb.AppendLine("⓪ " + WL.UI.BossHpBar.RaiseFakeNonBossSpawned() + " → visible=" + bar.Visible + " (기대 False)");
|
|
|
|
sb.AppendLine("① " + WL.UI.BossHpBar.RaiseFakeBossSpawned(1000f));
|
|
sb.AppendLine(bar.Dump());
|
|
sb.AppendLine("② " + WL.UI.BossHpBar.RaiseFakeHit(300d));
|
|
sb.AppendLine(bar.Dump());
|
|
sb.AppendLine("③ " + WL.UI.BossHpBar.RaiseFakeHit(350d));
|
|
sb.AppendLine(bar.Dump());
|
|
sb.AppendLine("④ " + WL.UI.BossHpBar.RaiseFakeKilled());
|
|
sb.AppendLine(bar.Dump());
|
|
|
|
bar.Subscribe(false); // 에디트 모드에서는 OnDisable 이 불리지 않는다 — 구독을 명시적으로 뗀다
|
|
Object.DestroyImmediate(bgo);
|
|
sb.AppendLine("정리 후 Spawned 구독자 = " + WL.Combat.Core.CombatEvents.Spawned.Count + " (기대 " + beforeSpawned + ")");
|
|
}
|
|
finally { if (cgo != null) Object.DestroyImmediate(cgo); }
|
|
return Save("boss", sb.ToString());
|
|
}
|
|
|
|
/// <summary>발주서 ⓓ — 저장된 프리팹의 추가 노드/컴포넌트 상태만 덤프한다(계층 전체 덤프 아님).</summary>
|
|
public static object DumpPrefab()
|
|
{
|
|
var sb = new StringBuilder();
|
|
var root = PrefabUtility.LoadPrefabContents(NewGameUIPath);
|
|
try
|
|
{
|
|
var pad = FindByPath(root.transform, PadPath);
|
|
sb.AppendLine(PadPath + " : " + (pad == null ? "없음" : Comp(pad)));
|
|
if (pad != null)
|
|
{
|
|
var prt = (RectTransform)pad;
|
|
sb.AppendLine(" rect aMin=" + prt.anchorMin + " aMax=" + prt.anchorMax + " offMin=" + prt.offsetMin +
|
|
" offMax=" + prt.offsetMax + " pivot=" + prt.pivot + " scale=" + prt.localScale +
|
|
" activeSelf=" + pad.gameObject.activeSelf + " children=" + pad.childCount);
|
|
for (int i = 0; i < pad.childCount; i++)
|
|
{
|
|
var c = pad.GetChild(i);
|
|
sb.AppendLine(" - " + c.name + " active=" + c.gameObject.activeSelf + " " +
|
|
Rect2(c as RectTransform));
|
|
}
|
|
}
|
|
var hud = FindByPath(root.transform, HudPath);
|
|
sb.AppendLine(HudPath + " : " + (hud == null ? "없음" : Comp(hud) + " children=" + hud.childCount));
|
|
if (hud != null)
|
|
for (int i = 0; i < hud.childCount; i++)
|
|
sb.AppendLine(" - " + hud.GetChild(i).name);
|
|
var bar = hud != null ? hud.Find(BossBarName) : null;
|
|
if (bar != null)
|
|
{
|
|
sb.AppendLine(BossBarName + " : " + Comp(bar) + " " + Rect2(bar as RectTransform));
|
|
DumpTree(bar, 1, sb);
|
|
var b = bar.GetComponent<WL.UI.BossHpBar>();
|
|
if (b != null) sb.AppendLine(b.Dump());
|
|
}
|
|
}
|
|
finally { PrefabUtility.UnloadPrefabContents(root); }
|
|
return Save("prefab", sb.ToString());
|
|
}
|
|
|
|
/// <summary>발주서 ⓓ — WLIngameUiOverride 가 쓰는 경로가 여전히 유효한지(패드 숨김 회귀 0).</summary>
|
|
public static object DumpOverride()
|
|
{
|
|
var sb = new StringBuilder();
|
|
var gs = WL.Settings.WLGameplaySettings.Instance;
|
|
sb.AppendLine("WLGameplaySettings: hideBattlePad=" + (gs != null ? gs.hideBattlePad.ToString() : "(에셋없음)") +
|
|
" (813c 는 읽기만 · 값 전환은 Lead)");
|
|
var root = PrefabUtility.LoadPrefabContents(NewGameUIPath);
|
|
try
|
|
{
|
|
foreach (var p in (gs != null && gs.battlePadPaths != null ? gs.battlePadPaths : new string[0]))
|
|
{
|
|
var t = FindByPath(root.transform, p);
|
|
sb.AppendLine(" battlePadPath \"" + p + "\" → " + (t == null ? "🔴 못 찾음(회귀!)" :
|
|
"OK activeSelf=" + t.gameObject.activeSelf + " children=" + t.childCount));
|
|
}
|
|
foreach (var p in (gs != null && gs.ingameHideCanvasGroupPaths != null ? gs.ingameHideCanvasGroupPaths : new string[0]))
|
|
{
|
|
var t = FindByPath(root.transform, p);
|
|
sb.AppendLine(" hideCanvasGroupPath \"" + p + "\" → " + (t == null ? "🔴 못 찾음(회귀!)" : "OK"));
|
|
}
|
|
var common = FindByPath(root.transform, "Common");
|
|
foreach (var n in (gs != null && gs.ingameHideCommonObjectNames != null ? gs.ingameHideCommonObjectNames : new string[0]))
|
|
{
|
|
var t = common != null ? common.Find(n) : null;
|
|
sb.AppendLine(" hideCommonName \"" + n + "\" → " + (t == null ? "「미확인」(NewGameUI.gos[0] 인덱스 기준이라 프리팹 경로와 다를 수 있음)" : "OK"));
|
|
}
|
|
}
|
|
finally { PrefabUtility.UnloadPrefabContents(root); }
|
|
return Save("override", sb.ToString());
|
|
}
|
|
|
|
static void DumpTree(Transform t, int depth, StringBuilder sb)
|
|
{
|
|
for (int i = 0; i < t.childCount; i++)
|
|
{
|
|
var c = t.GetChild(i);
|
|
sb.AppendLine(new string(' ', depth * 2) + "- " + c.name + " " + Comp(c) + " " + Rect2(c as RectTransform));
|
|
DumpTree(c, depth + 1, sb);
|
|
}
|
|
}
|
|
|
|
static string Comp(Transform t)
|
|
{
|
|
var sb = new StringBuilder("[");
|
|
var cs = t.GetComponents<Component>();
|
|
for (int i = 0; i < cs.Length; i++)
|
|
{
|
|
if (i > 0) sb.Append(',');
|
|
sb.Append(cs[i] == null ? "MISSING" : cs[i].GetType().Name);
|
|
}
|
|
return sb.Append(']').ToString();
|
|
}
|
|
|
|
static string Rect2(RectTransform rt)
|
|
{
|
|
if (rt == null) return "";
|
|
return "aMin" + rt.anchorMin + " aMax" + rt.anchorMax + " pos" + rt.anchoredPosition + " size" + rt.sizeDelta;
|
|
}
|
|
}
|