385 lines
19 KiB
C#
385 lines
19 KiB
C#
|
|
// WL-813tj (#813) — ① 설정 에셋 2종 생성 ② NewGameUI Safe Area 실효화(5레이어 재부모화)
|
||
|
|
// ③ 보스 배너 · 피격 비네트 · 부활 팝업 · 물약 버튼 노드 추가
|
||
|
|
// 실행:
|
||
|
|
// unity command run_script --file AgentScripts/WL813tj_Apply.cs --entry WL813tj_Apply.CreateSettings
|
||
|
|
// unity command run_script --file AgentScripts/WL813tj_Apply.cs --entry WL813tj_Apply.Resave
|
||
|
|
// unity command run_script --file AgentScripts/WL813tj_Apply.cs --entry WL813tj_Apply.ApplySafeArea
|
||
|
|
// unity command run_script --file AgentScripts/WL813tj_Apply.cs --entry WL813tj_Apply.ApplyUi
|
||
|
|
// unity command run_script --file AgentScripts/WL813tj_Apply.cs --entry WL813tj_Apply.Revert
|
||
|
|
// 🔴 run_script 파일은 파일마다 독립 어셈블리 — 다른 AgentScript 상수 참조 불가(813c 교훈).
|
||
|
|
//
|
||
|
|
// ■ Safe Area 를 패널 **2개**로 나누는 이유 (실측 근거 · 완료보고 ⓒ)
|
||
|
|
// NewGameUI 캔버스 직속 12레이어에는 Canvas/sortingOrder 가 하나도 없다(실측: 5레이어 전부 컴포넌트 1~2개,
|
||
|
|
// Canvas 0개) → **그리는 순서 = 형제 순서**다. 대상 5레이어는 원본에서
|
||
|
|
// Common(4) · LobbyUIs(5) < IngameUIs(6) · FarmUIs(7) < MessageInfo(8) · Center(9) · PopupMgr(10) < TestMapUIMgr(11)
|
||
|
|
// 로 **IngameUIs/FarmUIs 를 사이에 끼고 앞뒤로 갈라져 있다**. 5개를 패널 하나에 몰면 앞뒤 관계가 뒤집힌다
|
||
|
|
// (로비 UI 가 인게임 UI 위로 올라오거나, 팝업이 인게임 UI 아래로 내려간다).
|
||
|
|
// 그래서 Back(Common·LobbyUIs) / Front(MessageInfo·Center·PopupMgr) 두 패널을 원래 자리에 끼워
|
||
|
|
// **평탄화하면 원본과 완전히 같은 순서**가 되게 했다.
|
||
|
|
|
||
|
|
using System.Text;
|
||
|
|
using UnityEditor;
|
||
|
|
using UnityEngine;
|
||
|
|
|
||
|
|
public static class WL813tj_Apply
|
||
|
|
{
|
||
|
|
public const string NewGameUIPath = "Assets/Res_Addr/MainUI/NewGameUI.prefab";
|
||
|
|
public const string SettingsDir = "Assets/WL/UI/Settings/Resources/WL";
|
||
|
|
public const string BossSettingsPath = SettingsDir + "/WLBossUiSettings.asset";
|
||
|
|
public const string SurvivalSettingsPath = SettingsDir + "/WLSurvivalUiSettings.asset";
|
||
|
|
|
||
|
|
public const string BackPanel = "WL_SafeArea_Back";
|
||
|
|
public const string FrontPanel = "WL_SafeArea_Front";
|
||
|
|
public static readonly string[] BackLayers = { "Common", "LobbyUIs" };
|
||
|
|
public static readonly string[] FrontLayers = { "MessageInfo", "Center", "PopupMgr" };
|
||
|
|
|
||
|
|
public const string HudPath = "IngameUIs/WL_HUD";
|
||
|
|
public const string PadPath = "IngameUIs/BattleUI";
|
||
|
|
public const string BannerName = "WL_BossBanner";
|
||
|
|
public const string HitName = "WL_HitVignette";
|
||
|
|
public const string ReviveName = "WL_ReviveDialog";
|
||
|
|
public const string PotionName = "WL_PotionButton";
|
||
|
|
const string TmpFontGuid = "a387e325271126742ad15569dba1ac57"; // 813c/813g 가 실측한 원본 TMP 폰트
|
||
|
|
const int UILayer = 5;
|
||
|
|
|
||
|
|
// ── 유틸 ─────────────────────────────────────────────────────────────────
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
static Transform FindAnywhere(Transform root, string name)
|
||
|
|
{
|
||
|
|
for (int i = 0; i < root.childCount; i++)
|
||
|
|
{
|
||
|
|
var c = root.GetChild(i);
|
||
|
|
if (c.name == name) return c;
|
||
|
|
for (int j = 0; j < c.childCount; j++)
|
||
|
|
if (c.GetChild(j).name == name) return c.GetChild(j);
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void EnsureFolder(string dir)
|
||
|
|
{
|
||
|
|
var parts = dir.Split('/');
|
||
|
|
var cur = parts[0];
|
||
|
|
for (int i = 1; i < parts.Length; i++)
|
||
|
|
{
|
||
|
|
var next = cur + "/" + parts[i];
|
||
|
|
if (!AssetDatabase.IsValidFolder(next)) AssetDatabase.CreateFolder(cur, parts[i]);
|
||
|
|
cur = next;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static RectTransform EnsureNode(Transform parent, string name, StringBuilder sb)
|
||
|
|
{
|
||
|
|
var t = parent.Find(name) as RectTransform;
|
||
|
|
if (t == null)
|
||
|
|
{
|
||
|
|
var go = new GameObject(name, typeof(RectTransform));
|
||
|
|
go.layer = UILayer;
|
||
|
|
t = (RectTransform)go.transform;
|
||
|
|
t.SetParent((RectTransform)parent, false);
|
||
|
|
sb.AppendLine(" " + parent.name + "/" + name + " : 노드 추가");
|
||
|
|
}
|
||
|
|
else sb.AppendLine(" " + parent.name + "/" + name + " : 이미 있음");
|
||
|
|
return t;
|
||
|
|
}
|
||
|
|
|
||
|
|
static TMPro.TMP_FontAsset LoadFont(StringBuilder sb)
|
||
|
|
{
|
||
|
|
var p = AssetDatabase.GUIDToAssetPath(TmpFontGuid);
|
||
|
|
var f = string.IsNullOrEmpty(p) ? null : AssetDatabase.LoadAssetAtPath<TMPro.TMP_FontAsset>(p);
|
||
|
|
sb.AppendLine("폰트: " + (f != null ? p : "「미확인」 — TMP 기본 폰트로 떨어진다"));
|
||
|
|
return f;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── ① 설정 에셋 ──────────────────────────────────────────────────────────
|
||
|
|
/// <summary>설정 에셋 2종 생성(이미 있으면 값 유지 · 덮어쓰지 않는다).</summary>
|
||
|
|
public static object CreateSettings()
|
||
|
|
{
|
||
|
|
var sb = new StringBuilder();
|
||
|
|
EnsureFolder(SettingsDir);
|
||
|
|
|
||
|
|
var boss = AssetDatabase.LoadAssetAtPath<WL.UI.WLBossUiSettings>(BossSettingsPath);
|
||
|
|
if (boss == null)
|
||
|
|
{
|
||
|
|
boss = ScriptableObject.CreateInstance<WL.UI.WLBossUiSettings>();
|
||
|
|
AssetDatabase.CreateAsset(boss, BossSettingsPath);
|
||
|
|
sb.AppendLine("생성: " + BossSettingsPath);
|
||
|
|
}
|
||
|
|
else sb.AppendLine("이미 있음(값 유지): " + BossSettingsPath);
|
||
|
|
|
||
|
|
var sur = AssetDatabase.LoadAssetAtPath<WL.UI.WLSurvivalUiSettings>(SurvivalSettingsPath);
|
||
|
|
if (sur == null)
|
||
|
|
{
|
||
|
|
sur = ScriptableObject.CreateInstance<WL.UI.WLSurvivalUiSettings>();
|
||
|
|
AssetDatabase.CreateAsset(sur, SurvivalSettingsPath);
|
||
|
|
sb.AppendLine("생성: " + SurvivalSettingsPath);
|
||
|
|
}
|
||
|
|
else sb.AppendLine("이미 있음(값 유지): " + SurvivalSettingsPath);
|
||
|
|
|
||
|
|
AssetDatabase.SaveAssets();
|
||
|
|
AssetDatabase.Refresh();
|
||
|
|
WL.UI.WLBossUiSettings.ClearCache();
|
||
|
|
WL.UI.WLSurvivalUiSettings.ClearCache();
|
||
|
|
|
||
|
|
sb.AppendLine("── 813t 보스 배너(기준서 §D-1 813t)");
|
||
|
|
sb.AppendLine(" banner=" + boss.bannerSeconds + "s topPx=" + boss.bannerTopMarginPx + " sizePx=" + boss.bannerSizePx +
|
||
|
|
" title=\"" + boss.bannerTitleText + "\" punch=" + boss.bannerPunchScale);
|
||
|
|
sb.AppendLine(" warn=" + boss.warnVignetteSeconds + "s thickPx=" + boss.warnVignetteThicknessPx +
|
||
|
|
" pulses=" + boss.warnVignettePulses + " color=" + boss.warnVignetteColor);
|
||
|
|
sb.AppendLine("── 813j 생존 UI(기준서 §D-1 813j · §B 요소 8)");
|
||
|
|
sb.AppendLine(" 물약 slot=" + sur.potionReserveSlotIndex + " fallback(count=" + sur.potionFallbackCount +
|
||
|
|
" cd=" + sur.potionFallbackCooldownSeconds + "s) requireProvider=" + sur.potionRequireProvider);
|
||
|
|
sb.AppendLine(" 부활 delay=" + sur.reviveDelaySeconds + "s 공용팝업=" + sur.reviveUseCommonPopup +
|
||
|
|
" msg=\"" + sur.reviveMessage + "\" 비용=\"" + sur.reviveCostText + "\"");
|
||
|
|
sb.AppendLine(" 피격 border=" + sur.hitBorderSeconds + "s/" + sur.hitBorderThicknessPx + "px target=" + sur.hitBorderTargetPath +
|
||
|
|
" 무적무시=" + sur.ignoreInvincibleHits + " 스로틀=" + sur.hitMinIntervalSeconds + "s");
|
||
|
|
return sb.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>무변경 재저장 — 프리팹 편집 전에 재직렬화 diff 가 생기는지 먼저 잰다(802b·813c 교훈).</summary>
|
||
|
|
public static object Resave()
|
||
|
|
{
|
||
|
|
var root = PrefabUtility.LoadPrefabContents(NewGameUIPath);
|
||
|
|
try { PrefabUtility.SaveAsPrefabAsset(root, NewGameUIPath); }
|
||
|
|
finally { PrefabUtility.UnloadPrefabContents(root); }
|
||
|
|
AssetDatabase.Refresh();
|
||
|
|
return NewGameUIPath + " : 무변경 재저장 (git diff 로 재직렬화 여부 확인)";
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── ② Safe Area 실효화 ───────────────────────────────────────────────────
|
||
|
|
static RectTransform MakePanel(Transform root, string name, int siblingIndex, StringBuilder sb)
|
||
|
|
{
|
||
|
|
var t = root.Find(name) as RectTransform;
|
||
|
|
if (t == null)
|
||
|
|
{
|
||
|
|
var go = new GameObject(name, typeof(RectTransform));
|
||
|
|
go.layer = UILayer;
|
||
|
|
t = (RectTransform)go.transform;
|
||
|
|
t.SetParent((RectTransform)root, false);
|
||
|
|
sb.AppendLine(name + " : 패널 추가");
|
||
|
|
}
|
||
|
|
else sb.AppendLine(name + " : 이미 있음");
|
||
|
|
|
||
|
|
t.anchorMin = Vector2.zero; t.anchorMax = Vector2.one;
|
||
|
|
t.offsetMin = Vector2.zero; t.offsetMax = Vector2.zero;
|
||
|
|
t.pivot = new Vector2(0.5f, 0.5f);
|
||
|
|
t.localScale = Vector3.one;
|
||
|
|
t.localPosition = new Vector3(0f, 0f, 0f);
|
||
|
|
if (t.GetComponent<WL.UI.SafeAreaFitter>() == null)
|
||
|
|
{
|
||
|
|
t.gameObject.AddComponent<WL.UI.SafeAreaFitter>();
|
||
|
|
sb.AppendLine(" SafeAreaFitter 부착");
|
||
|
|
}
|
||
|
|
if (siblingIndex >= 0) t.SetSiblingIndex(Mathf.Min(siblingIndex, root.childCount - 1));
|
||
|
|
return t;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static object ApplySafeArea()
|
||
|
|
{
|
||
|
|
var sb = new StringBuilder();
|
||
|
|
var root = PrefabUtility.LoadPrefabContents(NewGameUIPath);
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var rt = root.transform;
|
||
|
|
sb.AppendLine("── 적용 전 캔버스 루트 순서");
|
||
|
|
sb.AppendLine(" " + Order(rt));
|
||
|
|
|
||
|
|
// Back 패널 = 원래 Common 이 있던 자리
|
||
|
|
int backAt = IndexOf(rt, BackLayers[0]);
|
||
|
|
if (backAt < 0) return "🔴 " + BackLayers[0] + " 없음 — 중단";
|
||
|
|
var back = MakePanel(rt, BackPanel, backAt, sb);
|
||
|
|
foreach (var n in BackLayers) Reparent(rt, n, back, sb);
|
||
|
|
|
||
|
|
// Front 패널 = 원래 MessageInfo 가 있던 자리(Back 이동으로 인덱스가 당겨진 뒤 다시 잰다)
|
||
|
|
int frontAt = IndexOf(rt, FrontLayers[0]);
|
||
|
|
if (frontAt < 0) return "🔴 " + FrontLayers[0] + " 없음 — 중단";
|
||
|
|
var front = MakePanel(rt, FrontPanel, frontAt, sb);
|
||
|
|
foreach (var n in FrontLayers) Reparent(rt, n, front, sb);
|
||
|
|
|
||
|
|
sb.AppendLine("── 적용 후 캔버스 루트 순서(children=" + rt.childCount + ")");
|
||
|
|
sb.AppendLine(" " + Order(rt));
|
||
|
|
sb.AppendLine("── 평탄화(패널을 펼친 순서) = 원본과 같아야 한다");
|
||
|
|
sb.AppendLine(" " + Flatten(rt));
|
||
|
|
|
||
|
|
PrefabUtility.SaveAsPrefabAsset(root, NewGameUIPath);
|
||
|
|
}
|
||
|
|
finally { PrefabUtility.UnloadPrefabContents(root); }
|
||
|
|
AssetDatabase.SaveAssets();
|
||
|
|
AssetDatabase.Refresh();
|
||
|
|
return sb.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
static int IndexOf(Transform parent, string name)
|
||
|
|
{
|
||
|
|
for (int i = 0; i < parent.childCount; i++) if (parent.GetChild(i).name == name) return i;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void Reparent(Transform root, string name, RectTransform panel, StringBuilder sb)
|
||
|
|
{
|
||
|
|
var t = root.Find(name) as RectTransform;
|
||
|
|
if (t == null)
|
||
|
|
{
|
||
|
|
if (panel.Find(name) != null) { sb.AppendLine(" " + name + " : 이미 " + panel.name + " 아래"); return; }
|
||
|
|
sb.AppendLine(" 🔴 " + name + " 없음");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
var before = new { a0 = t.anchorMin, a1 = t.anchorMax, p = t.anchoredPosition, s = t.sizeDelta, sc = t.localScale, z = t.localPosition.z, pv = t.pivot };
|
||
|
|
t.SetParent(panel, false); // worldPositionStays=false → 로컬 값 그대로 보존
|
||
|
|
t.SetAsLastSibling();
|
||
|
|
bool same = before.a0 == t.anchorMin && before.a1 == t.anchorMax && before.p == t.anchoredPosition &&
|
||
|
|
before.s == t.sizeDelta && before.sc == t.localScale && Mathf.Approximately(before.z, t.localPosition.z) &&
|
||
|
|
before.pv == t.pivot;
|
||
|
|
sb.AppendLine(" " + name + " → " + panel.name + " (보존=" + same + " aMin" + t.anchorMin + " aMax" + t.anchorMax +
|
||
|
|
" off" + t.offsetMin + t.offsetMax + " scale" + t.localScale + " z=" + t.localPosition.z + ")");
|
||
|
|
}
|
||
|
|
|
||
|
|
static string Order(Transform t)
|
||
|
|
{
|
||
|
|
var sb = new StringBuilder();
|
||
|
|
for (int i = 0; i < t.childCount; i++) { if (i > 0) sb.Append(" · "); sb.Append(i).Append(':').Append(t.GetChild(i).name); }
|
||
|
|
return sb.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
static string Flatten(Transform t)
|
||
|
|
{
|
||
|
|
var sb = new StringBuilder();
|
||
|
|
int k = 0;
|
||
|
|
for (int i = 0; i < t.childCount; i++)
|
||
|
|
{
|
||
|
|
var c = t.GetChild(i);
|
||
|
|
if (c.name.StartsWith("WL_SafeArea"))
|
||
|
|
{
|
||
|
|
for (int j = 0; j < c.childCount; j++) { if (k++ > 0) sb.Append(" · "); sb.Append(c.GetChild(j).name); }
|
||
|
|
}
|
||
|
|
else { if (k++ > 0) sb.Append(" · "); sb.Append(c.name); }
|
||
|
|
}
|
||
|
|
return sb.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── ③ UI 노드 ────────────────────────────────────────────────────────────
|
||
|
|
public static object ApplyUi()
|
||
|
|
{
|
||
|
|
var sb = new StringBuilder();
|
||
|
|
var boss = AssetDatabase.LoadAssetAtPath<WL.UI.WLBossUiSettings>(BossSettingsPath);
|
||
|
|
var sur = AssetDatabase.LoadAssetAtPath<WL.UI.WLSurvivalUiSettings>(SurvivalSettingsPath);
|
||
|
|
if (boss == null || sur == null) return "🔴 설정 에셋 없음 — CreateSettings 먼저";
|
||
|
|
var font = LoadFont(sb);
|
||
|
|
|
||
|
|
var root = PrefabUtility.LoadPrefabContents(NewGameUIPath);
|
||
|
|
try
|
||
|
|
{
|
||
|
|
// ── 813t + 813j 화면 연출 = IngameUIs/WL_HUD (802b SafeAreaFitter 갈래 · 813c/813g 규칙)
|
||
|
|
var hud = FindByPath(root.transform, HudPath);
|
||
|
|
if (hud == null) sb.AppendLine("🔴 " + HudPath + " 없음");
|
||
|
|
else
|
||
|
|
{
|
||
|
|
var banner = EnsureNode(hud, BannerName, sb);
|
||
|
|
var bc = banner.GetComponent<WL.UI.BossBanner>();
|
||
|
|
if (bc == null) { bc = banner.gameObject.AddComponent<WL.UI.BossBanner>(); sb.AppendLine(" BossBanner 추가"); }
|
||
|
|
if (font != null) bc.SetFont(font);
|
||
|
|
sb.AppendLine(" build made=" + bc.BuildIfNeeded() + " · " + bc.ApplyLayout());
|
||
|
|
bc.HideNow();
|
||
|
|
|
||
|
|
var hit = EnsureNode(hud, HitName, sb);
|
||
|
|
var hc = hit.GetComponent<WL.UI.HitVignette>();
|
||
|
|
if (hc == null) { hc = hit.gameObject.AddComponent<WL.UI.HitVignette>(); sb.AppendLine(" HitVignette 추가"); }
|
||
|
|
sb.AppendLine(" build made=" + hc.BuildIfNeeded() + " · " + hc.ApplyLayout());
|
||
|
|
hc.HideNow(); // HP 바 테두리는 런타임(EnsureBorder)에서 만든다 = 프리팹 diff 0
|
||
|
|
|
||
|
|
var rev = EnsureNode(hud, ReviveName, sb);
|
||
|
|
var rc = rev.GetComponent<WL.UI.ReviveDialog>();
|
||
|
|
if (rc == null) { rc = rev.gameObject.AddComponent<WL.UI.ReviveDialog>(); sb.AppendLine(" ReviveDialog 추가"); }
|
||
|
|
if (font != null) rc.SetFont(font);
|
||
|
|
sb.AppendLine(" build made=" + rc.BuildIfNeeded() + " · " + rc.ApplyLayout());
|
||
|
|
rc.HideNow();
|
||
|
|
rev.SetAsLastSibling(); // 폴백 팝업은 HUD 최상단
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── 813j 물약 버튼 = IngameUIs/BattleUI 의 813c 예약 슬롯 자리
|
||
|
|
var pad = FindByPath(root.transform, PadPath);
|
||
|
|
if (pad == null) sb.AppendLine("🔴 " + PadPath + " 없음");
|
||
|
|
else
|
||
|
|
{
|
||
|
|
var pot = EnsureNode(pad, PotionName, sb);
|
||
|
|
var pc = pot.GetComponent<WL.UI.PotionButton>();
|
||
|
|
if (pc == null) { pc = pot.gameObject.AddComponent<WL.UI.PotionButton>(); sb.AppendLine(" PotionButton 추가"); }
|
||
|
|
if (font != null) pc.SetFont(font);
|
||
|
|
sb.AppendLine(" build made=" + pc.BuildIfNeeded() + " · " + pc.ApplyLayout());
|
||
|
|
sb.AppendLine(" refresh " + pc.Refresh());
|
||
|
|
}
|
||
|
|
|
||
|
|
PrefabUtility.SaveAsPrefabAsset(root, NewGameUIPath);
|
||
|
|
}
|
||
|
|
finally { PrefabUtility.UnloadPrefabContents(root); }
|
||
|
|
AssetDatabase.SaveAssets();
|
||
|
|
AssetDatabase.Refresh();
|
||
|
|
return sb.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── 롤백 ─────────────────────────────────────────────────────────────────
|
||
|
|
public static object Revert()
|
||
|
|
{
|
||
|
|
var sb = new StringBuilder();
|
||
|
|
var root = PrefabUtility.LoadPrefabContents(NewGameUIPath);
|
||
|
|
try
|
||
|
|
{
|
||
|
|
// UI 노드
|
||
|
|
var hud = FindByPath(root.transform, HudPath);
|
||
|
|
if (hud != null)
|
||
|
|
foreach (var n in new[] { BannerName, HitName, ReviveName })
|
||
|
|
{
|
||
|
|
var t = hud.Find(n);
|
||
|
|
if (t != null) { Object.DestroyImmediate(t.gameObject); sb.AppendLine(HudPath + "/" + n + " : 제거"); }
|
||
|
|
}
|
||
|
|
var pad = FindByPath(root.transform, PadPath);
|
||
|
|
if (pad != null)
|
||
|
|
{
|
||
|
|
var t = pad.Find(PotionName);
|
||
|
|
if (t != null) { Object.DestroyImmediate(t.gameObject); sb.AppendLine(PadPath + "/" + PotionName + " : 제거"); }
|
||
|
|
}
|
||
|
|
|
||
|
|
// Safe Area 패널 — 자식을 원래 자리로 되돌리고 패널을 지운다
|
||
|
|
var rt = root.transform;
|
||
|
|
RestorePanel(rt, BackPanel, sb);
|
||
|
|
RestorePanel(rt, FrontPanel, sb);
|
||
|
|
sb.AppendLine("복원 후 순서: " + Order(rt));
|
||
|
|
|
||
|
|
PrefabUtility.SaveAsPrefabAsset(root, NewGameUIPath);
|
||
|
|
}
|
||
|
|
finally { PrefabUtility.UnloadPrefabContents(root); }
|
||
|
|
AssetDatabase.SaveAssets();
|
||
|
|
AssetDatabase.Refresh();
|
||
|
|
return sb.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
static void RestorePanel(Transform root, string panelName, StringBuilder sb)
|
||
|
|
{
|
||
|
|
var panel = root.Find(panelName) as RectTransform;
|
||
|
|
if (panel == null) { sb.AppendLine(panelName + " : 없음"); return; }
|
||
|
|
int at = panel.GetSiblingIndex();
|
||
|
|
while (panel.childCount > 0)
|
||
|
|
{
|
||
|
|
var c = panel.GetChild(0) as RectTransform;
|
||
|
|
c.SetParent(root as RectTransform, false);
|
||
|
|
c.SetSiblingIndex(at++);
|
||
|
|
sb.AppendLine(" " + c.name + " : 루트로 복원 @" + (at - 1));
|
||
|
|
}
|
||
|
|
Object.DestroyImmediate(panel.gameObject);
|
||
|
|
sb.AppendLine(panelName + " : 패널 제거");
|
||
|
|
}
|
||
|
|
}
|