# MD session recon -- run FIRST thing next bridge session: # python tools/md_bridge.py --file tools/tailor/md_recon.py --timeout 300 # # 1. Harvests pybind11 docstrings (all overloads) for every function the # t-shirt build needs -> tools/md_bridge/api_docs.json # 2. Imports the Lena avatar FBX (tools/tailor/avatar/Lena_QuatSkin_Avatar.fbx) # 3. Lists arrangement points, snapshots the scene # Defensive: each step reports independently; nothing dies on the first surprise. import json import os import tempfile import traceback REPO = r"C:\Users\Jeremy\tinqs\animation" AVATAR_FBX = os.path.join(REPO, "tools", "tailor", "avatar", "Lena_QuatSkin_Avatar.fbx") DOCS_OUT = os.path.join(REPO, "tools", "md_bridge", "api_docs.json") report = {"steps": []} def step(name, fn): entry = {"step": name} try: entry["ok"] = True entry["value"] = fn() except Exception: entry["ok"] = False entry["error"] = traceback.format_exc().strip().splitlines()[-1] report["steps"].append(entry) return entry # ---- 1. docstring harvest ------------------------------------------------- WANTED = { "import_api": ["ImportAvatar", "ImportFBX", "ImportOBJ", "ImportFile", "ImportZpac", "ImportPose"], "export_api": ["ExportSnapshot3D", "ExportCustomViewSnapshot", "ExportFBX", "ExportOBJ", "ExportZPac", "ExportTurntableImages", "GetAvatarCount", "GetAvatarNameList"], "pattern_api": ["CreatePatternWithPoints", "CreateInternalShapeWithPoints", "AddSeamlinePairGroup", "GetSeamlinePairGroupCount", "SetArrangement", "SetArrangementPosition", "SetArrangementOrientation", "GetArrangementList", "GetArrangementOfPattern", "SetPatternPiecePos", "SetPatternPieceMove", "MovePatternPoint", "FlipPatternPiece", "GetPatternIndexList", "GetPatternInformation", "SetPatternPieceElastic", "DeletePatternPiece"], "fabric_api": ["GetFabricList", "GetFabricIndexForPattern", "SetFabricForPattern", "AddFabric", "SetFabricColor"], "utility_api": ["Simulate", "NewProject", "OpenProject", "SaveProjectFile", "SetColorwayIndex", "DeleteAvatar", "AlignAvatarsAndGarmentToCenter", "ResetSimulation", "SetSimulationQuality", "GetCurrentProjectFilePath"], "ApiTypes": ["ImportExportOption"], } def harvest(): docs = {} for mod_name, names in WANTED.items(): mod = globals().get(mod_name) if mod is None: continue for n in names: f = getattr(mod, n, None) key = "{}.{}".format(mod_name, n) docs[key] = (getattr(f, "__doc__", None) or "") if f is not None else "" # ImportExportOption: dump its member names too -- it's the option struct opt = getattr(ApiTypes, "ImportExportOption", None) if opt is not None: docs["ApiTypes.ImportExportOption.members"] = [ m for m in dir(opt) if not m.startswith("_")] with open(DOCS_OUT, "w", encoding="utf-8") as f: json.dump(docs, f, indent=1) return {"harvested": len(docs), "out": DOCS_OUT} step("harvest_docs", harvest) # ---- 2. fresh scene + avatar ---------------------------------------------- step("NewProject", lambda: utility_api.NewProject()) step("avatar_file_exists", lambda: os.path.getsize(AVATAR_FBX)) def import_avatar(): # Try the simplest overload first; fall back to option-struct form. try: return {"call": "ImportAvatar(path)", "ret": import_api.ImportAvatar(AVATAR_FBX)} except TypeError: op = ApiTypes.ImportExportOption() return {"call": "ImportAvatar(path, op)", "ret": import_api.ImportAvatar(AVATAR_FBX, op)} step("ImportAvatar", import_avatar) step("avatars_after", lambda: {"count": export_api.GetAvatarCount(), "names": export_api.GetAvatarNameList()}) step("arrangement_points", lambda: pattern_api.GetArrangementList()) # ---- 3. look at her -------------------------------------------------------- SNAP = os.path.join(tempfile.gettempdir(), "tinqs_md_lena_avatar.png") def snap(): export_api.ExportSnapshot3D(SNAP) return {"path": SNAP, "exists": os.path.exists(SNAP), "size": os.path.getsize(SNAP) if os.path.exists(SNAP) else 0} step("snapshot", snap) report["passed"] = sum(1 for s in report["steps"] if s["ok"]) report["failed"] = sum(1 for s in report["steps"] if not s["ok"]) result = report