Add AIServer, character art pipeline, and Art package boot integration.

Bring in MaleExplorer assets/shaders, model tooling and Hunyuan updates, plus boot/YooAsset Art package support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
udx
2026-09-21 17:06:59 +08:00
co-authored by Cursor
parent b7a0bbcb89
commit 6550b8df4b
121 changed files with 313260 additions and 113 deletions
+55 -1
View File
@@ -117,6 +117,7 @@ def run_pipeline(
ray_distance: Optional[float] = None,
blender: Optional[str] = None,
keep_low: bool = True,
xpbr: bool = True,
callback_url: Optional[str] = None,
callback_file: Optional[str] = None,
quiet: bool = False,
@@ -211,6 +212,26 @@ def run_pipeline(
blender_args=("-t", "1"),
)
xpbr_dir = None
xpbr_summary = None
if xpbr:
callbacks.emit("stage", stage="打包 XPbr base/mix 贴图与材质", progress=88)
from model_translator import translate_fbx
bake_fbx = bake_dir / bake["fbx"]
xpbr_dir = out_dir / f"{stem}_xpbr"
xpbr_summary = translate_fbx(
str(bake_fbx), str(xpbr_dir), max_size=size, blender=blender_exe
)
callbacks.emit(
"xpbr",
stage="XPbr 资源已生成",
progress=95,
outdir=str(xpbr_dir),
fbx=xpbr_summary.get("fbx"),
materials=[m.get("name") for m in xpbr_summary.get("materials") or []],
)
result = {
"ok": True,
"status": "succeeded",
@@ -220,13 +241,28 @@ def run_pipeline(
"bake_dir": str(bake_dir),
"fbx": str(bake_dir / bake["fbx"]),
"maps": {k: str(bake_dir / v) for k, v in bake["outputs"].items()},
"xpbr_dir": str(xpbr_dir) if xpbr_dir else None,
"xpbr": (
{
"fbx": str(xpbr_dir / xpbr_summary["fbx"]),
"materials": xpbr_summary.get("materials"),
}
if xpbr_summary and xpbr_dir
else None
),
"tris_before": dec["tris_before"],
"tris_after": bake["low_tris"],
"high_tris": bake["high_tris"],
"size": size,
"ray_distance": bake["ray_distance"],
"warnings": list(dec.get("warnings") or []) + list(bake.get("warnings") or []),
"hint": "生成完成后请在 Doc/ResDesc_Model.md 登记该资源",
"hint": (
"XPbr 目录可拷进 AIClient/Assets;"
"预设用 Unity 菜单 AIGame/M3/Setup Character Prefab + Art Collector;"
"并登记 Doc/ResDesc_Model.md"
if xpbr
else "生成完成后请在 Doc/ResDesc_Model.md 登记该资源"
),
}
callbacks.emit("succeeded", **result)
return result
@@ -251,6 +287,19 @@ def build_parser() -> argparse.ArgumentParser:
p.add_argument("--max-overlap", type=float, default=None, help="UV 重叠容忍 (0,1]")
p.add_argument("--ray-distance", type=float, default=None, help="烘焙射线距离")
p.add_argument("--blender", default=None, help="blender.exe 路径")
p.add_argument(
"--xpbr",
dest="xpbr",
action="store_true",
default=True,
help="烘焙后打包 XPbr base/mix + .mat(默认开启)",
)
p.add_argument(
"--no-xpbr",
dest="xpbr",
action="store_false",
help="跳过 XPbr 打包,只保留五通道烘焙图",
)
p.add_argument(
"--callback-url", default=None, help="流程回调 URL:每个事件 POST JSON"
)
@@ -300,6 +349,11 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
else args.ray_distance
),
blender=payload.get("blender") or args.blender,
xpbr=bool(
payload["xpbr"]
if "xpbr" in payload
else args.xpbr
),
callback_url=payload.get("callback_url") or args.callback_url,
callback_file=payload.get("callback_file") or args.callback_file,
quiet=quiet,