feat: clothing lane, character sources, and DCC bridges
Bulk import of the working lanes that were living untracked on the PC. Content: - characters/ Lena/male body lanes, bakes, texture work, run logs - clothing/ garment pipeline, configs, gates, contract docs - garments/ MD-authored garment sources (.zprj/.zpac) - UAL-Lib/ Universal Animation Library 2 source (.blend/.fbx/.glb) - tools/ blender_bridge, iclone_bridge, md_bridge, tailor, glm_agent - docs/, plans/, dev/, .agents/plans/ Repo hygiene: - .gitattributes: LFS now covers .blend, .zprj, .zpac, .obj, .npy and the Reallusion .iAvatar/.ccAvatar/.ccRestore containers. Without this the ~3.8 GB in this commit would land as raw blobs. .png/.jpg are left out on purpose — ~250 are already tracked raw and converting them would rewrite every one without shrinking history. - .gitignore: exclude /accurig/ (~1 GB AccuRig program files, redistributable from Reallusion, nothing authored here) and /dev/null/ (git-lfs hook copies dropped by a `>/dev/null` redirect on Windows). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# TinqsMDBridge smoke test -- run via:
|
||||
# python tools/md_bridge.py --file tools/md_bridge/smoke_test.py --timeout 120
|
||||
#
|
||||
# Defensive by design: MD's api docs are incomplete and signatures unverified,
|
||||
# so every step is independently try/except'd and the whole thing returns a
|
||||
# step-by-step report instead of dying on the first surprise. Nothing here
|
||||
# should be treated as the "right" calling convention until this has passed
|
||||
# once -- it's a probe, not a recipe.
|
||||
|
||||
import inspect
|
||||
import os
|
||||
import tempfile
|
||||
import traceback
|
||||
|
||||
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
|
||||
|
||||
|
||||
def docs_of(mod, names):
|
||||
out = {}
|
||||
for n in names:
|
||||
f = getattr(mod, n, None)
|
||||
if f is None:
|
||||
out[n] = "<missing>"
|
||||
continue
|
||||
try:
|
||||
out[n] = str(inspect.signature(f))
|
||||
except (ValueError, TypeError):
|
||||
doc = (getattr(f, "__doc__", "") or "").strip()
|
||||
out[n] = doc.splitlines()[0] if doc else "<no signature/doc>"
|
||||
return out
|
||||
|
||||
|
||||
# 1. what do the key functions actually look like?
|
||||
step("signatures.pattern", lambda: docs_of(pattern_api, [
|
||||
"CreatePatternWithPoints", "AddSeamlinePairGroup", "SetArrangementPosition",
|
||||
"MovePatternPoint", "DeletePatternPiece"]))
|
||||
step("signatures.utility", lambda: docs_of(utility_api, [
|
||||
"NewProject", "Simulate", "GetAvatarCount", "GetAvatarNameList"]))
|
||||
step("signatures.export", lambda: docs_of(export_api, [
|
||||
"ExportSnapshot3D", "ExportCustomViewSnapshot", "ExportGLTF", "ExportFBX"]))
|
||||
|
||||
# 2. fresh project
|
||||
step("NewProject", lambda: utility_api.NewProject())
|
||||
|
||||
# 3. default avatar present?
|
||||
step("avatars", lambda: {
|
||||
"count": utility_api.GetAvatarCount(),
|
||||
"names": utility_api.GetAvatarNameList(),
|
||||
})
|
||||
|
||||
# 4. create a 50cm square pattern (units unverified -- try mm first, the CLO
|
||||
# convention; the snapshot will show which interpretation MD used)
|
||||
SQUARE_MM = [(0.0, 0.0), (500.0, 0.0), (500.0, 500.0), (0.0, 500.0)]
|
||||
|
||||
|
||||
def make_square():
|
||||
return pattern_api.CreatePatternWithPoints(SQUARE_MM)
|
||||
|
||||
|
||||
step("CreatePatternWithPoints(square)", make_square)
|
||||
|
||||
# 5. short drape
|
||||
step("Simulate(30)", lambda: utility_api.Simulate(30))
|
||||
|
||||
# 6. snapshot -- the agent's eyes
|
||||
SNAP = os.path.join(tempfile.gettempdir(), "tinqs_md_smoke.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("ExportSnapshot3D", 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
|
||||
Reference in New Issue
Block a user