97 lines
4.0 KiB
Python
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())
|