Files
5.24BuYu/Assets/MyGame/Editor/BakeLobbySlicesTool.cs
T
2026-10-20 18:30:03 +08:00

115 lines
6.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Text.RegularExpressions;
/// <summary>
/// 大厅图集切片烘焙工具(绕开 TextureImporter 管线,纯 Unity API):
/// 1. 读取 NGUI 图集 prefab 的 mSprites 坐标
/// 2. Sprite.Create 从大图切出 56 个 sprite,AssetDatabase.CreateAsset 落盘
/// 3. 大厅 prefab 里 108 个 Image 按节点语义规则重绑切片
/// 菜单:Tools / 烘焙大厅图集切片
/// </summary>
public static class BakeLobbySlicesTool
{
const string AtlasPrefabPath = "Assets/dataresources/atlas/a大厅/atlas_bylobbyclassic/Atlas_ByLobbyClassic.prefab";
const string AtlasTexPath = "Assets/dataresources/atlas/a大厅/atlas_bylobbyclassic/Atlas_ByLobbyClassic.png";
const string OutDir = "Assets/BakeLobbySlicesAssets";
const string LobbyPrefabPath = "Assets/bundles/by_lobby/bundles/panel/BY_LbPlayMainUGUIPanel.prefab";
[MenuItem("Tools/烘焙大厅图集切片")]
public static void Bake()
{
// ---------- 1. 读图集坐标 ----------
var atlasObj = AssetDatabase.LoadAssetAtPath<Object>(AtlasPrefabPath);
if (atlasObj == null) { Debug.LogError("[烘焙] 图集 prefab 加载失败: " + AtlasPrefabPath); return; }
var so = new SerializedObject(atlasObj);
var mSprites = so.FindProperty("mSprites");
if (mSprites == null || !mSprites.isArray || mSprites.arraySize == 0)
{ Debug.LogError("[烘焙] mSprites 读取失败 (arraySize=" + (mSprites == null ? -1 : mSprites.arraySize) + ")"); return; }
var tex = AssetDatabase.LoadAssetAtPath<Texture2D>(AtlasTexPath);
if (tex == null) { Debug.LogError("[烘焙] 大图加载失败,请先等 Unity 刷新完成: " + AtlasTexPath); return; }
Debug.Log($"[烘焙] 图集 {mSprites.arraySize} 切片, 大图 {tex.width}x{tex.height}");
// ---------- 2. 切片落盘 ----------
if (!AssetDatabase.IsValidFolder(OutDir)) AssetDatabase.CreateFolder("Assets", "BakeLobbySlicesAssets");
var made = new Dictionary<string, Sprite>();
for (int i = 0; i < mSprites.arraySize; i++)
{
var el = mSprites.GetArrayElementAtIndex(i);
string name = el.FindPropertyRelative("name").stringValue;
var rect = new Rect(el.FindPropertyRelative("x").floatValue, el.FindPropertyRelative("y").floatValue,
el.FindPropertyRelative("width").floatValue, el.FindPropertyRelative("height").floatValue);
var border = new Vector4(el.FindPropertyRelative("borderLeft").floatValue, el.FindPropertyRelative("borderBottom").floatValue,
el.FindPropertyRelative("borderRight").floatValue, el.FindPropertyRelative("borderTop").floatValue);
var sp = Sprite.Create(tex, rect, new Vector2(0.5f, 0.5f), 100f, 0, SpriteMeshType.FullRect, border);
sp.name = name;
var path = $"{OutDir}/{name}.asset";
AssetDatabase.DeleteAsset(path);
AssetDatabase.CreateAsset(sp, path);
made[name] = sp;
}
Debug.Log($"[烘焙] 生成 {made.Count} 个 sprite asset → {OutDir}");
// ---------- 3. 重绑大厅 prefab ----------
var root = PrefabUtility.LoadPrefabContents(LobbyPrefabPath);
int bound = 0, missing = 0;
try
{
var images = root.GetComponentsInChildren<UnityEngine.UI.Image>(true);
foreach (var img in images)
{
var sp = PickSlice(img.gameObject.name, made);
if (sp != null) { img.sprite = sp; bound++; }
else missing++;
}
PrefabUtility.SaveAsPrefabAsset(root, LobbyPrefabPath);
}
finally { PrefabUtility.UnloadPrefabContents(root); }
Debug.Log($"[烘焙] prefab 重绑 {bound} 个 Image, 未匹配 {missing} 个 —— 完成!");
}
// 节点名 → 切片(与此前 Python 修复用的语义规则一致,最后有兜底)
static Sprite PickSlice(string n, Dictionary<string, Sprite> m)
{
string s = null;
if (Regex.IsMatch(n, @"Frame_bg$")) s = "topbar_frame";
else if (n.Contains("Frame_lobby")) s = "topbar_def2";
else if (n.Contains("topbar_btn")) s = "topbar_btn";
else if (n.Contains("BtnClassic") || n == "Classic") s = "ic_tab_n1";
else if (n.Contains("BtnSuper") || n == "Super") s = "ic_tab_n2";
else if (n.Contains("BtnSiuxian") || n == "Siuxian") s = "ic_tab_n3";
else if (n.Contains("BtnFold")) s = "ic_tab_n4";
else if (n.StartsWith("tab_sel")) s = "tab_sel1";
else if (n.Contains("tab_bg")) s = "tab_bg";
else if (n.Contains("share_btn_bg")) s = "nor_frame_b";
else if (n.Contains("icon_more")) s = "icon_more";
else if (n.Contains("redDot")) s = "com_redDot";
else if (n.Contains("arrow") || n.Contains("jiantou")) s = "arrow";
else if (n == "bg_arrow") s = "bg_arrow";
else if (Regex.IsMatch(n, @"^(gem|gold|money|energy|bp)_bg")) s = "icon_bg";
else if (n.EndsWith("_spr")) s = "icon_bg2";
else if (n.Contains("headIcon")) s = "s_frame_p";
else if (n.Contains("player_level") || n.Contains("vip_spr")) s = "s_frame_r";
else if (n.EndsWith("_btn")) s = "btn";
else if (n.Contains("Frame") || n.Contains("frame")) s = "nor_frame_b2";
else if (n.StartsWith("eff_") || n.Contains("_eff")) s = "effect_1";
else if (n.Contains("lizi") || n.Contains("glow") || n.Contains("star") || n.Contains("sanguang")) s = "tx_mask";
else if (Regex.IsMatch(n, @"^bg( \(\d+\))?$")) s = "nor_frame_b";
else if (Regex.IsMatch(n, @"^Background( \(\d+\))?$")) s = "nor_frame_b2";
else if (n.Contains("ContentRoot")) s = "icon_bg";
else if (n.Contains("GodGuardTab") || n.Contains("ActivityCenter")) s = "tab_bg02";
else if (n.Contains("propIcon")) s = "icon_bg3";
else if (n.Contains("propTip")) s = "ls_txk_1";
else if (n.Contains("setup_bg")) s = "icon_bg3";
else if (n.Contains("musicOpen")) s = "icon_cardSystem_Bubble01";
else if (n.Contains("hlby_") || n.Contains("hong_spr")) s = "icon_cardSystem_Bubble02";
else if (n == "zi" || n.Contains("Label") || n.EndsWith("lab")) s = "txt_y_1";
else if (Regex.IsMatch(n, @"^Sprite( \(\d+\))?$")) s = "icon_bg2";
if (s != null && m.ContainsKey(s)) return m[s];
return m.ContainsKey("icon_bg2") ? m["icon_bg2"] : null; // 兜底
}
}