115 lines
6.9 KiB
C#
115 lines
6.9 KiB
C#
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; // 兜底
|
||
}
|
||
}
|