Files
AIGame/Tools/run_battlefield_scene_pipeline.py

97 lines
4.0 KiB
Python

"""Run the four authored stages of the battlefield scene workflow.
The command is deliberately an orchestrator: it owns stage ordering and
status checks, while image/model/Unity work remains in the existing tools.
Existing Unity component prefabs are reused by default during stage 2.
"""
from __future__ import annotations
import argparse
import json
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
MANIFEST = ROOT / "Doc/Design/Scene/Battlefield/battlefield_scene_manifest.json"
def load_manifest() -> dict:
return json.loads(MANIFEST.read_text(encoding="utf-8-sig"))
def design_ready(data: dict, design_id: str) -> bool:
option = next((x for x in data.get("designOptions", []) if x.get("id") == design_id), None)
generation = (option or {}).get("generation", {})
return generation.get("model") == "gpt-image-2.5" and generation.get("status") == "generated"
def run(command: list[str], dry_run: bool) -> None:
print("$", " ".join(f'"{part}"' if " " in part else part for part in command))
if not dry_run:
subprocess.run(command, cwd=ROOT, check=True)
def unity_command(entry: str) -> list[str]:
return [
"unity",
"command",
"--project-path",
str(ROOT / "AIClient"),
"run_script",
"--file",
"AgentScripts/BuildSceneReview.cs",
"--entry",
entry,
]
def main() -> int:
parser = argparse.ArgumentParser(description="Orchestrate design -> component sheets -> model plan -> Unity scene review")
parser.add_argument("--design", choices=["A", "B", "C"], required=True)
parser.add_argument("--dry-run", action="store_true", help="只打印阶段命令,不调用图像服务或 Unity")
parser.add_argument("--force-design", action="store_true", help="即使总览图已存在也重新生成")
parser.add_argument("--force-new-components", action="store_true", help="不复用已有组件,重新生成组件设计图")
parser.add_argument("--run-unity", action="store_true", help="阶段 4 直接调用已运行的 Unity Editor")
args = parser.parse_args()
data = load_manifest()
print("[1/4] 生成关卡总览设计图并等待选择")
if args.force_design or not design_ready(data, args.design):
command = [sys.executable, str(ROOT / "Tools/generate_battlefield_designs.py"), "--design", args.design]
if args.dry_run:
command.append("--dry-run")
run(command, args.dry_run)
else:
print(f"reuse overview: design {args.design} is already generated")
if not args.dry_run:
run([sys.executable, str(ROOT / "Tools/battlefield_scene_pipeline.py"), "select", args.design], False)
print("[2/4] 按总览图拆分地表和组件设计图(已有组件默认复用)")
command = [sys.executable, str(ROOT / "Tools/generate_battlefield_components.py"), "--design", args.design]
if args.dry_run:
command.append("--dry-run")
if args.force_new_components:
command.append("--force-new-components")
run(command, args.dry_run)
print("[3/4] 3D 模型生成与低模烘焙")
print("新组件默认:分件图 -> 混元 50k 高模 -> Studio 低模 -> Studio UV -> Blender 烘焙 -> 超目标 130% 时保留 UV 减面。")
print("组件图审核后,用 Tools/scene_component_pipeline.py --manifest <场景manifest> --part <组件id> 执行;--dry-run 只查看计划。")
print("高模先由 Tools/hunyuan_3d_generate.py 完成;已有 Prefab 可复用,历史已完成模型不自动重做。")
print("模型未登记到 manifest 前不会进入 Unity 场景阶段。")
print("[4/4] Unity 场景生成与人工审核")
print("$", " ".join(unity_command("BuildSceneReview.BuildAndOpenReview")))
if args.run_unity:
run(unity_command("BuildSceneReview.BuildAndOpenReview"), False)
else:
print("use --run-unity after the model stage, with Unity Editor and Pipeline running")
return 0
if __name__ == "__main__":
raise SystemExit(main())