#!/usr/bin/env python3 """ 从 Unity Assets/Tile/{theme}.prefab + Assets/Texture/{theme} 生成 Cocos 调色板配置。 对齐 Unity 平铺调色板(如 sanxing:WallBlock / JumpBlock / Baseblock / kuai11)。 """ from __future__ import annotations import json import re from pathlib import Path # Unity 目录名 → Cocos / GameController 主题名 THEMES = { "SILU": "silu", "snow": "snow", "sanxing": "sanxing", "Chinese": "chinese", "numMan": "numMan", "redArmy": "redarmy", "RED": "redArmy", "Level": "default", } GROUND_NAMES = {"Baseblock", "JumpBlock"} BORDER_NAMES = {"WallBlock", "kuai11", "Decor23", "素材切图-23", "素材切图2-23", "小游戏素材红色_03"} def parse_palette_guids(prefab_text: str) -> list[str]: guids: list[str] = [] in_array = False for line in prefab_text.splitlines(): if "m_TileAssetArray:" in line: in_array = True continue if in_array and "m_TileSpriteArray:" in line: break if in_array and "guid:" in line: m = re.search(r"guid: ([a-f0-9]+)", line) if m: guids.append(m.group(1)) return guids def read_meta_guid(meta_path: Path) -> str | None: try: for line in meta_path.read_text(encoding="utf-8").splitlines(): if line.startswith("guid:"): return line.split(":", 1)[1].strip() except Exception: pass return None def guid_to_tile_name(theme_dir: Path, guid: str) -> str | None: if not theme_dir.is_dir(): return None for meta in theme_dir.glob("*.asset.meta"): if read_meta_guid(meta) == guid: return meta.name.replace(".asset.meta", "") return None def build_theme(unity_root: Path, unity_folder: str, cocos_key: str) -> dict | None: tile_prefab = unity_root / "Assets" / "Tile" / f"{unity_folder}.prefab" tex_dir = unity_root / "Assets" / "Texture" / unity_folder if unity_folder == "Level": tex_dir = unity_root / "Assets" / "Texture" if not tile_prefab.is_file(): return None guids = parse_palette_guids(tile_prefab.read_text(encoding="utf-8")) tiles = [] for i, g in enumerate(guids): name = guid_to_tile_name(tex_dir, g) if not name: continue layer = "ground" if name in GROUND_NAMES else "border" tex_rel = f"textures/{cocos_key}/{name}" if cocos_key == "default": tex_rel = f"textures/default/{name}" tiles.append( { "display": name, "layer": layer, "tileKey": name, "texture": tex_rel, "unityIndex": i, } ) return {"displayName": cocos_key, "tiles": tiles} def main(): import argparse ap = argparse.ArgumentParser() ap.add_argument("--unity-root", required=True) ap.add_argument("--out", default="assets/resources/map-tiles/palettes") args = ap.parse_args() project = Path(__file__).resolve().parent.parent unity_root = Path(args.unity_root) out_dir = project / args.out out_dir.mkdir(parents=True, exist_ok=True) all_themes: dict[str, dict] = {} for unity_folder, cocos_key in THEMES.items(): t = build_theme(unity_root, unity_folder, cocos_key) if not t or not t["tiles"]: print(f" skip {unity_folder}") continue all_themes[cocos_key] = t (out_dir / f"{cocos_key}.json").write_text( json.dumps(t, indent=2, ensure_ascii=False), encoding="utf-8" ) print(f" {cocos_key}: {len(t['tiles'])} tiles") (out_dir / "_index.json").write_text( json.dumps({"themes": all_themes}, indent=2, ensure_ascii=False), encoding="utf-8" ) print(f"Wrote -> {out_dir}") if __name__ == "__main__": main()