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:
2026-08-06 15:55:43 -07:00
parent 3363209cac
commit 3ba86b2ea8
558 changed files with 68622 additions and 8 deletions
+93
View File
@@ -0,0 +1,93 @@
# 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
```bash
# 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)
```bash
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.