"""BSP 资产锚点检测脚本。 在 UE5 编辑器 Python 环境中运行,检测每个资产的 Bounds Origin, 判断锚点是中心、角落还是底部中心。 用法: 方式1 — 命令行: python main.py check-pivots 方式2 — 编辑器内: exec(open(r"check_pivots.py").read()) """ import sys import os from pathlib import Path # 将 level-builder 根目录加入 sys.path _SCRIPT_DIR = Path(__file__).resolve().parent _LB_DIR = _SCRIPT_DIR if str(_LB_DIR) not in sys.path: sys.path.insert(0, str(_LB_DIR)) from config.asset_mapping import MESH_ASSETS try: import unreal HAS_UNREAL = True except ImportError: HAS_UNREAL = False def check_pivots(): """检测所有 BSP 资产的锚点类型。""" if not HAS_UNREAL: print("[错误] 需要在 UE5 编辑器 Python 环境中运行") return results = [] for name, info in MESH_ASSETS.items(): path = info["path"] default_size = info.get("default_size") mesh = unreal.load_asset(path) if not mesh: results.append(f"{name}: ⚠️ 无法加载") continue # 获取 Bounding Box (UE5 Box 对象有 min/max,没有 origin/extent) bb = mesh.get_bounding_box() bmin = bb.min bmax = bb.max mn_x, mn_y, mn_z = bmin.x, bmin.y, bmin.z mx_x, mx_y, mx_z = bmax.x, bmax.y, bmax.z size_x = mx_x - mn_x size_y = mx_y - mn_y size_z = mx_z - mn_z # 判断锚点类型: # CENTER: min ≈ (-half, -half, -half),对称包围盒 # CORNER: min ≈ (0, 0, 0),锚点在角落 # CENTER_BOTTOM: min ≈ (-half, -half, 0),锚点在底部中心 pivot_type = "UNKNOWN" offset_desc = "" if default_size: dw, dh, dd = default_size half_w, half_h, half_d = dw / 2, dh / 2, dd / 2 tol = 5 # cm 容差 is_corner = (abs(mn_x) < tol and abs(mn_y) < tol and abs(mn_z) < tol) is_center = (abs(mn_x + half_w) < tol and abs(mn_y + half_h) < tol and abs(mn_z + half_d) < tol) is_center_bot = (abs(mn_x + half_w) < tol and abs(mn_y + half_h) < tol and abs(mn_z) < tol) if is_corner: pivot_type = "CORNER" elif is_center: pivot_type = "CENTER" elif is_center_bot: pivot_type = "CENTER_BOTTOM" else: pivot_type = "OTHER" offset_desc = f" (min=({mn_x:.0f},{mn_y:.0f},{mn_z:.0f}), expected corner=0/center=-{half_w:.0f})" else: # 无 default_size,用 min 值推断 tol = 5 if abs(mn_x) < tol and abs(mn_y) < tol and abs(mn_z) < tol: pivot_type = "CORNER?" elif mn_z < -tol: pivot_type = "CENTER?" else: pivot_type = "CENTER_BOTTOM?" offset_desc = f" (no default_size, inferred)" results.append( f"{name}:\n" f" min=({mn_x:.1f}, {mn_y:.1f}, {mn_z:.1f}) " f"max=({mx_x:.1f}, {mx_y:.1f}, {mx_z:.1f}) " f"size=({size_x:.0f}, {size_y:.0f}, {size_z:.0f})\n" f" default_size={default_size} → pivot={pivot_type}{offset_desc}" ) print("=" * 60) print("BSP 资产锚点检测结果") print("=" * 60) for r in results: print(r) print("=" * 60) # 保存结果 out_path = Path(__file__).parent / "output" / "pivot_check.txt" out_path.parent.mkdir(exist_ok=True) with open(out_path, "w", encoding="utf-8") as f: f.write("BSP 资产锚点检测结果\n") f.write("=" * 60 + "\n") for r in results: f.write(r + "\n") print(f"\n结果已保存: {out_path}") # 供命令行调用 if __name__ == "__main__": check_pivots()