Project_WL/AgentScripts/WL796_Probe.cs

251 lines
12 KiB
C#

// WL796_Probe.cs — PD 지시 #796 (하단 채팅창 숨김 + 하단 메뉴 가득 채우기) 사전 실측 · 읽기 전용
// unity command run_script --file AgentScripts/WL796_Probe.cs --entry WL796_Probe.DumpPrefab
// unity command run_script --file AgentScripts/WL796_Probe.cs --entry WL796_Probe.DumpNode --args '["WL_HUD"]'
// unity command run_script --file AgentScripts/WL796_Probe.cs --entry WL796_Probe.RuntimeRects (Play 중)
// 프리팹을 저장하지 않는다(AssetDatabase.LoadAssetAtPath 로 읽기만).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
public static class WL796_Probe
{
const string PrefabPath = "Assets/Res_Addr/MainUI/NewGameUI.prefab";
static GameObject Root()
{
return AssetDatabase.LoadAssetAtPath<GameObject>(PrefabPath);
}
static string Path(Transform t, Transform root)
{
var parts = new List<string>();
while (t != null && t != root) { parts.Add(t.name); t = t.parent; }
parts.Reverse();
return string.Join("/", parts);
}
static string RtLine(RectTransform rt)
{
if (rt == null) return "(no RectTransform)";
return string.Format(
"aMin{0} aMax{1} piv{2} anchoredPos{3} sizeDelta{4} scale{5}",
rt.anchorMin.ToString("F2"), rt.anchorMax.ToString("F2"), rt.pivot.ToString("F2"),
rt.anchoredPosition.ToString("F1"), rt.sizeDelta.ToString("F1"), rt.localScale.ToString("F3"));
}
static string Comps(GameObject go)
{
var names = go.GetComponents<Component>()
.Where(c => c != null)
.Select(c => c.GetType().Name)
.Where(n => n != "RectTransform" && n != "Transform");
return string.Join(",", names.ToArray());
}
static void Walk(Transform t, Transform root, StringBuilder sb, int depth, int maxDepth)
{
string pad = new string(' ', depth * 2);
var rt = t as RectTransform;
sb.Append(pad).Append(t.name)
.Append(t.gameObject.activeSelf ? "" : " [OFF]")
.Append(" ").Append(RtLine(rt));
string c = Comps(t.gameObject);
if (c.Length > 0) sb.Append(" {").Append(c).Append("}");
var btn = t.GetComponent<Button>();
if (btn != null)
{
int n = btn.onClick.GetPersistentEventCount();
var ev = new List<string>();
for (int i = 0; i < n; i++)
{
var tgt = btn.onClick.GetPersistentTarget(i);
ev.Add((tgt != null ? tgt.GetType().Name : "null") + "." + btn.onClick.GetPersistentMethodName(i));
}
sb.Append(" onClick[").Append(string.Join(" | ", ev.ToArray())).Append("]");
}
var txt = t.GetComponent<UnityEngine.UI.Text>();
if (txt != null) sb.Append(" text=\"").Append(txt.text).Append("\"");
var tmp = t.GetComponent<TMPro.TMP_Text>();
if (tmp != null) sb.Append(" tmp=\"").Append(tmp.text).Append("\"");
sb.AppendLine();
if (depth >= maxDepth) { if (t.childCount > 0) sb.Append(pad).Append(" ...(").Append(t.childCount).AppendLine(" children)"); return; }
for (int i = 0; i < t.childCount; i++) Walk(t.GetChild(i), root, sb, depth + 1, maxDepth);
}
static Transform FindDeep(Transform root, string name)
{
if (root.name == name) return root;
for (int i = 0; i < root.childCount; i++)
{
var r = FindDeep(root.GetChild(i), name);
if (r != null) return r;
}
return null;
}
static List<Transform> FindAllDeep(Transform root, string name, List<Transform> acc)
{
if (root.name == name) acc.Add(root);
for (int i = 0; i < root.childCount; i++) FindAllDeep(root.GetChild(i), name, acc);
return acc;
}
/// <summary>프리팹 최상위 자식 목록 + 캔버스/스케일러 설정.</summary>
public static object DumpPrefab()
{
var go = Root();
if (go == null) return "prefab not found: " + PrefabPath;
var sb = new StringBuilder();
var canvas = go.GetComponent<Canvas>();
var scaler = go.GetComponent<CanvasScaler>();
sb.AppendLine("root=" + go.name + " comps={" + Comps(go) + "}");
if (canvas != null) sb.AppendLine("Canvas renderMode=" + canvas.renderMode + " sortOrder=" + canvas.sortingOrder);
if (scaler != null) sb.AppendLine("CanvasScaler mode=" + scaler.uiScaleMode + " ref=" + scaler.referenceResolution +
" match=" + scaler.matchWidthOrHeight + " screenMatch=" + scaler.screenMatchMode);
var rrt = go.transform as RectTransform;
sb.AppendLine("rootRect " + RtLine(rrt));
sb.AppendLine("== top-level children (" + go.transform.childCount + ") ==");
for (int i = 0; i < go.transform.childCount; i++)
{
var c = go.transform.GetChild(i);
sb.AppendLine(" [" + i + "] " + c.name + (c.gameObject.activeSelf ? "" : " [OFF]") + " " + RtLine(c as RectTransform) + " children=" + c.childCount);
}
// 이름 중복 확인
foreach (var n in new[] { "Chat", "WL_HUD", "BotMenu", "HUD", "Common", "IngameUIs" })
{
var all = FindAllDeep(go.transform, n, new List<Transform>());
sb.AppendLine("find '" + n + "' count=" + all.Count + " -> " + string.Join(" ; ", all.Select(t => Path(t, go.transform)).ToArray()));
}
return sb.ToString();
}
/// <summary>하단 메뉴 5버튼의 Image(배경) 스프라이트·색·알파 — 넓히면 늘어나는지 판단용.</summary>
public static object ButtonImages()
{
var go = Root();
if (go == null) return "prefab not found";
var menu = FindDeep(go.transform, "HUD_BottomMenu");
if (menu == null) return "HUD_BottomMenu not found";
var sb = new StringBuilder();
for (int i = 0; i < menu.childCount; i++)
{
var b = menu.GetChild(i);
var img = b.GetComponent<Image>();
sb.Append(b.name).Append(" : ");
if (img == null) sb.AppendLine("(no Image)");
else sb.AppendLine("sprite=" + (img.sprite != null ? img.sprite.name : "(null)") +
" color=" + img.color + " a=" + img.color.a.ToString("F3") +
" type=" + img.type + " raycast=" + img.raycastTarget +
" preserveAspect=" + img.preserveAspect);
// 아이콘도 함께
var icon = b.Find("Icon");
if (icon != null)
{
var ii = icon.GetComponent<Image>();
if (ii != null) sb.AppendLine(" Icon sprite=" + (ii.sprite != null ? ii.sprite.name : "(null)") + " a=" + ii.color.a.ToString("F2"));
}
}
return sb.ToString();
}
/// <summary>이름으로 찾은 노드의 서브트리를 덤프한다(기본 깊이 4).</summary>
public static object DumpNode(string name)
{
return DumpNodeDepth(name, 4);
}
public static object DumpNodeDepth(string name, int maxDepth)
{
var go = Root();
if (go == null) return "prefab not found";
var all = FindAllDeep(go.transform, name, new List<Transform>());
if (all.Count == 0) return "not found: " + name;
var sb = new StringBuilder();
foreach (var t in all)
{
sb.AppendLine("=== " + Path(t, go.transform) + " (parent=" + (t.parent != null ? t.parent.name : "-") + ") ===");
Walk(t, go.transform, sb, 0, maxDepth);
sb.AppendLine();
}
return sb.ToString();
}
/// <summary>경로로 찾은 노드의 서브트리를 덤프한다.</summary>
public static object DumpPath(string path, int maxDepth)
{
var go = Root();
if (go == null) return "prefab not found";
var t = go.transform.Find(path);
if (t == null) return "not found path: " + path;
var sb = new StringBuilder();
sb.AppendLine("=== " + path + " ===");
Walk(t, go.transform, sb, 0, maxDepth);
return sb.ToString();
}
// ── Play 중 실측 ──────────────────────────────────────────────────────────
static Rect ScreenRect(RectTransform rt, Canvas canvas)
{
var corners = new Vector3[4];
rt.GetWorldCorners(corners);
var cam = canvas != null && canvas.renderMode != RenderMode.ScreenSpaceOverlay ? canvas.worldCamera : null;
Vector2 min = new Vector2(float.MaxValue, float.MaxValue), max = new Vector2(float.MinValue, float.MinValue);
for (int i = 0; i < 4; i++)
{
Vector2 p = cam != null ? (Vector2)RectTransformUtility.WorldToScreenPoint(cam, corners[i]) : (Vector2)corners[i];
min = Vector2.Min(min, p); max = Vector2.Max(max, p);
}
return Rect.MinMaxRect(min.x, min.y, max.x, max.y);
}
/// <summary>Play 중: 하단 메뉴 버튼들과 Chat 의 화면 픽셀 사각형 · 활성 상태 · 알파.</summary>
public static object RuntimeRects()
{
if (!Application.isPlaying) return "not playing";
var sb = new StringBuilder();
sb.AppendLine("screen=" + Screen.width + "x" + Screen.height + " safeArea=" + Screen.safeArea.ToString("F0") + " dpi=" + Screen.dpi);
// 런타임 인스턴스 이름은 "NewGameUI(Clone)" 이 될 수 있으므로 컴포넌트 타입으로 찾는다.
var comp = GameObject.FindObjectsByType<NewGameUI>(FindObjectsInactive.Include, FindObjectsSortMode.None).FirstOrDefault();
GameObject uiRoot = comp != null ? comp.gameObject : GameObject.Find("NewGameUI");
if (uiRoot == null) return sb.AppendLine("NewGameUI not found").ToString();
sb.AppendLine("uiRoot=" + uiRoot.name);
var canvas = uiRoot.GetComponent<Canvas>();
var scaler = uiRoot.GetComponent<CanvasScaler>();
if (scaler != null) sb.AppendLine("scaler ref=" + scaler.referenceResolution + " match=" + scaler.matchWidthOrHeight + " scaleFactor=" + (canvas != null ? canvas.scaleFactor : 0f));
foreach (var nm in new[] { "WL_HUD", "Chat" })
{
var t = FindDeep(uiRoot.transform, nm);
if (t == null) { sb.AppendLine("[" + nm + "] not found"); continue; }
var cg = t.GetComponent<CanvasGroup>();
sb.AppendLine("[" + nm + "] activeSelf=" + t.gameObject.activeSelf + " activeInHierarchy=" + t.gameObject.activeInHierarchy +
(cg != null ? " CanvasGroup alpha=" + cg.alpha + " blocksRaycasts=" + cg.blocksRaycasts + " interactable=" + cg.interactable : " (no CanvasGroup)") +
" rect=" + (t is RectTransform ? ScreenRect(t as RectTransform, canvas).ToString("F0") : "-"));
for (int i = 0; i < t.childCount; i++)
{
var c = t.GetChild(i);
var crt = c as RectTransform;
sb.AppendLine(" - " + c.name + (c.gameObject.activeSelf ? "" : " [OFF]") + " rect=" + (crt != null ? ScreenRect(crt, canvas).ToString("F0") : "-"));
if (nm == "WL_HUD" && c.name.IndexOf("Menu", StringComparison.OrdinalIgnoreCase) >= 0)
{
for (int j = 0; j < c.childCount; j++)
{
var b = c.GetChild(j);
var brt = b as RectTransform;
var r = brt != null ? ScreenRect(brt, canvas) : new Rect();
sb.AppendLine(" * " + b.name + " x[" + r.xMin.ToString("F0") + ".." + r.xMax.ToString("F0") + "] y[" +
r.yMin.ToString("F0") + ".." + r.yMax.ToString("F0") + "] w=" + r.width.ToString("F0") + " h=" + r.height.ToString("F0") +
" scale=" + b.localScale.x.ToString("F2") + (b.gameObject.activeSelf ? "" : " [OFF]"));
}
}
}
}
return sb.ToString();
}
}