116 lines
4.5 KiB
Python
116 lines
4.5 KiB
Python
|
|
# 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 "<missing>") if f is not None else "<missing>"
|
||
|
|
# 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
|