140 lines
6.8 KiB
C#
140 lines
6.8 KiB
C#
// WL802b_Probe.cs — #802 재단 2차 검증 덤프: CanvasScaler 유닛 스케일 + SafeAreaFitter 부착/앵커 실측 (에디트 모드 · Play 불필요)
|
|
// unity command run_script --file AgentScripts/WL802b_Probe.cs --entry WL802b_Probe.Dump
|
|
// 산출: ⓑ 파일당 SafeAreaFitter 개수·경로 · ⓒ 부착 RectTransform 앵커/offset + safeArea=전체화면 시뮬레이션 · ⓓ #806 팝업 값 · ⓔ 환산표.
|
|
using System.Text;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
public static class WL802b_Probe
|
|
{
|
|
static readonly string[] Prefabs =
|
|
{
|
|
"Assets/ResWork/UIPrefabs/Title/TitleInfo.prefab",
|
|
"Assets/ResWork/UIPrefabs/Title/SortOrder_5.prefab",
|
|
"Assets/Res_Addr/MainUI/NewGameUI.prefab",
|
|
};
|
|
|
|
// Lead 확정 QA 캡처 해상도 5종 (§3)
|
|
static readonly Vector2Int[] QaRes =
|
|
{
|
|
new Vector2Int(1080, 1920), new Vector2Int(1080, 2340), new Vector2Int(1080, 2400),
|
|
new Vector2Int(720, 1600), new Vector2Int(1440, 3200),
|
|
};
|
|
|
|
// CanvasScaler.ScreenMatchMode.Expand 의 실제 계산식 (UnityEngine.UI 소스와 동일)
|
|
static float ExpandScale(Vector2 refRes, Vector2Int screen)
|
|
{
|
|
return Mathf.Min(screen.x / refRes.x, screen.y / refRes.y);
|
|
}
|
|
|
|
static string Path(Transform t, Transform stop)
|
|
{
|
|
var s = t.name;
|
|
for (var p = t.parent; p != null && p != stop; p = p.parent) s = p.name + "/" + s;
|
|
return s;
|
|
}
|
|
|
|
static string Rt(RectTransform rt)
|
|
{
|
|
return "aMin=" + rt.anchorMin + " aMax=" + rt.anchorMax + " offMin=" + rt.offsetMin + " offMax=" + rt.offsetMax
|
|
+ " size=" + rt.sizeDelta + " pos=" + rt.anchoredPosition + " pivot=" + rt.pivot;
|
|
}
|
|
|
|
// SafeAreaFitter.Apply() 와 동일한 산식 — Play 없이 결과를 재현한다.
|
|
static string SimulateFitter(Rect safe, Vector2Int screen)
|
|
{
|
|
var min = new Vector2(safe.xMin / screen.x, safe.yMin / screen.y);
|
|
var max = new Vector2(safe.xMax / screen.x, safe.yMax / screen.y);
|
|
return "screen=" + screen.x + "x" + screen.y + " safeArea=" + safe
|
|
+ " → anchorMin=" + min + " anchorMax=" + max + " offsetMin=(0,0) offsetMax=(0,0)";
|
|
}
|
|
|
|
static RectTransform FindByName(GameObject root, string name)
|
|
{
|
|
foreach (var rt in root.GetComponentsInChildren<RectTransform>(true)) if (rt.name == name) return rt;
|
|
return null;
|
|
}
|
|
|
|
public static object Dump()
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.AppendLine("== WL-802b Probe ==");
|
|
|
|
foreach (var path in Prefabs)
|
|
{
|
|
var root = PrefabUtility.LoadPrefabContents(path);
|
|
try
|
|
{
|
|
sb.AppendLine();
|
|
sb.AppendLine("### " + path + " (root=" + root.name + ")");
|
|
|
|
// --- CanvasScaler ---
|
|
foreach (var cs in root.GetComponentsInChildren<CanvasScaler>(true))
|
|
{
|
|
sb.AppendLine(" CanvasScaler @" + Path(cs.transform, root.transform.parent)
|
|
+ " mode=" + cs.uiScaleMode + " ref=" + cs.referenceResolution
|
|
+ " match=" + cs.screenMatchMode + " matchWH=" + cs.matchWidthOrHeight
|
|
+ " refPPU=" + cs.referencePixelsPerUnit);
|
|
foreach (var r in QaRes)
|
|
sb.AppendLine(" scaleFactor " + r.x + "x" + r.y + " = " + ExpandScale(cs.referenceResolution, r).ToString("0.#####")
|
|
+ " (1 px = " + (1f / ExpandScale(cs.referenceResolution, r)).ToString("0.####") + " unit)");
|
|
}
|
|
|
|
// --- SafeAreaFitter ---
|
|
var fitters = root.GetComponentsInChildren<WL.UI.SafeAreaFitter>(true);
|
|
sb.AppendLine(" SafeAreaFitter count = " + fitters.Length);
|
|
foreach (var f in fitters)
|
|
{
|
|
var so = new SerializedObject(f);
|
|
var rt = (RectTransform)f.transform;
|
|
bool activeChain = true;
|
|
for (var t = f.transform; t != null; t = t.parent) if (!t.gameObject.activeSelf) { activeChain = false; break; }
|
|
sb.AppendLine(" @" + Path(f.transform, root.transform.parent)
|
|
+ " parent=" + (f.transform.parent != null ? f.transform.parent.name : "(none)")
|
|
+ " canvasDirectChild=" + (f.transform.parent == root.transform)
|
|
+ " activeInPrefab=" + activeChain
|
|
+ " applyH=" + so.FindProperty("applyHorizontal").boolValue
|
|
+ " applyV=" + so.FindProperty("applyVertical").boolValue);
|
|
sb.AppendLine(" RectTransform: " + Rt(rt));
|
|
sb.AppendLine(" graphic=" + (rt.GetComponent<Graphic>() != null) + " childCount=" + rt.childCount);
|
|
}
|
|
|
|
// --- #806 팝업 값 (레이아웃 회귀 확인) ---
|
|
if (path.EndsWith("SortOrder_5.prefab"))
|
|
{
|
|
foreach (var n in new[] { "PopupUI", "LoadingUI" })
|
|
{
|
|
var p = FindByName(root, n);
|
|
if (p == null) { sb.AppendLine(" [" + n + "] 없음"); continue; }
|
|
sb.AppendLine(" [" + n + "] " + Rt(p));
|
|
foreach (var c in p.GetComponentsInChildren<RectTransform>(true))
|
|
if (c != p && (c.name == "bg" || c.name == "msg" || c.name == "btn_ok"))
|
|
sb.AppendLine(" " + c.name + " " + Rt(c));
|
|
}
|
|
}
|
|
}
|
|
finally { PrefabUtility.UnloadPrefabContents(root); }
|
|
}
|
|
|
|
// --- ⓒ safeArea = 전체 화면일 때 회귀 0 ---
|
|
sb.AppendLine();
|
|
sb.AppendLine("### SafeAreaFitter.Apply 시뮬레이션 (Play 없이 산식 재현)");
|
|
foreach (var r in QaRes)
|
|
sb.AppendLine(" 미적용기기: " + SimulateFitter(new Rect(0, 0, r.x, r.y), r));
|
|
sb.AppendLine(" 노치예시(추정): " + SimulateFitter(new Rect(0, 0, 1080, 2400 - 91), new Vector2Int(1080, 2400)));
|
|
|
|
// --- ⓔ 환산표 ---
|
|
sb.AppendLine();
|
|
sb.AppendLine("### 유닛 ↔ px 환산 (세로 1080 폭 기준 · Expand)");
|
|
sb.AppendLine(" ref 1080x1920: scale 1.0 → 1 unit = 1 px");
|
|
sb.AppendLine(" ref 1920x1080: scale 0.5625 → 1 px = 1.7778 unit");
|
|
foreach (var px in new[] { 44f, 88f, 130f, 340f })
|
|
sb.AppendLine(" " + px + " px = " + px + " unit(1080기준) = " + (px / 0.5625f).ToString("0.##") + " unit(1920기준)");
|
|
|
|
sb.AppendLine();
|
|
sb.AppendLine("Screen(batch) = " + Screen.width + "x" + Screen.height + " safeArea=" + Screen.safeArea + " (배치모드 값 — 실기 아님)");
|
|
return sb.ToString();
|
|
}
|
|
}
|