#!/usr/bin/env python3 """把 dgx3d_animal_pipeline 产物拷进 Unity Bundles(Rigged + Anims)。""" from __future__ import annotations import argparse import json import shutil from pathlib import Path def main() -> int: ap = argparse.ArgumentParser() ap.add_argument( "-m", "--manifest", type=Path, required=True, help="Tools/output/{name}_dgx/{Name}_manifest.json", ) ap.add_argument( "--kind", default="Animal", help="Characters/{kind}/{Name}", ) args = ap.parse_args() man = json.loads(args.manifest.read_text(encoding="utf-8")) name = man["name"] dest_root = Path(f"AIClient/Assets/Bundles/Characters/{args.kind}/{name}") rigged_dir = dest_root / "Rigged" anim_dir = dest_root / "Anims" rigged_dir.mkdir(parents=True, exist_ok=True) anim_dir.mkdir(parents=True, exist_ok=True) src_fbx = Path(man["rigged_fbx"]) if not src_fbx.is_file(): raise SystemExit(f"missing {src_fbx}") dest_fbx = rigged_dir / f"{name}_Rigged.fbx" shutil.copy2(src_fbx, dest_fbx) # Copy sibling textures next to model.fbx if present src_dir = src_fbx.parent for tex in list(src_dir.glob("*.png")) + list(src_dir.glob("*.jpg")): shutil.copy2(tex, rigged_dir / tex.name) copied = {"rigged": str(dest_fbx), "anims": {}} for clip, rel in (man.get("anims") or {}).items(): src = Path(rel) if not src.is_file(): # try relative to manifest parent / out root alt = args.manifest.parent / rel src = alt if alt.is_file() else src if not src.is_file(): raise SystemExit(f"missing anim {clip}: {rel}") dest = anim_dir / f"{name}_{clip}.fbx" shutil.copy2(src, dest) copied["anims"][clip] = str(dest) out = { "ok": True, "dest": str(dest_root), "files": copied, "next": ( f'unity command --project-path D:/UD/AI/AIGame/AIClient run_script ' f'--file AgentScripts/SetupAnimalAnimator.cs --entry {man.get("setup_entry", "SetupAnimalAnimator.Setup" + name)}' ), "postprocess": man.get("postprocess", []), } print(json.dumps(out, ensure_ascii=False, indent=2)) return 0 if __name__ == "__main__": raise SystemExit(main())