Files
jeremy 3ba86b2ea8 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>
2026-08-06 15:55:43 -07:00

4.7 KiB

Marvelous Designer Bridge (TinqsMDBridge)

Live control of Marvelous Designer's Python scripting API from the terminal, sibling of the iClone bridge (docs/iclone-bridge.md): a socket server plug-in inside the app + a thin JSON-over-TCP client.

Key architectural difference from the iClone bridge, found the hard way (2026-07-30, MD 2026 Personal): MD's embedded Python (3.11.8) does NOT schedule background threads while MD idles, and ships no Python Qt binding — so both the daemon-thread server and the QTimer executor patterns are dead on arrival (a threaded server binds, the OS accepts connections, and every request times out). Instead the bridge is a blocking main-thread serve loop: clicking the plugin starts a bridge session during which MD's UI is frozen ("Not Responding" is normal) and all api calls run on the main thread. The session ends via --stop or an idle timeout (default 14400 s / 4 h — the escape hatch, since a frozen UI can't be clicked).

iClone bridge MD bridge
Plug-in source tools/iclone_bridge/TinqsBridge/main.py tools/md_bridge/TinqsMDBridge.py
Client tools/iclone_bridge.py tools/md_bridge.py
Port 18800 18900 (TINQS_MD_BRIDGE_PORT overrides)
Install ps1 copies to OpenPlugin, auto-loads manual register, click = start session
Executor QTimer on Qt main thread, app stays live main-thread serve loop, UI frozen during session
Session end app exit --stop, or idle TINQS_MD_BRIDGE_IDLE (4 h default)
Embedded Python 3.8 3.11.8
Log %TEMP%\tinqs_iclone_bridge.log %TEMP%\tinqs_md_bridge.log

Install (one-time)

  1. Marvelous Designer > Plugin tab > Plug-in Manager > + ADD
  2. Select tools/md_bridge/TinqsMDBridge.py, name it TinqsMDBridge, OK.

⚠ Unverified: whether the Plug-in Manager references the .py in place or copies it. --ping returns a source field — if it isn't the repo path, MD copied it and every edit to the plug-in needs remove + re-ADD. If a click appears to run stale code (old prints, old behavior), re-register.

Session workflow

# 1. In MD: click Plugin > TinqsMDBridge   (UI freezes -- session active)
python tools/md_bridge.py --ping                    # 2. verify
python tools/md_bridge.py --exec "result = dir(pattern_api)"
python tools/md_bridge.py --file draft_tshirt.py
python tools/md_bridge.py --timeout 300 --exec "utility_api.Simulate(200)"
python tools/md_bridge.py --stop                    # 3. unfreeze MD

Wire protocol and result convention are identical to the iClone bridge: newline-delimited JSON, one request per connection; set result in submitted code to get a JSON value back; stdout/stderr captured; exceptions return ok:false + traceback without ending the session. The exec namespace persists across requests within a session (NOT across sessions) and is pre-seeded with:

  • MD api modules that imported successfully: import_api, export_api, pattern_api, fabric_api, utility_api, ApiTypes (all 6 confirmed importable in MD 2026 Personal)
  • BRIDGE — info dict: version, mode ("mainloop"), port, idle_timeout_s, source, api_modules, api_missing, python

Day-1 checklist (next session)

python tools/md_bridge.py --ping                       # mode=mainloop, source path?
python tools/md_bridge.py --exec "result = {m: [f for f in dir(globals()[m]) if not f.startswith('_')] for m in BRIDGE['api_modules']}"
                                                       # dump the REAL api surface (docs are incomplete)
python tools/md_bridge.py --file tools/md_bridge/smoke_test.py --timeout 180
                                                       # signatures + square-of-fabric + Simulate + snapshot
python tools/md_bridge.py --stop

Open question the smoke test answers: do viewport snapshots (ExportSnapshot3D) render while the Qt event loop is blocked? If not, plan B is pumping events from inside the loop or snapshotting after --stop.

Then the real milestones:

  • import Ariki_Female_QuatSkin as FBX avatar (Blender-convert the GLB first), drape a rectangle, snapshot.
  • t-shirt + shorts from tools/tailor/lena_measurements.json drafts.
  • EveryWear rig + GLB export, check bone names == Quaternius.

Gotchas

  • A session must be started by a human click in MD — plan work in batches, and always --stop when done so Jeremy gets his UI back.
  • Long Simulate() calls: raise client --timeout; the idle timer only resets when a request completes, so a 4-minute drape is safe but two 6-minute gaps in a row end the session.
  • Windows may dim the MD window and offer to kill it — decline; the process is healthy.
  • Port clash: 18900 chosen to coexist with iClone's 18800.