Files
ChildHood/tools/asset-catalog/run_all.py
T
starmen1265 9f6572600b feat(tools): 添加UE5资产探索脚本系统asset-catalog
- discover_assets: 枚举Content资产,按UE5类型分类,输出index.json
- analyze_meshes: 包围盒/锚点/bbox_faces(area+orientation)/Line Trace细节包围盒/规则Tags
- analyze_materials: 动态参数提取/base_color_hex自动转换/规则Tags
- analyze_blueprints: generated_class API Actor检测/组件提取/interaction推断Tags
- run_all编排器: 断点续跑/步骤控制/错误traceback/UE5 JSON序列化兼容
- probe脚本: UE5.7 API探测(TraceTypeQuery/DrawDebugTrace枚举发现)
2026-06-09 19:01:50 +08:00

214 lines
6.1 KiB
Python

"""UE5 资产探索编排器。
在单次 UE5 编辑器会话内顺序执行所有分析步骤。
步骤:
1. discover — 资产发现
2. mesh — 模型几何提取
3. material — 材质参数提取
4. blueprint — 蓝图结构提取
通过 AC_STEPS 环境变量控制执行哪些步骤(逗号分隔)。
默认全部执行。
环境变量(由 run_all.bat 设置):
AC_SCAN_ROOT — 扫描路径
AC_OUTPUT_DIR — 输出目录
AC_NO_QUIT — 是否不退出
AC_STEPS — 步骤列表
AC_PROJECT_ROOT — 项目根目录(用于 sys.path)
"""
import json
import os
import sys
import time
from pathlib import Path
# ---- sys.path 设置 ----
_SCRIPT_DIR = Path(__file__).resolve().parent
if str(_SCRIPT_DIR) not in sys.path:
sys.path.insert(0, str(_SCRIPT_DIR))
# 项目根目录
_project_root = os.environ.get("AC_PROJECT_ROOT", "")
if _project_root:
PROJECT_ROOT = Path(_project_root)
else:
PROJECT_ROOT = _SCRIPT_DIR.parent.parent
# ---- Unreal import ----
try:
import unreal
HAS_UNREAL = True
except ImportError:
HAS_UNREAL = False
print("[AssetCatalog] 错误: unreal 模块不可用,必须在 UE5 环境中运行")
sys.exit(1)
from _common import (
get_scan_root, get_output_dir, get_steps, should_no_quit,
write_json, wait_for_editor, quit_editor, iso_now,
)
TAG = "[AssetCatalog]"
def run():
"""主流程:顺序执行所有启用的步骤。"""
print(f"{TAG} {'=' * 50}")
print(f"{TAG} UE5 资产探索工具")
print(f"{TAG} {'=' * 50}")
scan_root = get_scan_root()
output_dir = get_output_dir()
steps = get_steps()
print(f"{TAG} 扫描路径: {scan_root}")
print(f"{TAG} 输出目录: {output_dir}")
print(f"{TAG} 执行步骤: {', '.join(steps)}")
print(f"{TAG}")
# 确保输出目录存在
output_dir.mkdir(parents=True, exist_ok=True)
# 等待编辑器就绪
if not wait_for_editor():
print(f"{TAG} 错误: 编辑器初始化超时")
return
log = {
"started_at": iso_now(),
"scan_root": scan_root,
"output_dir": str(output_dir),
"steps": [],
}
index_data = None
# ---- Step 0: Discover ----
if "discover" in steps:
print(f"\n{TAG} {'-' * 40}")
print(f"{TAG} Step 0: Discover")
print(f"{TAG} {'-' * 40}")
t0 = time.time()
from discover_assets import run as run_discover
result = run_discover()
elapsed = time.time() - t0
result["elapsed_sec"] = round(elapsed, 1)
log["steps"].append({"name": "discover", **result})
if result.get("status") == "ok":
# load index.json for subsequent steps
try:
index_data = json.loads(
(output_dir / "index.json").read_text(encoding="utf-8")
)
except Exception as e:
print(f"{TAG} WARN: load index.json failed: {e}")
else:
print(f"{TAG} Discover failed, skipping remaining steps")
log["completed_at"] = iso_now()
log["status"] = "discover_failed"
_save_log(log, output_dir)
_maybe_quit()
return
# ---- Step 1: Meshes ----
if "mesh" in steps:
print(f"\n{TAG} {'-' * 40}")
print(f"{TAG} Step 1: Mesh Analysis")
print(f"{TAG} {'-' * 40}")
t0 = time.time()
try:
from analyze_meshes import run as run_mesh
result = run_mesh(index_data)
except Exception as e:
print(f"{TAG} ERROR in mesh analysis: {e}")
import traceback
traceback.print_exc()
result = {"status": "error", "reason": str(e)}
elapsed = time.time() - t0
result["elapsed_sec"] = round(elapsed, 1)
log["steps"].append({"name": "mesh", **result})
# ---- Step 2: Materials ----
if "material" in steps:
print(f"\n{TAG} {'-' * 40}")
print(f"{TAG} Step 2: Material Analysis")
print(f"{TAG} {'-' * 40}")
t0 = time.time()
try:
from analyze_materials import run as run_material
result = run_material(index_data)
except Exception as e:
print(f"{TAG} ERROR in material analysis: {e}")
import traceback
traceback.print_exc()
result = {"status": "error", "reason": str(e)}
elapsed = time.time() - t0
result["elapsed_sec"] = round(elapsed, 1)
log["steps"].append({"name": "material", **result})
# ---- Step 3: Blueprints ----
if "blueprint" in steps:
print(f"\n{TAG} {'-' * 40}")
print(f"{TAG} Step 3: Blueprint Analysis")
print(f"{TAG} {'-' * 40}")
t0 = time.time()
try:
from analyze_blueprints import run as run_blueprint
result = run_blueprint(index_data)
except Exception as e:
print(f"{TAG} ERROR in blueprint analysis: {e}")
import traceback
traceback.print_exc()
result = {"status": "error", "reason": str(e)}
elapsed = time.time() - t0
result["elapsed_sec"] = round(elapsed, 1)
log["steps"].append({"name": "blueprint", **result})
# ---- 汇总 ----
log["completed_at"] = iso_now()
log["status"] = "ok"
_save_log(log, output_dir)
print(f"\n{TAG} {'=' * 50}")
print(f"{TAG} 全部完成")
print(f"{TAG} {'=' * 50}")
for step in log["steps"]:
print(f"{TAG} {step['name']}: {step.get('status', '?')} "
f"({step.get('analyzed', step.get('total', '?'))} 成功, "
f"{step.get('elapsed_sec', '?')}s)")
_maybe_quit()
def _save_log(log: dict, output_dir: Path):
"""保存运行日志。"""
log_path = output_dir / "catalog_log.json"
write_json(log, log_path)
print(f"{TAG} 日志已保存: {log_path}")
def _maybe_quit():
"""根据 AC_NO_QUIT 决定是否退出编辑器。"""
if should_no_quit():
print(f"{TAG} AC_NO_QUIT=1,不退出编辑器")
else:
print(f"{TAG} 退出编辑器...")
quit_editor()
# ---- 入口 ----
if __name__ == "__main__":
run()