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,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.
|
||||
Reference in New Issue
Block a user