cozyclay 2.1.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +12 -30
  3. package/bin/agent/agent-routes.mjs +40 -113
  4. package/bin/agent/agent-runner.mjs +9 -10
  5. package/bin/agent/cliproxy-provider.mjs +135 -0
  6. package/bin/agent/credential-store.mjs +30 -7
  7. package/bin/agent/pi-tools.mjs +4 -1
  8. package/bin/agent/provider-keys.mjs +32 -0
  9. package/bin/agent/provider-login.mjs +110 -0
  10. package/bin/agent/provider-routes.mjs +99 -0
  11. package/bin/agent/providers.mjs +19 -97
  12. package/bin/agent/script-tool.mjs +17 -4
  13. package/bin/agent/studio-motion-reference.mjs +23 -0
  14. package/bin/agent/studio-prompt.mjs +1 -1
  15. package/bin/agent/studio-rebase-text.mjs +32 -0
  16. package/bin/agent/studio-rebase.mjs +26 -39
  17. package/bin/agent/studio-tools.mjs +9 -28
  18. package/bin/agent/tool-arguments.mjs +49 -0
  19. package/bin/agent/turn-frames.mjs +66 -0
  20. package/bin/codex-auth.mjs +9 -2
  21. package/bin/cozyclay.mjs +10 -116
  22. package/bin/live/cli.mjs +3 -3
  23. package/bin/mcp-runtime.mjs +2 -12
  24. package/bin/package-signature.mjs +0 -4
  25. package/dist/app/index.html +7 -6
  26. package/dist/assets/EXRLoader-CvVIvGVE.js +1 -0
  27. package/dist/assets/analytics-C9sUnndd.js +1 -0
  28. package/dist/assets/app-CCh--1Hc.js +5087 -0
  29. package/dist/assets/app-f-fkV5uP.css +1 -0
  30. package/dist/assets/compile-worker-CkxiD6lH.js +5 -0
  31. package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
  32. package/dist/assets/{first-shot-handoff-msLI71g1.js → first-shot-handoff-CC4xe4HM.js} +1 -1
  33. package/dist/assets/{landing-ChUvB_zL.js → landing-DjHD8u7k.js} +1 -1
  34. package/dist/assets/scene-asset-sync-Hx_FzdOH.js +20 -0
  35. package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
  36. package/dist/assets/workflow-C4yKH1p4.js +179 -0
  37. package/dist/cozyclay-package.json +1 -1
  38. package/dist/index.html +3 -3
  39. package/dist/sw.js +3 -6
  40. package/dist/workflow/index.html +5 -4
  41. package/mcp/LIVE-PROTOCOL.md +7 -47
  42. package/mcp/README.md +16 -26
  43. package/mcp/live-hub.mjs +6 -10
  44. package/mcp/package.json +1 -3
  45. package/mcp/tool-handlers.mjs +4 -168
  46. package/package.json +3 -22
  47. package/src/App.jsx +150 -2624
  48. package/src/agent-progress.js +79 -0
  49. package/src/agent-turn-mark.js +30 -0
  50. package/src/analytics.js +1 -19
  51. package/src/app-context.js +5 -0
  52. package/src/app-stage.jsx +2 -34
  53. package/src/asset-pane.jsx +6 -5
  54. package/src/camera-block.js +21 -0
  55. package/src/camera-direction.js +120 -0
  56. package/src/character-kind.js +3 -9
  57. package/src/command-bus.js +8 -6
  58. package/src/commands/cast.js +5 -34
  59. package/src/commands/elements/character.js +1 -1
  60. package/src/commands/elements/motion.js +1 -6
  61. package/src/commands/elements/object.js +6 -2
  62. package/src/commands/elements/shot.js +4 -1
  63. package/src/commands/elements.js +38 -14
  64. package/src/commands/index.js +3 -1
  65. package/src/commands/kits.js +37 -0
  66. package/src/commands/motion-timing.js +57 -0
  67. package/src/commands/motion.js +9 -152
  68. package/src/commands/motion3-compile.js +65 -0
  69. package/src/commands/motion3.js +207 -0
  70. package/src/commands/objects.js +6 -4
  71. package/src/commands/shot.js +49 -11
  72. package/src/commands/stage.js +14 -1
  73. package/src/commands/view.js +4 -1
  74. package/src/document-mirrors.js +42 -0
  75. package/src/document-store.js +4 -0
  76. package/src/domains/cast.js +19 -194
  77. package/src/domains/motion/motion-range-pin-rules.js +1 -1
  78. package/src/domains/motion/take-source.js +51 -0
  79. package/src/domains/motion.js +60 -1838
  80. package/src/domains/scenes.js +12 -55
  81. package/src/domains/shots.js +2 -2
  82. package/src/domains/stage.js +4 -2
  83. package/src/draft-ghost.js +46 -0
  84. package/src/draft-ghost.jsx +129 -0
  85. package/src/dualview.jsx +4 -3
  86. package/src/effects/EffectsLayer.jsx +112 -0
  87. package/src/effects/effect-meshes.js +232 -0
  88. package/src/effects/effect-record.js +103 -0
  89. package/src/effects/emitter.js +59 -0
  90. package/src/effects/simulate.js +261 -0
  91. package/src/effects/state.js +59 -0
  92. package/src/execution-telemetry.js +2 -3
  93. package/src/first-success-guide.jsx +5 -5
  94. package/src/ghost-set.js +257 -0
  95. package/src/held-object-edit.jsx +113 -0
  96. package/src/held-object-pose.js +175 -0
  97. package/src/hierarchy-model.js +1 -1
  98. package/src/hierarchy-panel.jsx +1 -1
  99. package/src/imported-mesh.jsx +103 -0
  100. package/src/kits/held.js +84 -0
  101. package/src/kits/index.js +70 -0
  102. package/src/kits/smoking.js +57 -0
  103. package/src/light-blockers.js +93 -0
  104. package/src/motion/beat-board-model.js +84 -0
  105. package/src/motion/beat-board.css +124 -0
  106. package/src/motion/beat-board.jsx +59 -0
  107. package/src/motion/center-of-mass.js +66 -0
  108. package/src/motion/fix-collisions.js +850 -0
  109. package/src/motion/physics-review.js +118 -0
  110. package/src/{ardy → motion}/physics-support.js +1 -76
  111. package/src/motion/rig-snapshot.js +22 -0
  112. package/src/motion/take-segments.jsx +140 -0
  113. package/src/{ardy → motion}/timeline-coordinates.js +0 -21
  114. package/src/{ardy → motion}/timeline.css +1 -2
  115. package/src/{ardy → motion}/timeline.jsx +42 -413
  116. package/src/motion/waypoints.js +76 -0
  117. package/src/motion3/beats.js +83 -0
  118. package/src/motion3/body.js +158 -0
  119. package/src/motion3/bones.js +47 -0
  120. package/src/motion3/carried.js +47 -0
  121. package/src/motion3/compile-job.js +75 -0
  122. package/src/motion3/compile-worker.js +10 -0
  123. package/src/motion3/compiler/anchors.js +105 -0
  124. package/src/motion3/compiler/arm-orient.js +128 -0
  125. package/src/motion3/compiler/channels.js +125 -0
  126. package/src/motion3/compiler/compile.js +205 -0
  127. package/src/motion3/compiler/gait-rhythm.js +97 -0
  128. package/src/motion3/compiler/grip.js +171 -0
  129. package/src/motion3/compiler/head-steady.js +48 -0
  130. package/src/motion3/compiler/hold.js +134 -0
  131. package/src/motion3/compiler/idle.js +113 -0
  132. package/src/motion3/compiler/limbs.js +170 -0
  133. package/src/motion3/compiler/math.js +72 -0
  134. package/src/motion3/compiler/pose.js +162 -0
  135. package/src/motion3/compiler/quat.js +49 -0
  136. package/src/motion3/compiler/skeleton.js +74 -0
  137. package/src/motion3/compiler/validate-common.js +32 -0
  138. package/src/motion3/compiler/validate-goals.js +118 -0
  139. package/src/motion3/compiler/validate-objects.js +143 -0
  140. package/src/motion3/compiler/validate-parts.js +116 -0
  141. package/src/motion3/compiler/validate.js +122 -0
  142. package/src/motion3/compiler/vocab.js +73 -0
  143. package/src/motion3/compiler/walk-pelvis.js +275 -0
  144. package/src/motion3/compiler/walk.js +207 -0
  145. package/src/motion3/compiler/wrist-clamp.js +32 -0
  146. package/src/motion3/delta.js +47 -0
  147. package/src/motion3/describe.js +174 -0
  148. package/src/motion3/docs.js +27 -0
  149. package/src/motion3/edit-carry.js +21 -0
  150. package/src/motion3/fix/ease.js +16 -0
  151. package/src/motion3/fix/ground.js +37 -0
  152. package/src/motion3/fix/index.js +52 -0
  153. package/src/motion3/fix/push.js +71 -0
  154. package/src/motion3/fix/reach.js +46 -0
  155. package/src/motion3/fix/retime.js +79 -0
  156. package/src/motion3/fix/self.js +211 -0
  157. package/src/motion3/fix/slide.js +70 -0
  158. package/src/motion3/fix/turn.js +51 -0
  159. package/src/motion3/follow.js +39 -0
  160. package/src/motion3/free-motion.js +173 -0
  161. package/src/motion3/grip-choice.js +130 -0
  162. package/src/motion3/hold-plan.js +157 -0
  163. package/src/motion3/json-patch.js +77 -0
  164. package/src/motion3/key-aim.js +105 -0
  165. package/src/motion3/key-edit.js +82 -0
  166. package/src/motion3/lenient.js +127 -0
  167. package/src/motion3/object-keys.js +236 -0
  168. package/src/motion3/object-pose.js +182 -0
  169. package/src/motion3/object-tracks.js +12 -0
  170. package/src/motion3/pipeline.js +102 -0
  171. package/src/motion3/playback.js +51 -0
  172. package/src/motion3/probes.js +91 -0
  173. package/src/motion3/qa/body-checks.js +34 -0
  174. package/src/motion3/qa/check-names.js +14 -0
  175. package/src/motion3/qa/checks.js +121 -0
  176. package/src/motion3/qa/contact-checks.js +51 -0
  177. package/src/motion3/qa/explain.js +80 -0
  178. package/src/motion3/qa/fmt.js +5 -0
  179. package/src/motion3/qa/foot-checks.js +72 -0
  180. package/src/motion3/qa/geometry.js +77 -0
  181. package/src/motion3/qa/goals.js +191 -0
  182. package/src/motion3/qa/ground.js +60 -0
  183. package/src/motion3/qa/hints-contact.js +179 -0
  184. package/src/motion3/qa/hints-goal.js +160 -0
  185. package/src/motion3/qa/hints-knee.js +24 -0
  186. package/src/motion3/qa/hints-motion.js +209 -0
  187. package/src/motion3/qa/hints-object.js +91 -0
  188. package/src/motion3/qa/index.js +42 -0
  189. package/src/motion3/qa/key-checks.js +82 -0
  190. package/src/motion3/qa/near.js +96 -0
  191. package/src/motion3/qa/object-checks.js +135 -0
  192. package/src/motion3/qa/patch.js +161 -0
  193. package/src/motion3/qa/severity.js +38 -0
  194. package/src/motion3/qa/spec-checks.js +65 -0
  195. package/src/motion3/qa/style.js +218 -0
  196. package/src/motion3/qa/wrist-checks.js +69 -0
  197. package/src/motion3/qa/wrist-obs.js +60 -0
  198. package/src/motion3/refs.js +120 -0
  199. package/src/motion3/repair-tune.js +121 -0
  200. package/src/motion3/repair.js +83 -0
  201. package/src/motion3/report.js +67 -0
  202. package/src/motion3/rigs/index.js +14 -0
  203. package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
  204. package/src/motion3/rigs/x-bot-tpose.json +1 -0
  205. package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
  206. package/src/motion3/rigs/y-bot-tpose.json +1 -0
  207. package/src/motion3/scene.js +60 -0
  208. package/src/motion3/schema/brief.js +89 -0
  209. package/src/motion3/schema/fields.js +44 -0
  210. package/src/motion3/schema/spec-examples.js +46 -0
  211. package/src/motion3/schema/topics.js +111 -0
  212. package/src/motion3/schema/types.js +147 -0
  213. package/src/motion3/search.js +117 -0
  214. package/src/motion3/second-hand.js +112 -0
  215. package/src/motion3/skills/basic.js +82 -0
  216. package/src/motion3/skills/book.js +76 -0
  217. package/src/motion3/skills/car.js +145 -0
  218. package/src/motion3/skills/frames-auto.js +29 -0
  219. package/src/motion3/skills/index.js +83 -0
  220. package/src/motion3/skills/info.js +65 -0
  221. package/src/motion3/skills/smoke-kit.js +109 -0
  222. package/src/motion3/skills/smoke.js +160 -0
  223. package/src/motion3/spec-store.js +59 -0
  224. package/src/motion3/take-edit.js +155 -0
  225. package/src/motion3/take.js +63 -0
  226. package/src/motion3/timeline.js +127 -0
  227. package/src/motion3/views.js +121 -0
  228. package/src/motion3/walk-plan.js +119 -0
  229. package/src/object-catalog.jsx +7 -1
  230. package/src/object-colors.js +98 -0
  231. package/src/object-gizmo-parts.js +115 -0
  232. package/src/object-gizmo.jsx +37 -122
  233. package/src/object-glow.js +139 -0
  234. package/src/object-hidden.js +33 -0
  235. package/src/object-look.js +196 -0
  236. package/src/object-size.js +10 -0
  237. package/src/object-travel.js +71 -6
  238. package/src/panels/CameraPanel.jsx +7 -7
  239. package/src/panels/HdrEnvironmentControls.jsx +59 -0
  240. package/src/panels/LightPanel.jsx +25 -4
  241. package/src/panels/ObjectLookPanel.jsx +88 -0
  242. package/src/panels/PosePanel.jsx +2 -17
  243. package/src/panels/RigControlPanel.jsx +5 -53
  244. package/src/panels/SubjectBox.jsx +4 -1
  245. package/src/panels/details.css +14 -0
  246. package/src/posestudio.jsx +4 -27
  247. package/src/project-browser.jsx +3 -4
  248. package/src/project-resources.js +18 -31
  249. package/src/project.js +13 -104
  250. package/src/props.jsx +25 -280
  251. package/src/rail-dot-drag.js +23 -0
  252. package/src/render-passes.js +10 -0
  253. package/src/resource-status.jsx +1 -0
  254. package/src/result-modal.jsx +4 -19
  255. package/src/room.jsx +20 -12
  256. package/src/scene-assets.js +8 -6
  257. package/src/scene-light-place.js +72 -0
  258. package/src/scene-lights.jsx +148 -0
  259. package/src/scene-objects.js +31 -139
  260. package/src/scenes.js +15 -105
  261. package/src/semantic-edit.js +2 -5
  262. package/src/set-pieces.jsx +183 -0
  263. package/src/settings-menu.jsx +3 -11
  264. package/src/shell/BottomDock.jsx +9 -51
  265. package/src/shell/DetailsSlot.jsx +16 -200
  266. package/src/shell/GhostsMenuGroup.jsx +74 -0
  267. package/src/shell/LibrarySlot.jsx +1 -3
  268. package/src/shell/MenuBar.jsx +3 -3
  269. package/src/shell/PreferencesDialog.jsx +15 -264
  270. package/src/shell/PreferencesSlot.jsx +2 -8
  271. package/src/shell/TopBar.jsx +5 -84
  272. package/src/shell/ViewportToolbar.jsx +10 -70
  273. package/src/shell/agent-glass.css +19 -6
  274. package/src/shell/details-selection.js +42 -0
  275. package/src/shell/ghosts-menu.css +22 -0
  276. package/src/shell/glass-regions.css +29 -3
  277. package/src/shell/preferences.css +6 -1
  278. package/src/shot-authoring.js +4 -7
  279. package/src/soft-shadows.js +37 -0
  280. package/src/stage-attach-frames.js +12 -12
  281. package/src/stage-canvas-rigs.jsx +3 -3
  282. package/src/stage-capture.jsx +42 -8
  283. package/src/stage-characters.jsx +22 -216
  284. package/src/stage-editor-gizmos.jsx +6 -6
  285. package/src/stage-environment.js +93 -0
  286. package/src/stage-hdr-builtins.js +107 -0
  287. package/src/stage-hdr-image.js +116 -0
  288. package/src/stage-hdr-library.js +70 -0
  289. package/src/stage-hdr-map.js +94 -0
  290. package/src/stage-hdr.js +130 -0
  291. package/src/stage-lighting.js +149 -0
  292. package/src/stage-occlusion.js +210 -0
  293. package/src/stage-sky.jsx +159 -0
  294. package/src/stage-startup-defaults.js +5 -9
  295. package/src/studio-actions.js +12 -14
  296. package/src/studio-agent-commands.js +19 -16
  297. package/src/studio-agent-motion.js +9 -9
  298. package/src/studio-agent-protocol.js +41 -71
  299. package/src/studio-app-binding.js +25 -45
  300. package/src/studio-asset-list.js +17 -0
  301. package/src/studio-contact-sheet.js +37 -5
  302. package/src/studio-elements.js +27 -7
  303. package/src/studio-entity-bounds.js +18 -0
  304. package/src/studio-error-codes.js +8 -0
  305. package/src/studio-export-framing.js +152 -0
  306. package/src/studio-lighting-check.js +103 -0
  307. package/src/studio-motion-visual.js +150 -0
  308. package/src/studio-schema-errors.js +80 -0
  309. package/src/studio-support-gap.js +74 -0
  310. package/src/styles.css +1 -19
  311. package/src/timeline-defaults.js +5 -0
  312. package/src/timeline-extent.js +8 -20
  313. package/src/tutorial-walk.js +17 -0
  314. package/src/ui-scrub.js +1 -1
  315. package/src/use-shot-camera-tracks.js +12 -0
  316. package/src/view-ghosts.js +97 -0
  317. package/src/view-ghosts.jsx +49 -0
  318. package/src/workflow/AgentPanel.jsx +47 -166
  319. package/src/workflow/AgentProgressCard.jsx +107 -0
  320. package/src/workflow/AgentReplyText.jsx +37 -0
  321. package/src/workflow/AgentTurnSteps.jsx +84 -0
  322. package/src/workflow/LoginPanel.jsx +140 -0
  323. package/src/workflow/WorkflowBuilder.jsx +7 -23
  324. package/src/workflow/agent-client.js +54 -51
  325. package/src/workflow/agent-panel.css +71 -1
  326. package/src/workflow/agent-progress-card.css +167 -0
  327. package/src/workflow/agent-progress-view.js +47 -0
  328. package/src/workflow/agent-turn-steps.css +113 -0
  329. package/src/workflow/agent-turn.js +191 -0
  330. package/src/workflow/login-client.js +34 -0
  331. package/src/workflow/motion-input.js +18 -31
  332. package/src/workflow/node-schema.js +1 -1
  333. package/src/workflow/reply-markdown.js +69 -0
  334. package/src/workflow/scene-asset-sync.js +8 -8
  335. package/tools/agent-session-stats.mjs +61 -0
  336. package/tools/dev-full.mjs +5 -56
  337. package/tools/eslint-baseline.json +12 -13
  338. package/tools/knip-baseline.json +0 -179
  339. package/tools/loc-baseline.json +31 -81
  340. package/tools/motion3/extract-body.mjs +103 -0
  341. package/tools/motion3/extract-rig.mjs +85 -0
  342. package/tools/process-supervisor.mjs +0 -88
  343. package/tools/run-tests.mjs +8 -124
  344. package/bin/agent/motion-runtime.mjs +0 -76
  345. package/dist/ardy/cskel27-rest.json +0 -557
  346. package/dist/assets/analytics-C9pMpW7s.js +0 -1
  347. package/dist/assets/app-B_2XB9rw.css +0 -1
  348. package/dist/assets/app-DAuvKPP8.js +0 -4920
  349. package/dist/assets/config-Bx7pYsD9.js +0 -1
  350. package/dist/assets/config-DeoFTYzb.css +0 -1
  351. package/dist/assets/demo-CvKuBgy5.js +0 -1
  352. package/dist/assets/scene-asset-sync-DKkpjKBV.js +0 -19
  353. package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
  354. package/dist/assets/ticket-BPk2Ni95.js +0 -1
  355. package/dist/assets/workflow-jJRBR94Z.js +0 -179
  356. package/dist/demo/walk-then-stop.npz +0 -0
  357. package/mcp/ardy-prompts.mjs +0 -218
  358. package/src/ardy/auto-fix-panel.css +0 -108
  359. package/src/ardy/auto-physics.js +0 -1194
  360. package/src/ardy/client.js +0 -153
  361. package/src/ardy/convert.js +0 -313
  362. package/src/ardy/cskel27-neutral.js +0 -39
  363. package/src/ardy/cskel27.js +0 -77
  364. package/src/ardy/export.js +0 -165
  365. package/src/ardy/fix-collisions.js +0 -2257
  366. package/src/ardy/foot-lock.js +0 -230
  367. package/src/ardy/motion-calibration.js +0 -118
  368. package/src/ardy/motion-edit.js +0 -213
  369. package/src/ardy/motion-url.js +0 -55
  370. package/src/ardy/mp4-duration.js +0 -102
  371. package/src/ardy/npz.js +0 -595
  372. package/src/ardy/physics-panel.css +0 -21
  373. package/src/ardy/physics-panel.jsx +0 -89
  374. package/src/ardy/physics-refine.js +0 -111
  375. package/src/ardy/physics-review.js +0 -567
  376. package/src/ardy/physics-temporal.js +0 -54
  377. package/src/ardy/platform-fit-panel.css +0 -64
  378. package/src/ardy/platform-fit-panel.jsx +0 -41
  379. package/src/ardy/platform-fit.js +0 -326
  380. package/src/ardy/playback.js +0 -711
  381. package/src/ardy/pose-pin.js +0 -97
  382. package/src/ardy/prompt-clips.js +0 -30
  383. package/src/ardy/retime.js +0 -211
  384. package/src/ardy/root-drop.js +0 -369
  385. package/src/ardy/timeline-resize.js +0 -13
  386. package/src/ardy/to-cskel27.js +0 -225
  387. package/src/ardy/trim.js +0 -33
  388. package/src/ardy/waypoints.js +0 -369
  389. package/src/ardy-bridge-contract.js +0 -281
  390. package/src/domains/motion/motion-video-capture.js +0 -664
  391. package/src/i2v-motion-client.js +0 -77
  392. package/src/i2v-motion-studio.jsx +0 -180
  393. package/src/line-edit.js +0 -1348
  394. package/src/motion/generation.js +0 -105
  395. package/src/motion-readiness-ui.jsx +0 -67
  396. package/src/motion-readiness.js +0 -40
  397. package/src/motion-resources.js +0 -177
  398. package/src/motion-store.js +0 -65
  399. package/src/motion-trail.js +0 -601
  400. package/src/multimodel-ingest.js +0 -394
  401. package/src/panels/PromptBlocksPanel.jsx +0 -444
  402. package/src/panels/VideoCapturePanel.jsx +0 -181
  403. package/src/pose-extract/browser.js +0 -42
  404. package/src/pose-extract/detector.js +0 -100
  405. package/src/pose-extract/fit.js +0 -227
  406. package/src/pose-extract/image-frame.js +0 -51
  407. package/src/pose-extract/index.js +0 -58
  408. package/src/pose-extract/keyframes.js +0 -74
  409. package/src/pose-extract/landmarks.js +0 -162
  410. package/src/pose-extract/mirror.js +0 -153
  411. package/src/pose-extract/take.js +0 -131
  412. package/src/pose-extract/video-frames.js +0 -91
  413. package/src/take-recipe.js +0 -165
  414. package/src/trail-key-conflicts.js +0 -39
  415. package/src/trail-pick.js +0 -59
  416. package/src/use-i2v-capture-modal.js +0 -15
  417. package/tools/ardy/BRIDGE.md +0 -37
  418. package/tools/ardy/GVHMR-NPZ.md +0 -68
  419. package/tools/ardy/README.md +0 -124
  420. package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
  421. package/tools/ardy/artifacts.mjs +0 -34
  422. package/tools/ardy/bridge.mjs +0 -1732
  423. package/tools/ardy/bvh-cskel27.mjs +0 -1265
  424. package/tools/ardy/cclay_constrained_generate.py +0 -561
  425. package/tools/ardy/cclay_gvhmr_worker.py +0 -264
  426. package/tools/ardy/cclay_motion_edit.py +0 -510
  427. package/tools/ardy/cclay_sequence_generate.py +0 -705
  428. package/tools/ardy/cclay_worker.py +0 -304
  429. package/tools/ardy/dump-npz.py +0 -205
  430. package/tools/ardy/extract-rest.mjs +0 -299
  431. package/tools/ardy/extract.mjs +0 -507
  432. package/tools/ardy/footage.mjs +0 -467
  433. package/tools/ardy/gvhmr-floor.mjs +0 -102
  434. package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
  435. package/tools/ardy/gvhmr_fastpath.py +0 -168
  436. package/tools/ardy/gvhmr_trajectory.py +0 -240
  437. package/tools/ardy/merge-text-encoder.py +0 -160
  438. package/tools/ardy/mocap-metrics.mjs +0 -200
  439. package/tools/ardy/mocap-quality-gate.mjs +0 -110
  440. package/tools/ardy/motion-stabilize.mjs +0 -348
  441. package/tools/ardy/npz.mjs +0 -414
  442. package/tools/ardy/pose-to-npz.mjs +0 -106
  443. package/tools/ardy/prompt-limits.mjs +0 -5
  444. package/tools/ardy/run-edit-on-box.sh +0 -73
  445. package/tools/ardy/run-local.mjs +0 -233
  446. package/tools/ardy/run-on-box.sh +0 -593
  447. package/tools/ardy/run-sequence-on-box.sh +0 -177
  448. package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
  449. package/tools/ardy/runners/index.mjs +0 -18
  450. package/tools/ardy/runners/local.mjs +0 -455
  451. package/tools/ardy/runners/proc.mjs +0 -125
  452. package/tools/ardy/runners/remote.mjs +0 -252
  453. package/tools/ardy/setup-local.mjs +0 -189
  454. package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
  455. package/tools/ardy/setup-text-encoder.py +0 -306
  456. package/tools/ardy/smpl-cskel27.mjs +0 -178
  457. package/tools/ardy/visual-qa.mjs +0 -196
  458. package/tools/ardy/vq-car.mjs +0 -52
  459. package/tools/bench/EXP3.md +0 -61
  460. package/tools/bench/cclay_bench_extract_incam.py +0 -125
  461. package/tools/bench/cclay_bench_extract_obs.py +0 -204
  462. package/tools/bench/cclay_bench_runner.py +0 -42
  463. package/tools/bench/cube-contact.mjs +0 -162
  464. package/tools/bench/exp3.mjs +0 -152
  465. package/tools/bench/extract-bench-lib.mjs +0 -216
  466. package/tools/bench/extract-bench.mjs +0 -302
  467. package/tools/bench/fal-generate.mjs +0 -88
  468. package/tools/bench/fit/README.md +0 -189
  469. package/tools/bench/fit/camera.mjs +0 -59
  470. package/tools/bench/fit/contact.mjs +0 -419
  471. package/tools/bench/fit/footlock.mjs +0 -234
  472. package/tools/bench/fit/motion.mjs +0 -85
  473. package/tools/bench/fit/pin.mjs +0 -27
  474. package/tools/bench/fit/remote.mjs +0 -105
  475. package/tools/bench/fit-bench.mjs +0 -126
  476. package/tools/bench/fit-sanity.mjs +0 -45
  477. package/tools/bench/metrics.mjs +0 -313
  478. package/tools/bench/obs/depth.mjs +0 -258
  479. package/tools/bench/obs/extrinsics.mjs +0 -175
  480. package/tools/bench/obs/fit_mannequin_betas.py +0 -340
  481. package/tools/bench/obs/ground.mjs +0 -294
  482. package/tools/bench/obs/heading.mjs +0 -151
  483. package/tools/bench/obs/ladder.mjs +0 -555
  484. package/tools/bench/obs/mannequin-betas.json +0 -124
  485. package/tools/bench/obs/remote.mjs +0 -83
  486. package/tools/bench/obs/rest_joints.py +0 -52
  487. package/tools/bench/obs/ybot-targets.mjs +0 -49
  488. package/tools/bench/obs-bench.mjs +0 -520
  489. package/tools/bench/score.mjs +0 -343
  490. package/tools/bench/summarize.mjs +0 -86
  491. package/tools/demo-worker/README.md +0 -137
  492. package/tools/demo-worker/api-client.mjs +0 -233
  493. package/tools/demo-worker/generate.mjs +0 -301
  494. package/tools/demo-worker/index.mjs +0 -466
  495. package/tools/demo-worker/sign-core.mjs +0 -112
  496. package/tools/demo-worker/sign.mjs +0 -161
  497. package/tools/gt-render/browser.mjs +0 -182
  498. package/tools/gt-render/camera-math.mjs +0 -276
  499. package/tools/gt-render/page.mjs +0 -267
  500. package/tools/gt-render/render.mjs +0 -514
  501. package/tools/gt-render/scene-box.mjs +0 -31
  502. package/tools/gt-render/take-transform.mjs +0 -87
  503. package/tools/kimodo/compare-seam.mjs +0 -108
  504. package/tools/kimodo/constraints.mjs +0 -244
  505. package/tools/kimodo/edit.mjs +0 -259
  506. package/tools/kimodo/effector-constraints.mjs +0 -200
  507. package/tools/kimodo/generate.mjs +0 -646
  508. package/tools/kimodo/local-output.mjs +0 -265
  509. package/tools/kimodo/measure-pose.mjs +0 -65
  510. package/tools/kimodo/measure-preserve.mjs +0 -899
  511. package/tools/kimodo/measure-waypoints.mjs +0 -55
  512. package/tools/kimodo/mlx-generate.py +0 -111
  513. package/tools/kimodo/pose-constraints.mjs +0 -248
  514. package/tools/kimodo/preserve-mask.mjs +0 -543
  515. package/tools/kimodo/read-npz.mjs +0 -189
  516. package/tools/kimodo/run-edit-on-box.mjs +0 -155
  517. package/tools/kimodo/run-sequence-on-box.mjs +0 -178
  518. package/tools/kimodo/runner.mjs +0 -284
  519. package/tools/kimodo/seam-batch.mjs +0 -77
  520. package/tools/kimodo/setup-local.mjs +0 -30
  521. package/tools/kimodo/setup-on-box.sh +0 -339
  522. package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
  523. package/tools/morphgs/assets/gen_truth.py +0 -39
  524. package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
  525. package/tools/morphgs/assets/playback-check.mjs +0 -30
  526. package/tools/morphgs/demo-gate.sh +0 -26
  527. package/tools/morphgs/fbx2morphgs.mjs +0 -68
  528. package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
  529. package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
  530. package/tools/morphgs/setup-on-cluster.sh +0 -126
  531. package/tools/projflow/driver.py +0 -1069
  532. package/tools/projflow/generate.mjs +0 -805
  533. package/tools/projflow/hml22-to-cskel27.mjs +0 -735
  534. package/tools/projflow/line-edit-job.mjs +0 -547
  535. package/tools/projflow/replay.mjs +0 -452
  536. package/tools/projflow/runner.mjs +0 -269
  537. package/tools/projflow/service.mjs +0 -742
  538. package/tools/track/DESIGN.md +0 -513
  539. package/tools/track/backfill-provenance.mjs +0 -116
  540. package/tools/track/budget.mjs +0 -8
  541. package/tools/track/check-rig.mjs +0 -209
  542. package/tools/track/diagnostics.schema.json +0 -60
  543. package/tools/track/export-rig.mjs +0 -256
  544. package/tools/track/fallback.mjs +0 -7
  545. package/tools/track/fk-parity-fixture.mjs +0 -161
  546. package/tools/track/gate.mjs +0 -349
  547. package/tools/track/masks.mjs +0 -318
  548. package/tools/track/metrics.mjs +0 -201
  549. package/tools/track/publish-obs.mjs +0 -108
  550. package/tools/track/py/check_env.py +0 -61
  551. package/tools/track/py/eval_lr.py +0 -229
  552. package/tools/track/py/lr_viterbi.py +0 -294
  553. package/tools/track/py/masks.py +0 -405
  554. package/tools/track/py/objective.py +0 -382
  555. package/tools/track/py/rig.py +0 -508
  556. package/tools/track/py/scene.py +0 -326
  557. package/tools/track/py/test_joint_indices.py +0 -123
  558. package/tools/track/py/test_lr_viterbi.py +0 -195
  559. package/tools/track/py/test_masks.py +0 -229
  560. package/tools/track/py/test_rig.py +0 -288
  561. package/tools/track/py/test_scene.py +0 -354
  562. package/tools/track/py/test_track.py +0 -328
  563. package/tools/track/py/track.py +0 -411
  564. package/tools/track/remote.mjs +0 -140
  565. package/tools/track/rig-dump.mjs +0 -227
  566. package/tools/track/run-box-tests.mjs +0 -14
  567. package/tools/track/run-box.mjs +0 -168
  568. package/tools/track/setup-box.sh +0 -59
  569. package/tools/track/study-2d.mjs +0 -728
  570. /package/src/{ardy → motion}/collision-blockers.js +0 -0
  571. /package/src/{ardy → motion}/ground.js +0 -0
  572. /package/src/{ardy → motion}/ik-drag.js +0 -0
  573. /package/src/{ardy → motion}/ik-key-json.js +0 -0
  574. /package/src/{ardy → motion}/ik.js +0 -0
  575. /package/src/{ardy → motion}/physics-surface.js +0 -0
  576. /package/src/{ardy → motion}/playback-clock.js +0 -0
  577. /package/src/{ardy → motion}/range-pin.js +0 -0
@@ -0,0 +1 @@
1
+ {"model":"y-bot-tpose","units":"cm","mesh":"Alpha_Surface","bones":[{"name":"Hips","parent":-1,"localPos":[-0.000006757011760782916,99.79193878173828,0.00004844740033149719],"localQuat":[7.615435492247396e-11,-0.0000017453292503320135,0.00004363323128594654,0.9999999990465473],"worldPos":[-0.000006757011760782916,99.79193878173828,0.00004844740033149719],"worldQuat":[7.615435492247396e-11,-0.0000017453292503320135,0.00004363323128594654,0.9999999990465473]},{"name":"Spine","parent":0,"localPos":[0.0008597856133863019,9.923461876522225,-1.2273349078167588],"localQuat":[-0.06073022898235704,5.303745488019905e-22,0.000006119354919596912,0.9981542161661715],"worldPos":[-0.000008672608244745512,109.71540069587908,-1.227286457407732],"worldQuat":[-0.060730228859120175,-0.000004391963877518737,0.00004956605444176136,0.9981542149520963]},{"name":"Spine1","parent":1,"localPos":[0,11.731977989043784,-3.552713678800501e-15],"localQuat":[0.0001960924550491026,4.662287733052689e-14,-0.000009316072744031837,0.9999999807304797],"worldPos":[-0.0011632832276606084,121.36083978703566,-2.649627688070991],"worldQuat":[-0.06053449713743436,-0.00000494801144686156,0.00004026803743853935,0.9981661049195772]},{"name":"Spine2","parent":2,"localPos":[1.931491945550423e-11,13.458836780167971,6.235012506294879e-13],"localQuat":[0.057711730916465316,0.0000021958232674411106,0.000003285013706200134,0.9983332890868721],"worldPos":[-0.0022371547694859653,134.72103871836885,-4.27608729015328],"worldQuat":[-0.002827710078055566,-2.2517339024978275e-7,0.00004363254684471116,0.9999960010679366]},{"name":"Neck","parent":3,"localPos":[0.00002548122992670175,15.027761372130044,0.8779068542021755],"localQuat":[0.0028277058943183713,-8.816242878226746e-39,-7.234126583784003e-21,0.9999960020316957],"worldPos":[-0.003523660156014883,149.7535246254643,-3.4831824403326026],"worldQuat":[-4.186445695616128e-9,-1.017924801167934e-7,0.00004363300912729469,0.999999999048075]},{"name":"Head","parent":4,"localPos":[0.000002562548663041439,10.32183835340436,3.1424288991299827],"localQuat":[1.2407709188295404e-24,1.3234889800848435e-23,-3.3812794736012347e-21,1],"worldPos":[-0.0044224830930743595,160.07536296607333,-0.3407536277174854],"worldQuat":[-4.1864456956161264e-9,-1.0179248011679337e-7,0.000043633009127294685,0.999999999048075]},{"name":"HeadTop_End","parent":5,"localPos":[0.00015451594228192873,18.474670356296826,6.63639947863672],"localQuat":[6.93889473108785e-18,-6.61744490042423e-24,-1.0158249377722142e-20,1],"worldPos":[-0.005881529143937624,178.55003332101543,6.295645696100038],"worldQuat":[-4.186445688677232e-9,-1.0179248011679308e-7,0.00004363300912729468,0.999999999048075]},{"name":"LeftShoulder","parent":3,"localPos":[6.105824524896,9.10629188078309,0.757062475638635],"localQuat":[-0.45383506682997793,-0.5448493479758866,0.5511388470821386,-0.4397941465761588],"worldPos":[6.10279217248512,143.83199925791556,-3.5705353792059826],"worldQuat":[-0.4525659925709384,-0.5433084112379314,0.5526580275773418,-0.44109987213863294]},{"name":"LeftArm","parent":7,"localPos":[4.884981308350689e-15,12.92228632488431,2.842170943040401e-14],"localQuat":[-0.010451820107802023,-0.0010627185813176982,0.10115046260752789,0.9948156683526521],"worldPos":[18.75785325853472,143.5671732022338,-6.171454434247386],"worldQuat":[0.49997802104022876,0.5000219779933275,-0.4999777974641308,0.5000222015503447]},{"name":"LeftForeArm","parent":8,"localPos":[3.059411390893274e-9,27.404682159441652,-2.842170943040401e-14],"localQuat":[-1.0173904404505293e-20,6.815758221109549e-27,1.3234889800848457e-23,1],"worldPos":[46.162535310990236,143.5695947084291,-6.171442183765884],"worldQuat":[0.49997802104022876,0.5000219779933275,-0.4999777974641308,0.5000222015503447]},{"name":"LeftHand","parent":9,"localPos":[-0.000012820418092474029,27.614463806173113,2.3361064904747764e-7],"localQuat":[-3.397640826470449e-21,-1.8680226235633534e-27,5.2939559203393736e-23,1],"worldPos":[73.77699900937316,143.57203451753804,-6.171417016006557],"worldQuat":[0.49997802104022876,0.5000219779933275,-0.4999777974641308,0.5000222015503447]},{"name":"LeftHandRing1","parent":10,"localPos":[2.216630558205681,12.147010274148471,-0.009996226470974534],"localQuat":[5.56794949511021e-7,-3.067028835367668e-9,0.000004777353976607745,0.9999999999884335],"worldPos":[85.92400934395243,143.5831040665074,-8.388042142881478],"worldQuat":[0.49998068669282075,0.5000193094968617,-0.4999756886184537,0.500024313263825]},{"name":"LeftHandRing2","parent":11,"localPos":[0,3.601188659840844,0],"localQuat":[-0.000002306826384812874,1.861861504887997e-11,-0.000008071095064110734,0.999999999964768],"worldPos":[89.52519798990681,143.58341826103262,-8.388006124364832],"worldQuat":[0.4999754975118546,0.5000244982373176,-0.49997857087756026,0.5000214312542258]},{"name":"LeftHandRing3","parent":12,"localPos":[-7.140954494389007e-13,3.3073120118204997,2.2737367544323206e-13],"localQuat":[-3.2584970000852863e-21,-2.067951531382572e-25,-6.352747104407258e-22,1],"worldPos":[92.83250998771065,143.5837220743585,-8.388026432414401],"worldQuat":[0.49997549751185466,0.5000244982373176,-0.49997857087756026,0.5000214312542258]},{"name":"LeftHandRing4","parent":13,"localPos":[-0.0000241726316367874,3.660118102908669,0.000016886514032421474],"localQuat":[0.000008486035821629225,0.007396474405473809,0.0007707649842267434,0.9999723486255485],"worldPos":[96.49262807680708,143.5840414103271,-8.388024734185503],"worldQuat":[0.5040493957792119,0.5033194611486261,-0.4958855340273986,0.4966903097363882]},{"name":"LeftHandMiddle1","parent":10,"localPos":[-0.000018344155402694184,12.77552795411546,-0.0000010320898695681535],"localQuat":[5.567949752588633e-7,-2.6633364343577455e-9,2.0800236288001427e-7,0.9999999999998233],"worldPos":[86.55252691351437,143.5731644085546,-6.171392959489538],"worldQuat":[0.49997840212413347,0.5000215942797767,-0.49997797319957754,0.5000220284932966]},{"name":"LeftHandMiddle2","parent":15,"localPos":[-3.552713678800501e-15,3.61396789550858,-2.842170943040401e-14],"localQuat":[2.3697741078528623e-20,6.203854594147698e-25,-2.6469779601696844e-23,1],"worldPos":[90.16649479526663,143.5734797180353,-6.171389840137076],"worldQuat":[0.49997840212413347,0.5000215942797767,-0.49997797319957754,0.5000220284932966]},{"name":"LeftHandMiddle3","parent":16,"localPos":[0.000028508498060020315,3.4597625732240687,-8.526512829121202e-14],"localQuat":[1.692147750009982e-20,2.0679515313825724e-25,2.64697796016969e-23,1],"worldPos":[93.62625735534596,143.57378157349484,-6.171415362383127],"worldQuat":[0.49997840212413347,0.5000215942797767,-0.49997797319957754,0.5000220284932966]},{"name":"LeftHandMiddle4","parent":17,"localPos":[-0.000030473889779614183,3.680191040059995,-2.842170943040401e-14],"localQuat":[-0.00000133272714831852,0.004579424073341433,-0.000654144096597114,0.9999893004272004],"worldPos":[97.30644838137125,143.57410266077613,-6.171381711981186],"worldQuat":[0.5019349111684311,0.5026337814312043,-0.4980094305837711,0.4974004762403589]},{"name":"LeftHandThumb1","parent":10,"localPos":[-3.002975029424964,3.7888090485209744,2.1671489778191813],"localQuat":[0.25189492500135036,-0.05946403657250492,0.2219235197808198,0.940086659027326],"worldPos":[77.56599819190912,141.40522033116738,-3.168440292478436],"worldQuat":[0.6772116616355364,0.20343190021506413,-0.5147394802435296,0.484812432594653]},{"name":"LeftHandThumb2","parent":19,"localPos":[-1.9984014443252818e-15,4.744970523440218,2.842170943040401e-14],"localQuat":[0.0000069460704858849485,5.5796786860811154e-12,8.032883032279416e-7,0.9999999999755533],"worldPos":[81.24162844278966,139.28353174695044,-1.0464306132517085],"worldQuat":[0.6772151925776482,0.20342778079987783,-0.5147405038353289,0.48480814210593404]},{"name":"LeftHandThumb3","parent":20,"localPos":[-5.984102102729594e-13,4.3821287009303775,5.172751116333529e-12],"localQuat":[7.030691099565929e-18,7.121429504040547e-18,-1.5407439555097887e-32,1],"worldPos":[84.63615479208448,137.32403482337068,0.9133179986734019],"worldQuat":[0.6772151925776482,0.20342778079987775,-0.5147405038353289,0.48480814210593404]},{"name":"LeftHandThumb4","parent":21,"localPos":[-0.0000051284654249972306,3.459077859769903,4.03463474185628e-7],"localQuat":[0.009146816027813427,0.1256374250101491,0.07207247635857116,0.9894125182879566],"worldPos":[87.31565650284612,135.77728679427992,2.4602700847142343],"worldQuat":[0.7538118553684166,0.20866722684171796,-0.3911265183168664,0.4850213622280347]},{"name":"LeftHandIndex1","parent":10,"localPos":[-2.822044006965872,12.266617250897596,0.23182516767607808],"localQuat":[5.567949601161418e-7,-3.075281477739248e-9,0.00000487076476385117,0.9999999999879827],"worldPos":[86.04363543486608,143.34129324170544,-3.34936752423002],"worldQuat":[0.49998073339592125,0.5000192627891642,-0.4999756419148924,0.5000243599710406]},{"name":"LeftHandIndex2","parent":23,"localPos":[-1.3322676295501878e-15,3.891967773631521,0],"localQuat":[-3.0225470980600983e-21,0,-0.000006214320207710297,0.999999999980691],"worldPos":[89.93560319348254,143.34163280596658,-3.349327870283342],"worldQuat":[0.49997762610645813,0.5000223698198841,-0.4999787492167228,0.5000212529526508]},{"name":"LeftHandIndex3","parent":24,"localPos":[4.071321058063404e-11,3.415161132822689,-1.1368683772161603e-13],"localQuat":[4.6684518186119064e-23,-9.183549615799121e-41,2.1175823681357537e-22,1],"worldPos":[93.35076431329836,143.34193077006435,-3.3493355202090695],"worldQuat":[0.49997762610645813,0.5000223698198841,-0.4999787492167229,0.5000212529526508]},{"name":"LeftHandIndex4","parent":25,"localPos":[5.854722480158614e-7,3.0779876709090814,5.684341886080802e-14],"localQuat":[0.0000010393592226093013,0.004001602788212073,0.000022779581052790166,0.9999919932955144],"worldPos":[96.4287519724834,143.34219931663745,-3.3493430003052733],"worldQuat":[0.5019862492920715,0.5020073437901309,-0.4979631636001596,0.4980272281710877]},{"name":"LeftHandPinky1","parent":10,"localPos":[4.72583130478205,10.908194092064392,0.22613216873591568],"localQuat":[0.0000028521120612919424,-3.0577730863769185e-9,0.000141051374267014,0.9999999900481878],"worldPos":[84.68521515320175,143.3468662092345,-10.897243443373178],"worldQuat":[0.5000499694422342,0.49995002290857044,-0.49990869131728644,0.5000912946652625]},{"name":"LeftHandPinky2","parent":27,"localPos":[-5.329070518200751e-15,4.136657059551979,2.842170943040401e-14],"localQuat":[-0.0000059544873416476465,2.190560405006969e-9,-0.0003678839387923365,0.9999999323129735],"worldPos":[88.82187203349876,143.3472081321215,-10.896074631422186],"worldQuat":[0.4998630353195086,0.5001369272162459,-0.5000896549937187,0.49991032888321396]},{"name":"LeftHandPinky3","parent":28,"localPos":[4.3876013933186186e-13,2.594834461051775,0],"localQuat":[0.0000036591694282576963,8.409112616016821e-10,0.00022980932036022433,0.999999973587143],"worldPos":[91.41670621645012,143.34745351466333,-10.897250657097295],"worldQuat":[0.49997978792115133,0.5000202113293842,-0.49997658739741363,0.5000234114387793]},{"name":"LeftHandPinky4","parent":29,"localPos":[-2.948752353404416e-13,2.9238662720287607,-2.842170943040401e-14],"localQuat":[-0.0000010497831164166655,0.004099894588367042,-0.0005750644579927158,0.9999914300453439],"worldPos":[94.34057247729058,143.3477086145383,-10.89723194250163],"worldQuat":[0.5017372856540723,0.5023540149301887,-0.4982094589732469,0.49768210220741194]},{"name":"RightShoulder","parent":3,"localPos":[-6.1056956701096174,9.10638358733786,0.7570756312724551],"localQuat":[0.4538375688887134,-0.5448472538987562,0.5511399888422243,0.43979272809263187],"worldPos":[-6.1087279840345,143.8310253866605,-3.5705252284969617],"worldQuat":[0.45261579666489365,-0.5432669079313696,0.5526977464106563,0.44105012013225253]},{"name":"RightArm","parent":31,"localPos":[3.9968028886505635e-15,12.922286714484947,0],"localQuat":[-0.01045541384979725,0.0010630628959740092,-0.10114940861202837,0.9948157373885607],"worldPos":[-18.763745414580892,143.56389953844294,-6.171423447408117],"worldQuat":[0.5000215299672571,-0.4999784691060287,0.5000215360351153,0.4999784630368383]},{"name":"RightForeArm","parent":32,"localPos":[8.327427636345419e-9,27.404682159441318,-2.842170943040401e-14],"localQuat":[-3.388329060809388e-21,-1.5146129380243438e-28,8.271806125530284e-25,1],"worldPos":[-46.16842747236397,143.56153906740224,-6.171423771692651],"worldQuat":[0.5000215299672571,-0.49997846910602883,0.5000215360351153,0.4999784630368383]},{"name":"RightHand","parent":33,"localPos":[0.000012842842382454478,27.614463806155165,0.000015492399938921153],"localQuat":[-1.9727179218464944e-25,-7.573064690121704e-29,0,1],"worldPos":[-73.78289117474843,143.55914503465877,-6.17141126400836],"worldQuat":[0.5000215299672571,-0.4999784691060287,0.5000215360351153,0.4999784630368383]},{"name":"RightHandThumb1","parent":34,"localPos":[3.002974470681663,3.7888088905192205,2.1671490371761024],"localQuat":[0.25189499102226326,0.05946427874712486,-0.2219234615465524,0.9400866397658112],"worldPos":[-77.57151342274972,141.3916696607838,-3.168436839313407],"worldQuat":[0.6772291629398663,-0.20337279117491877,0.5147821060302558,0.4847675236487542]},{"name":"RightHandThumb2","parent":35,"localPos":[-6.8833827526759706e-15,4.744970470128291,2.842170943040401e-14],"localQuat":[0.000008453832451066965,-3.3376070678072775e-12,-3.9480215616198235e-7,0.9999999999641884],"worldPos":[-81.24677425676067,139.26933968812125,-1.0464288158806956],"worldQuat":[0.6772333413527709,-0.20336817191604672,0.5147836339017984,0.48476200168592604]},{"name":"RightHandThumb3","parent":36,"localPos":[-1.7763568394002505e-13,4.382135391768333,-4.092726157978177e-12],"localQuat":[-1.4347996972659013e-17,-5.998687332454958e-18,-1.387778780781447e-17,1],"worldPos":[-84.64095942776746,137.30923516924733,0.9133180789494266],"worldQuat":[0.6772333413527709,-0.20336817191604672,0.5147836339017984,0.48476200168592604]},{"name":"RightHandThumb4","parent":37,"localPos":[0.000011177533225659175,3.4590709023307085,-0.000023241859054223823],"localQuat":[0.00923206336161341,-0.1271302153500302,-0.0723276818427547,0.989202397788438],"worldPos":[-87.32019182850055,135.76203483248253,2.460268746809576],"worldQuat":[0.7545499013151971,-0.2090649481886763,0.389944180490974,0.4846543407061524]},{"name":"RightHandIndex1","parent":34,"localPos":[2.822042502024897,12.266617102415225,0.23182522345669554],"localQuat":[5.567922673046469e-7,-7.224337929733461e-9,-0.000004743924457641052,0.9999999999885925],"worldPos":[-86.04948829791044,143.32626324098368,-3.3493689108641775],"worldQuat":[0.5000241838181078,-0.4999758222398485,0.5000194389411731,0.4999805530753941]},{"name":"RightHandIndex2","parent":39,"localPos":[0,3.891967773619811,0],"localQuat":[1.695401251774016e-20,-4.135903062840235e-25,0.00000602627167052741,0.9999999999818419],"worldPos":[-89.94145605654246,143.32592367674323,-3.3493320316989923],"worldQuat":[0.5000211708188947,-0.4999788355123435,0.5000224519507367,0.4999775398133359]},{"name":"RightHandIndex3","parent":40,"localPos":[-5.1669779566054785e-12,3.4151611328221207,1.1368683772161603e-13],"localQuat":[-1.3593959205239575e-20,0,0,1],"worldPos":[-93.35661717635494,143.32562571266394,-3.349340831998884],"worldQuat":[0.5000211708188947,-0.4999788355123435,0.5000224519507367,0.4999775398133359]},{"name":"RightHandIndex4","parent":41,"localPos":[-0.0000012771572572845002,3.0779876709101757,-2.842170943040401e-14],"localQuat":[-0.00007290381402922513,-0.006709307422924062,0.0013745331778991744,0.9999765449936721],"worldPos":[-96.4346048355366,143.3253571661075,-3.3493500406116747],"worldQuat":[-0.5026405594004304,0.5040453607575476,-0.49730671352060296,-0.49596045712511533]},{"name":"RightHandMiddle1","parent":34,"localPos":[0.000016632154487439266,12.775527954114011,-0.0000010320893863990932],"localQuat":[5.567949633221699e-7,-7.289108692409176e-9,-3.662527039828292e-7,0.9999999999997777],"worldPos":[-86.55841908156046,143.55804566121927,-6.171394786911078],"worldQuat":[0.5000219951158138,-0.4999780112066047,0.5000216276573223,0.4999783641170999]},{"name":"RightHandMiddle2","parent":43,"localPos":[8.881784197001252e-16,3.6139678955093757,0],"localQuat":[-3.3759614098155274e-21,-4.135903062765133e-25,0,1],"worldPos":[-90.17238696331393,143.55773035173834,-6.171392183522983],"worldQuat":[0.5000219951158138,-0.4999780112066047,0.5000216276573223,0.4999783641170999]},{"name":"RightHandMiddle3","parent":44,"localPos":[-0.000029421479796454264,3.4597625732165085,1.4210854715202004e-13],"localQuat":[3.4003021678244415e-21,-8.271806125530284e-25,-7.940933880509075e-23,1],"worldPos":[-93.63214952338268,143.55742849627876,-6.1714191126993185],"worldQuat":[0.5000219951158138,-0.4999780112066047,0.5000216276573223,0.4999783641170999]},{"name":"RightHandMiddle4","parent":45,"localPos":[0.000028549065814509333,3.680191040067001,-5.684341886080802e-14],"localQuat":[-0.00005158123071926063,-0.006695195594000001,-0.0017083442773867367,0.9999761263426065],"worldPos":[-97.31234054942114,143.557107408997,-6.171387912540353],"worldQuat":[0.504186145435319,-0.5024851098604104,0.49578202059538456,0.49749897806327625]},{"name":"RightHandRing1","parent":34,"localPos":[-2.216632303077052,12.147002761381543,-0.009996270293299858],"localQuat":[5.567954667309114e-7,-7.224304767843245e-9,-0.000004803651127566965,0.9999999999883074],"worldPos":[-85.92989472518438,143.5680950366908,-8.38804371451417],"worldQuat":[0.5000242136815972,-0.49997579237346873,0.5000194090805982,0.49998058293828956]},{"name":"RightHandRing2","parent":47,"localPos":[0,3.6011962892353893,-8.526512829121202e-14],"localQuat":[-5.732183384702703e-21,0,0.000008071083662125689,0.9999999999674287],"worldPos":[-89.53109100054763,143.5677808414962,-8.388009160440863],"worldQuat":[0.5000201783188615,-0.4999798280944457,0.5000234444494263,0.4999765472235214]},{"name":"RightHandRing3","parent":48,"localPos":[-6.055600465515454e-12,3.307312011785328,-1.1368683772161603e-13],"localQuat":[3.2821615918857455e-21,-3.6734198463196485e-40,2.1175823681357546e-22,1],"worldPos":[-92.83840299967426,143.56749228695628,-8.38803081342569],"worldQuat":[0.5000201783188615,-0.4999798280944457,0.5000234444494263,0.4999765472235214]},{"name":"RightHandRing4","parent":49,"localPos":[0.00002417262415121968,3.6601181029476635,-2.842170943040401e-14],"localQuat":[-0.00006164489635359998,-0.007613221748708619,-0.000300224892743606,0.9999709720384515],"worldPos":[-96.49852108877111,143.56717295098406,-8.388030603602541],"worldQuat":[0.5039317385023292,-0.503652452411389,0.49602123868179077,0.49633651979941534]},{"name":"RightHandPinky1","parent":34,"localPos":[-4.725833119502555,10.90819434071372,0.2261320753251539],"localQuat":[5.567949828639406e-7,-7.530380981813863e-9,-0.000003132050030138696,0.99999999999494],"worldPos":[-84.69106594001192,143.3320733953033,-10.897244515904388],"worldQuat":[0.5000233780731588,-0.4999766283665967,0.5000202446951756,0.49997974695226793]},{"name":"RightHandPinky2","parent":51,"localPos":[0,4.13665008553545,-2.842170943040401e-14],"localQuat":[1.470867824118891e-22,8.271806125977124e-25,0.000010394374390791114,0.9999999999459783],"worldPos":[-88.8277160097222,143.33171248313417,-10.897218653721097],"worldQuat":[0.5000181811018849,-0.4999818257697831,0.5000254416448413,0.49997454952763204]},{"name":"RightHandPinky3","parent":52,"localPos":[-3.950617610826157e-12,2.5948410036845218,-8.526512829121202e-14],"localQuat":[6.674018442413745e-21,1.836709923259698e-40,-0.000010428465638715964,0.9999999999456235],"worldPos":[-91.42255700325643,143.33148608987582,-10.897256374372848],"worldQuat":[0.5000233951179858,-0.49997661132017523,0.5000202276502416,0.4999797639985816]},{"name":"RightHandPinky4","parent":53,"localPos":[4.362732397567015e-12,2.923866272034857,5.684341886080802e-14],"localQuat":[-0.00008226663950025322,-0.00849884034311731,0.0022061069470672434,0.9999614472754239],"worldPos":[-94.34642326410449,143.33123099000105,-10.897237895108226],"worldQuat":[-0.5031095764062739,0.5053508241180749,-0.4968132089402998,-0.4946493041680384]},{"name":"LeftUpLeg","parent":0,"localPos":[9.123873709849553,-6.657188518716367,-0.05540310527662988],"localQuat":[0.000020251728747483253,-0.006350177975401161,0.9999754277247583,-0.002969642442257367],"worldPos":[9.12444806072654,93.13554649657034,-0.05532280954860631],"worldQuat":[0.000018783520922709306,-0.006350171978846871,0.999975297231096,-0.00301328568169704]},{"name":"LeftLeg","parent":55,"localPos":[-4.618527782440651e-14,40.59943638074365,1.170175067954915e-13],"localQuat":[-0.018114309191591866,0.00018249364298742092,-0.005920146666904975,0.9998183786878614],"worldPos":[9.369107731941927,52.540121711606496,-0.5709414745281038],"worldQuat":[-0.0000715314874584385,-0.02446331907456045,0.9996964939479204,0.00290876113461602]},{"name":"LeftFoot","parent":56,"localPos":[-1.0658141036401503e-14,42.09902591219656,2.0872192862952943e-14],"localQuat":[0.5405498192560871,0.01436647216366454,0.024951033886733327,0.8408192096329419],"worldPos":[9.12441738143423,10.49219684921195,-2.6300976499043784],"worldQuat":[-0.01346031169880001,0.5198601039256607,0.853859207560786,-0.022107600933591907]},{"name":"LeftToeBase","parent":57,"localPos":[1.7763568394002505e-15,15.721559146548017,-1.509903313490213e-14],"localQuat":[0.2276920621809942,-0.032521469150786096,-0.015365592016704316,0.9730686396375217],"worldPos":[9.497939603229476,3.2836504838127345,11.336461068911172],"worldQuat":[0.0016492651748272183,0.7007886739142866,0.7132730439227728,0.01157925951782756]},{"name":"LeftToe_End","parent":58,"localPos":[1.7763568394002505e-15,9.999999999999991,4.890746918562172e-9],"localQuat":[3.842630640765734e-10,-2.181956872127079e-18,8.673617379884037e-19,1],"worldPos":[9.355871856763304,3.108427383452366,21.333916426176543],"worldQuat":[0.0016492651792767014,0.700788674188371,0.7132730436534856,0.011579259517193808]},{"name":"RightUpLeg","parent":0,"localPos":[-9.125032356625555,-6.655601347887028,-0.05535274484958799],"localQuat":[-0.000017972283601838397,-0.006333801286546503,0.9999752669985558,0.0030574547301418053],"worldPos":[-9.12445807483328,93.1355411499169,-0.055336149820714026],"worldQuat":[-0.000019441205218510228,-0.006333807477113975,0.9999753994199062,0.00301381152055421]},{"name":"RightLeg","parent":60,"localPos":[7.105427357601002e-15,40.59943859177964,2.6645352591003757e-14],"localQuat":[-0.018147073530042527,-0.00018249394989624574,0.005920149654138874,0.9998177845219228],"worldPos":[-9.369160167563622,52.54009755727,-0.5696263108436963],"worldQuat":[0.00007086285029500266,-0.024479715368387448,0.9996960941175567,-0.0029082503401009767]},{"name":"RightFoot","parent":61,"localPos":[-2.4868995751603507e-14,42.09902387472938,-6.217248937900877e-14],"localQuat":[0.5405636018310247,-0.014366037304083883,-0.024951225824318232,0.8408103506008421],"worldPos":[-9.12451164224619,10.492242047309674,-2.6301615125796047],"worldQuat":[0.013459958226241265,0.5198600714589466,0.8538592128932476,0.02210837363015364]},{"name":"RightToeBase","parent":62,"localPos":[3.552713678800501e-15,15.721558809599616,2.6645352591003757e-15],"localQuat":[0.22770869920802236,0.03211960072148292,0.015257901862228916,0.9730797891155923],"worldPos":[-9.498060396707743,3.2836958492734345,11.33639620371245],"worldQuat":[-0.0013617607248561205,0.700801240791512,0.7132661380535977,-0.011277536030161229]},{"name":"RightToe_End","parent":63,"localPos":[3.1880595940947387e-9,9.999999999999998,5.687534443410414e-9],"localQuat":[-3.109963189751316e-10,-1.6439215440311446e-16,-1.7347234759768052e-18,1],"worldPos":[-9.356269180688868,3.1086870931784847,21.33385924122101],"worldQuat":[-0.0013617607213487338,0.7008012405696887,0.7132661382715444,-0.011277536030584614]}],"landmarks":{"mouth":[0,158.399150390625,12.493875312805176],"headEllipsoid":{"centre":[-0.000016689300537109375,167.32984161376953,0.6807799339294434],"radii":[8.005595684051514,13.133369445800781,12.374487400054932]},"headJoint":[-0.0044224830930743595,160.07536296607333,-0.3407536277174854],"headTop":[-0.005881529143937624,178.55003332101543,6.295645696100038],"sole":{"ball":3.3,"tip":2.6}}}
@@ -0,0 +1,60 @@
1
+ // Scene records -> what the motion compiler and QA collide with: each drawable object as an
2
+ // oriented box on its base pivot (bottom centre), sized by objectSize (scene-objects.js, the
3
+ // one owner of footprint x scale) and turned by the renderer's Euler XYZ (rotX, rot, rotZ).
4
+ // Every entry lists its `ancestors` (parent ids, nearest group first) and their poses
5
+ // (`ancestorPoses`, the same order), so a group (an Empty, which has no box of its own) is known
6
+ // by its parts (object-pose.js partsOf) and by its root pose. A saved take keeps scene.objects
7
+ // and scene.others (take-source.js), so the groups are rebuilt from the entries: groupsOf.
8
+ // `others` lists the records with no box (an Empty, a light, an effect, a plane) by id with their
9
+ // renderer and ancestors: a switch entry (C15) may name them, and a skill finds a kit's lit parts
10
+ // there. A body that glows (record.glow) says so (`glow: true`).
11
+ import { objectSize } from "../object-size.js";
12
+ import { mul, rx, ry, rz } from "./compiler/math.js";
13
+
14
+ const NO_BODY = new Set(["empty", "plane", "cutout"]);
15
+
16
+ /** Parent records of a record, nearest first (stops at a cycle, a missing parent or an attached record). */
17
+ function ancestorsOf(o, byId) {
18
+ const out = [];
19
+ for (let p = byId.get(o.parent); p && !out.includes(p) && !p.attach; p = byId.get(p.parent)) out.push(p);
20
+ return out;
21
+ }
22
+
23
+ const poseOf = o => ({ pos: [o.x ?? 0, o.y ?? 0, o.z ?? 0], R: mul(rx(o.rotX ?? 0), mul(ry(o.rot ?? 0), rz(o.rotZ ?? 0))) });
24
+
25
+ const groupCache = new WeakMap();
26
+
27
+ /**
28
+ * The groups of a motion scene, rebuilt from its body entries: { id: { pos, R, ancestors,
29
+ * children } }. A group is body-less; `children` lists its direct children (bodies and groups).
30
+ */
31
+ export function groupsOf(scene) {
32
+ const objects = scene?.objects ?? {};
33
+ if (groupCache.has(objects)) return groupCache.get(objects);
34
+ const groups = {};
35
+ for (const [id, o] of Object.entries(objects)) {
36
+ (o.ancestors ?? []).forEach((g, i) => {
37
+ const pose = o.ancestorPoses?.[i];
38
+ groups[g] ??= { pos: pose?.pos ?? [0, 0, 0], R: pose?.R ?? [[1, 0, 0], [0, 1, 0], [0, 0, 1]], ancestors: o.ancestors.slice(i + 1), children: [] };
39
+ const child = i ? o.ancestors[i - 1] : id;
40
+ if (!groups[g].children.includes(child)) groups[g].children.push(child);
41
+ });
42
+ }
43
+ groupCache.set(objects, groups);
44
+ return groups;
45
+ }
46
+
47
+ export function motionScene(objects = []) {
48
+ const out = {}, others = {}, byId = new Map(objects.filter(Boolean).map(o => [o.id, o]));
49
+ for (const o of objects) {
50
+ if (!o || o.hidden) continue;
51
+ const size = objectSize(o), up = ancestorsOf(o, byId);
52
+ if (NO_BODY.has(o.renderer) || !(size.width > 0 && size.height > 0 && size.depth > 0)) {
53
+ others[o.id] = { renderer: o.renderer, ancestors: up.map(p => p.id) };
54
+ continue;
55
+ }
56
+ out[o.id] = { name: o.name, renderer: o.renderer, ...poseOf(o), half: [size.width / 2, size.height / 2, size.depth / 2],
57
+ ancestors: up.map(p => p.id), ...(up.length ? { ancestorPoses: up.map(poseOf) } : {}), ...(o.glow ? { glow: true } : {}) };
58
+ }
59
+ return { objects: out, groups: groupsOf({ objects: out }), others };
60
+ }
@@ -0,0 +1,89 @@
1
+ // A JSON Schema fragment (describe.js) -> one short type line, for motion.describe
2
+ // { topic: "essentials" }: `{f: int, set: object, step?: string[]}`. `?` marks an optional
3
+ // field, `=v` a default, `lo..hi` a range, `A | B` a choice, `[key]: T` a map, `a_l|r` a field
4
+ // that has a twin with the same type, `a|b?: T` optional fields with the same schema; a $ref to a
5
+ // shared shape keeps its name (vec3, key, ...). With { means: true } each field also says what it
6
+ // means, `hand_l|r?: vec3 (the WRIST target in world metres)`, from the schema's description.
7
+
8
+ const BARE = { integer: "int", number: "number", string: "string", boolean: "bool" };
9
+ /** Descriptions that say only the unit: the essentials notes give the units once. */
10
+ const UNIT_ONLY = /^(degrees|m)$/;
11
+ const range = s => (s.minimum !== undefined && s.maximum !== undefined ? ` ${s.minimum}..${s.maximum}` : "");
12
+ /** A literal: strings in single quotes, so the JSON answer needs no escapes. */
13
+ const lit = v => (typeof v === "string" ? `'${v}'` : JSON.stringify(v));
14
+ const dflt = s => (s.default !== undefined ? `=${lit(s.default)}` : "");
15
+ const wrap = t => (/[ |]/.test(t) && !/^[{[].*[}\]]$/.test(t) ? `(${t})` : t);
16
+ /** The key name of a map from its description: "scene object or group id -> hinge or carry" -> "scene object or group id". */
17
+ const keyOf = s => s.description?.match(/^(?:[^:]*: )?(.+?) -> /)?.[1] ?? "name";
18
+
19
+ /** A value as a JS literal with single-quoted strings: an example inside a JSON string needs no escapes. */
20
+ export function literal(v) {
21
+ if (Array.isArray(v)) return `[${v.map(literal).join(", ")}]`;
22
+ if (v && typeof v === "object") return `{${Object.entries(v).map(([k, x]) => `${k}: ${literal(x)}`).join(", ")}}`;
23
+ return lit(v);
24
+ }
25
+
26
+ /** The tail a description shares with an earlier one in the same line, from a word after ", " or ": ". */
27
+ function sharedTail(d, earlier) {
28
+ let i = 0;
29
+ while (i < d.length && i < earlier.length && d[d.length - 1 - i] === earlier[earlier.length - 1 - i]) i += 1;
30
+ const tail = d.slice(d.length - i), cut = tail.search(/[,:] \S/);
31
+ return cut < 0 || tail.length - cut < 40 ? "" : tail.slice(cut + 2);
32
+ }
33
+
34
+ /** The fields of an object schema: `{ a: T, b?: T }`, a map `{ [key]: T }`, or both. */
35
+ function objectLine(s, opts) {
36
+ const req = new Set(s.required ?? []), props = Object.entries(s.properties ?? {});
37
+ if (opts.depth === 0) return "object";
38
+ const inner = { ...opts, depth: opts.depth === undefined ? undefined : opts.depth - 1, seen: undefined };
39
+ // a long table of optional numbers with defaults (checks.limits): the names only
40
+ if (props.length > 8 && !req.size && props.every(([, v]) => v.type === "number" && v.default !== undefined)) return `{ [${props.map(([k]) => k).join("|")}]: number }`;
41
+ const twinned = new Set(props.map(([, v]) => v.$ref?.match(/^#\/properties\/(.+)$/)?.[1]).filter(Boolean));
42
+ const said = [];
43
+ /** "(meaning)" once: a meaning that ends like an earlier field's says "as <that field>" instead of the tail;
44
+ * a field a sibling choice already explained (`opts.seen`, a switch's visible after a carry's) says nothing. */
45
+ const mean = (name, d) => {
46
+ if (opts.seen?.has(`${name}\0${d}`)) return "";
47
+ opts.seen?.add(`${name}\0${d}`);
48
+ for (const [n, e] of said) { const tail = sharedTail(d, e); if (tail) return ` (${d.slice(0, -tail.length - 2)}, as ${n})`; }
49
+ said.push([name, d]);
50
+ return ` (${d})`;
51
+ };
52
+ const typed = (name, v, t = briefType(v, inner)) => t + (opts.means && v.description && !UNIT_ONLY.test(v.description) && !t.includes(v.description) ? mean(name, v.description) : "");
53
+ // optional fields that read the same share one entry: `pitch|spine_pitch?: T`
54
+ const groups = new Map();
55
+ for (const [k, v] of props.filter(([, v]) => !v.$ref?.startsWith("#/properties/"))) {
56
+ const name = twinned.has(k) ? k.replace(/_l$/, "_l|r") : k, t = typed(name, v), same = req.has(k) ? `${k}\0` : t;
57
+ groups.set(same, { names: [...(groups.get(same)?.names ?? []), name], t, req: req.has(k) });
58
+ }
59
+ const fields = [...groups.values()].map(g => `${g.names.join("|")}${g.req ? "" : "?"}: ${g.t}`);
60
+ for (const [p, v] of Object.entries(s.patternProperties ?? {})) fields.push(`/${p}/: ${typed(p, v)}`);
61
+ const extra = s.additionalProperties && typeof s.additionalProperties === "object" ? s.additionalProperties : null;
62
+ if (extra) fields.push(`[${s.propertyNames?.enum?.join("|") ?? keyOf(s)}]: ${typed("", extra)}`);
63
+ return fields.length ? `{${fields.join(", ")}}` : `object${s.description ? ` (${s.description})` : ""}`;
64
+ }
65
+
66
+ /** schema -> type line; opts.means adds each field's meaning, opts.depth stops at that many object levels ("object"). */
67
+ export function briefType(s, opts = {}) {
68
+ if (!s || typeof s !== "object") return "any";
69
+ const title = s.title ? `${s.title} ` : "", brief = x => briefType(x, opts);
70
+ if (s.$ref) return s.$ref.split("/").pop() + dflt(s);
71
+ if ("const" in s) return lit(s.const);
72
+ if (s.enum) return s.enum.map(lit).join("|") + dflt(s);
73
+ if (s.oneOf) {
74
+ const shapes = s.oneOf.filter(o => !(Object.keys(o).length === 1 && o.required)), picks = s.oneOf.flatMap(o => (shapes.includes(o) ? [] : o.required));
75
+ const own = s.type === "object" || s.properties ? objectLine(s, opts) : "";
76
+ // the choices share what they explained: a field that reads the same in an earlier choice says nothing more
77
+ const seen = new Set(), choice = shapes.length && shapes.every(o => o.pattern && !o.type) ? `string: ${shapes.map(o => o.description ?? o.pattern).join("; ")}`
78
+ : shapes.map(x => briefType(x, { ...opts, seen })).join(" | ");
79
+ return [title + own, choice, picks.length ? `(one of ${picks.join("|")})` : ""].filter(Boolean).join(" ") + (own ? "" : dflt(s));
80
+ }
81
+ if (s.type === "array") {
82
+ if (!s.items && !s.prefixItems) return `array${s.description ? ` (${s.description})` : ""}`;
83
+ if (s.prefixItems) return `[${s.prefixItems.map(brief).join(", ")}]`;
84
+ const n = s.minItems === s.maxItems && s.maxItems ? ` (${s.maxItems})` : s.maxItems ? ` (<= ${s.maxItems})` : "";
85
+ return `${wrap(brief(s.items))}[]${n}`;
86
+ }
87
+ if (s.type === "object" || s.properties) return title + objectLine(s, opts);
88
+ return (BARE[s.type] ?? "any") + range(s) + dflt(s);
89
+ }
@@ -0,0 +1,44 @@
1
+ // C1. The motion spec's field tables, the one source the validator (compiler/validate*.js),
2
+ // the skills expander and motion.describe (describe.js) read. Channels, ranges and presets stay
3
+ // in compiler/vocab.js, FIX_KEYS in fix/index.js, QA_LIMITS in qa/checks.js and the skill names
4
+ // in skills/index.js; import those, never copy them here. See docs/motion-api-v3.1.md.
5
+
6
+ /** Top-level spec fields. */
7
+ export const SPEC_FIELDS = ["schema", "fps", "frames", "label", "keys", "anchors", "props", "fits", "objects", "generators", "checks", "fix", "use", "channels", "detourRadius", "search", "goals", "flow", "idle"];
8
+ /** One key: { f, set, step?, src? } (src is written by the skills expander). */
9
+ export const KEY_FIELDS = ["f", "set", "step", "src"];
10
+ /** One spec.use entry. */
11
+ export const USE_FIELDS = ["skill", "args", "f0"];
12
+ /** Anchor fields by anchor kind (besides `kind`). */
13
+ export const ANCHOR_FIELDS = { world: ["p"], body: ["p"], bone: ["bone", "offset"], segment: ["from", "to", "t", "tMin", "offset", "reach"],
14
+ object: ["object", "local"], landmark: ["name"], prop: ["prop", "point", "offset"] };
15
+ export const PROP_FIELDS = ["hand", "origin", "points"];
16
+ export const FIT_FIELDS = ["side", "anchor", "effector", "offset", "orient"];
17
+ /** spec.objects[id]: a hinge or a carry (a body or a group id), see C3; carry keys: C14; a switch (any record, C15) moves nothing; a follow (any record, C16) rides a point of the body; a free entry (C17) moves by keys and falls. */
18
+ export const OBJECT_FIELDS = { hinge: ["pivot", "axis", "channel"], carry: ["prop", "at", "along", "visible", "level", "grab", "release", "keys", "fall"], switch: ["visible", "level"],
19
+ follow: ["follow", "offset", "aim", "visible", "level"], free: ["keys", "fall", "visible", "level"] };
20
+ /** One spec.objects[id].fall entry (C17): the frame it starts to fall, what it lands on, how much it bounces. */
21
+ export const FALL_FIELDS = ["at", "onto", "bounce"];
22
+ /** One spec.objects[id].keys entry (C14): the held object's world pose at frame f; aim (+ roll) in place of rot (C16). */
23
+ export const OBJECT_KEY_FIELDS = ["f", "pos", "rot", "aim", "roll", "lean"];
24
+ export const WALK_FIELDS = ["type", "f0", "steps", "step", "period", "swing", "halfWidth", "lift", "heading", "turnDistance", "pelvisHigh", "pelvisLow", "firstStep", "armSwing", "vary"];
25
+ /** spec.checks keys. */
26
+ export const CHECK_FIELDS = ["contacts", "orient", "below", "clearance", "appear", "supports", "allow", "limits", "mouthPoints"];
27
+ /** Fields of one entry of each spec.checks list. */
28
+ export const CHECK_ENTRY_FIELDS = {
29
+ contacts: ["name", "point", "target", "tol", "when"],
30
+ orient: ["name", "from", "to", "along", "minCos", "when"],
31
+ below: ["name", "joint", "ref", "min", "when"],
32
+ clearance: ["name", "part", "object", "min", "frames"],
33
+ appear: ["name", "channel", "joint", "anchor", "tol"],
34
+ supports: ["object", "part", "tol"],
35
+ allow: ["part", "object", "depth"],
36
+ };
37
+ /** One spec.goals entry (C8): exactly one of near | above | moved | still | speed; after / before order it on another goal. */
38
+ export const GOAL_FIELDS = ["name", "near", "above", "moved", "still", "speed", "tol", "by", "at", "mode", "after", "before"];
39
+ /** One motion.compile probes entry (C5): exactly one of distance | position. */
40
+ export const PROBE_FIELDS = ["name", "distance", "position", "frames", "every"];
41
+ /** Point reference kinds (C2, refs.js). */
42
+ export const REF_KINDS = ["joint", "bone", "prop", "anchor", "landmark", "object"];
43
+ /** motion.describe topics (C9); examples: whole specs that compile (schema/spec-examples.js). */
44
+ export const DESCRIBE_TOPICS = ["essentials", "spec", "skills", "anchors", "props", "objects", "checks", "goals", "probes", "channels", "refs", "fix", "examples"];
@@ -0,0 +1,46 @@
1
+ // motion.describe { topic: "examples" }: whole specs, each compiled at QA 0 on the scene its `scene`
2
+ // line names (test/bus/verify-motion3-examples.mjs builds those scenes and compiles every spec on
3
+ // both rigs). They come from the skills' and kits' own examples: reachGrip, smokeCigarette with
4
+ // args.kit and the squat of the smoke pacing test, the sword kit's props and carry, a hinge.
5
+ // Kept out of essentials (its budget is spent).
6
+ const SCHEMA = "cozyclay.motion-spec.v1";
7
+
8
+ export const SPEC_EXAMPLES = [
9
+ { name: "reachGrip carry: take a lantern off its hook and walk off with it",
10
+ scene: "lantern: a 14 x 20 x 14 cm box hanging at (0.3, 0.95, 0.4); the character at the origin, yaw 0",
11
+ spec: { schema: SCHEMA, fps: 24, frames: "auto", label: "take the lantern and walk off",
12
+ use: [{ skill: "standIdle", f0: 0, args: { at: [0, 0], heading: 0 } },
13
+ { skill: "reachGrip", f0: 10, args: { anchor: "handle", side: "l", define: { kind: "object", object: "lantern", local: [0, 0.22, 0] } } },
14
+ { skill: "walkTo", f0: 70, args: { to: [0, 1.6], steps: 4 } }],
15
+ objects: { lantern: { prop: "handleGrip", grab: 30 } },
16
+ goals: [{ name: "lantern carried off", moved: "object:lantern", by: 0.8, at: [170, 184] }] } },
17
+ { name: "squat and smoke, dressed by kits (smokeCigarette args.kit)",
18
+ scene: "object.createKit cigarette, lighter and exhale answered rootIds cig, lighter, exhale",
19
+ spec: { schema: SCHEMA, fps: 24, frames: 240, label: "squat and smoke",
20
+ keys: [{ f: 0, set: { root: [0, 0.45, -0.12], yaw: 0, pitch: 22, spine_pitch: 10, head_pitch: -12, foot_l: [0.16, 0.101, 0.02], foot_r: [-0.16, 0.101, 0.02],
21
+ fyaw_l: 15, fyaw_r: -15, knee_l: [0.45, 0, 1], knee_r: [-0.45, 0, 1] } }],
22
+ use: [{ skill: "smokeCigarette", f0: 1, args: { kit: { cig: "cig", lighter: "lighter", exhale: "exhale" } } }], fix: { retime: true },
23
+ goals: [{ name: "cigarette at the mouth", near: ["prop:cig.origin", "landmark:mouth"], tol: 0.08, at: [40, 230], mode: "any" }] } },
24
+ { name: "aim keys: raise a held sword to guard, then point it at a target",
25
+ scene: "object.createKit sword answered rootId sword and the props and bind below",
26
+ spec: { schema: SCHEMA, fps: 24, frames: 60, label: "sword to guard, then point",
27
+ use: [{ skill: "standIdle", f0: 0, args: { at: [0, 0], heading: 0 } }],
28
+ props: { swordGrip: { hand: "r", origin: ["RightHandIndex2", "RightHandMiddle2"], points: { tip: [0, 0.87, -0.015] } } },
29
+ anchors: { target: { kind: "world", p: [-0.25, 1.52, 1.13] } },
30
+ objects: { sword: { prop: "swordGrip", at: [0, 0, -0.015], along: [0, 1, 0], keys: [{ f: 20, pos: [-0.25, 1, 0.35], aim: [0, 0.7, 0.7] },
31
+ { f: 40, pos: [-0.25, 1.05, 0.4], aim: [0, 0.55, 0.85] }, { f: 59, pos: [-0.25, 1.05, 0.4], aim: [0, 0.55, 0.85] }] } },
32
+ goals: [{ name: "blade points at the target", near: ["prop:swordGrip.tip", "anchor:target"], tol: 0.1, at: [40, 59] }] } },
33
+ { name: "hinge: push a door open by its knob",
34
+ scene: "door: a 0.9 x 2 x 0.04 m box, base at (0, 0, 0.75), hinged on its +x edge",
35
+ spec: { schema: SCHEMA, fps: 24, frames: 72, label: "push the door open",
36
+ use: [{ skill: "standIdle", f0: 0, args: { at: [-0.1, 0.45], heading: 0 } },
37
+ { skill: "reachGrip", f0: 5, args: { anchor: "knob", side: "r", hold: 15, release: 8, define: { kind: "object", object: "door", local: [-0.35, 1, -0.04] } } }],
38
+ objects: { door: { pivot: [0.45, 0, 0.75], axis: [0, 1, 0], channel: "door" } },
39
+ keys: [{ f: 25, set: { door: 0 } }, { f: 40, set: { door: 10 } }, { f: 48, set: { door: 15 } }, { f: 70, set: { door: 75 } }],
40
+ goals: [{ name: "door swung open", moved: "object:door", by: 0.3, at: [60, 71] }] } },
41
+ ];
42
+
43
+ export const EXAMPLE_NOTES = [
44
+ "Each spec compiles at QA 0 on its scene. Ids are examples: use the scene's (object.createKit answers rootId, props and bind).",
45
+ "The lantern rides the hand from grab on (no release); the knob anchor follows the hinged door; aim keys pose the sword, the arm follows; the last key holds the pose.",
46
+ ];
@@ -0,0 +1,111 @@
1
+ // motion.describe examples and notes, one per topic (describe.js builds the schemas from
2
+ // fields.js and types.js). Each example is a part of a spec that passes validation when merged
3
+ // into a spec with standIdle at f0 0 and frames 60 (probes: a motion.compile probes list);
4
+ // test/motion3/verify-motion3-describe.mjs checks that. Object ids are examples: use the scene's.
5
+ import { CONVENTIONS } from "../compiler/vocab.js";
6
+ import { FIX_KEYS } from "../fix/index.js";
7
+ import { literal } from "./brief.js";
8
+ import { WRIST_LIMITS } from "../compiler/arm-orient.js";
9
+ import { KEY_BLEND } from "../object-keys.js";
10
+
11
+ const SPOT = { kind: "world", p: [-0.2, 1.1, 0.35] };
12
+ const GRIP = { hand: "r", origin: ["RightHandIndex2", "RightHandMiddle2"], points: { fingers: [0, 0, 0] } };
13
+
14
+ export const EXAMPLES = {
15
+ spec: { schema: "cozyclay.motion-spec.v1", fps: 24, frames: "auto", label: "walk up and grip the bar",
16
+ use: [{ skill: "standIdle", f0: 0, args: { at: [0, 0], heading: 0 } }, { skill: "walkTo", f0: 10, args: { to: [0, 1.2] } },
17
+ { skill: "reachGrip", f0: 140, args: { anchor: "bar", side: "r", define: { kind: "world", p: [-0.2, 1.2, 1.6] } } }],
18
+ keys: [{ f: 150, set: { head_pitch: 10 } }] },
19
+ anchors: { anchors: { spot: SPOT, pocket: { kind: "body", p: [0.13, -0.035, 0.08] }, knee: { kind: "segment", from: "LeftUpLeg", to: "LeftLeg", t: 0.45, reach: "l" },
20
+ handle: { kind: "object", object: "cup", local: [0.07, 0, 0] }, mouth: { kind: "landmark", name: "mouth" } },
21
+ keys: [{ f: 10, set: { armw_r: 1, w_spot_r: 0 } }, { f: 30, set: { w_spot_r: 1 } }] },
22
+ props: { props: { cupGrip: GRIP }, anchors: { spot: SPOT }, fits: [{ side: "r", anchor: "spot", effector: { prop: "cupGrip", point: "fingers" } }] },
23
+ objects: { props: { cupGrip: GRIP },
24
+ objects: { cup: { prop: "cupGrip", grab: 20, release: 50 }, door: { pivot: [0.9, 0, 0.5], axis: [0, 1, 0], channel: "door" },
25
+ bat: { prop: "cupGrip", grab: 52, keys: [{ f: 54, pos: [0.3, 1.2, 0.2], rot: [0, 0, 0.38268, 0.92388] }, { f: 58, pos: [0.3, 1.1, 0.4], aim: [0, -0.2, 1] }] },
26
+ ember: { visible: "ember_vis", level: "ember" }, puff: { follow: "landmark:mouth", aim: "face", visible: "ember_vis" } },
27
+ keys: [{ f: 0, set: { door: 0, ember_vis: 0, ember: 0.6 } }, { f: 30, set: { ember_vis: 1, ember: 2 }, step: ["ember_vis"] }, { f: 40, set: { door: -60 } }] },
28
+ checks: { anchors: { spot: SPOT }, checks: {
29
+ contacts: [{ name: "right hand on the spot", point: "joint:RightHand", target: "anchor:spot", tol: 0.05, when: [30, 40] }],
30
+ clearance: [{ name: "hand off the cup", part: "hand_r", object: "cup", min: 0.01, frames: [0, 20] }],
31
+ allow: [{ part: "hand", object: "cup", depth: 0.03 }], limits: { object: 0.01 } } },
32
+ goals: { anchors: { spot: SPOT }, goals: [
33
+ { name: "hand at the spot", near: ["joint:RightHand", "anchor:spot"], tol: 0.06, at: [30, 40] },
34
+ { name: "hand over the table", above: ["joint:RightHand", "object:table.top"], by: 0.05, at: 35, mode: "any" },
35
+ { name: "cup lifted", moved: "object:cup", by: 0.1, at: [40, 59], after: "hand at the spot" },
36
+ { name: "cup still before", still: "object:cup", at: [0, 59], before: "cup lifted" },
37
+ { name: "hand quick", speed: "joint:RightHand", by: 1.2, at: [20, 30] }] },
38
+ probes: [{ name: "handToCup", distance: ["joint:RightHand", "object:cup"], frames: [0, 59] }, { name: "cupTop", position: "object:cup.top", frames: [0, 59], every: 10 }],
39
+ channels: { anchors: { spot: SPOT }, channels: ["lid"], keys: [
40
+ { f: 0, set: { armw_r: 1, hand_r: [-0.25, 1.0, 0.2], elbow_r: [-0.5, -1, -0.3], fingers_r: { grip: 0 }, lid: 0 } },
41
+ { f: 20, set: { w_spot_r: 1, fingers_r: { grip: 1 }, head_yaw: -15, spine_pitch: 8 } },
42
+ { f: 30, set: { lid: 1 }, step: ["lid"] }] },
43
+ refs: { props: { cupGrip: GRIP }, anchors: { spot: SPOT }, goals: [
44
+ { name: "fingers at the spot", near: ["prop:cupGrip.fingers", "anchor:spot"], at: 30 },
45
+ { name: "cup at the mouth", near: ["object:cup.top", "landmark:mouth"], tol: 0.06, at: [40, 50] },
46
+ { name: "hand above the hips", above: ["joint:RightHand", "bone:Hips"], at: 30 }] },
47
+ fix: { fix: { reach: true, slide: true, penetration: 0.02, self: true, retime: false } },
48
+ };
49
+
50
+ const UNITS = `World metres, +Y up; ${CONVENTIONS.yaw}; the character's left is +X at yaw 0. Angles in degrees.`;
51
+ const NO_JUMP = "Without at/along it keeps its grab-frame offset to the palm: no jump.";
52
+ /** The objects example's carry: a grip prop and the object it holds. */
53
+ const CARRY = { props: EXAMPLES.objects.props, objects: { cup: EXAMPLES.objects.objects.cup } };
54
+
55
+ export const NOTES = {
56
+ essentials: ["types: ? optional, =v default, a..b range, A | B one of, [key]: T map, a|b?: T both, x_l|r each side, (text) meaning.",
57
+ `A carried object: ${literal(CARRY)}. ${NO_JUMP}`,
58
+ "motion.describe { topic } or { topic: 'skills', name }: the rest."],
59
+ spec: [UNITS,
60
+ "frames: an integer, or \"auto\" (the last skill end, generator end or key f, plus 1); the stored spec keeps the number.",
61
+ "Any number may be { range: [lo, hi] } (int: true for frames): the compiler searches it, QA 0 first, at most search.budget compiles.",
62
+ "use expands skills (topic skills) into keys, anchors, props, fits and checks first; your own keys win on the same frame and your anchors/props replace a skill's.",
63
+ "Keys ease between values (step jumps); a channel holds its last value. Unknown fields are refused with the field list.",
64
+ "More: topics anchors, props, objects, checks, goals, probes, channels, refs, fix, skills."],
65
+ anchors: ["An anchor is a named point a hand can go to: key w_<anchor>_l / w_<anchor>_r from 0 to 1 with armw_<side> 1 (the IK arm).",
66
+ "An anchor name may not end in _l or _r.", "object anchors (a body or a group; local in its own axes) follow the object where it is (hinges, carries): put the other hand on a carried object with one; the carrying hand's own anchor stays where it took it. prop anchors are a point of a prop the other hand holds.",
67
+ "segment with reach slides from t toward tMin until the arm reaches it."],
68
+ props: ["A prop is a set of points fixed to one hand, [d, l, n] along the palm axes; prop:<prop>.origin is the mean of its origin bones.",
69
+ "fits: the hand target moves so the effector (a prop point or the mean of joints), not the wrist, lands on the anchor.",
70
+ "A fit on a scene body also turns the hand about the forearm into a grip: a thin body (a can, a bar, a handle, a neck) across the palm, else thumb up; never past a comfortable forearm turn. A wrist you turn (wtwist/wflex) wins; fit.orient: false (reachGrip args.orient: false) turns it off.",
71
+ "reachGrip adds props.<anchor>Grip and its fit. Carry a scene object with objects.<id>.prop (topic objects)."],
72
+ objects: ["A hinge turns the object (a body or a group) about pivot/axis by the angle channel your keys set (degrees).",
73
+ "A carry follows the prop's hand: before grab the scene pose, grab..release in the hand, after release frozen where it was let go.",
74
+ `No grab: in hand from frame 0; no release: to the end. ${NO_JUMP}`,
75
+ "A group (Empty) id moves all its parts; at/along pin a group's root to the palm too (an object.createKit kit). A carried object is an obstacle for the body and the scene.",
76
+ "A switch { visible?, level? } (no prop, no hinge field) moves nothing: it shows or hides any record (a part, a light, an effect) and sets its level, 0..4 light, glow and effect strength "
77
+ + "(an unkeyed level reads 1). Hiding a group hides its parts. A carry takes level too.",
78
+ "keys pose a carried object in the world while it is in hand (grab <= f <= release): pos is its base (a group: its root), rot a quaternion [x, y, z, w], "
79
+ + "or aim [x, y, z] the direction its +Y points (a bat's barrel), turned from how the hand holds it there, plus roll degrees about aim; no roll: the roll the arm holds most easily. "
80
+ + `The object leads and the whole arm follows (the elbow swings, the forearm turns, the wrist adds the rest within ${Object.entries(WRIST_LIMITS).map(([k, [lo, hi]]) => `${k} ${lo}..${hi}`).join(", ")} deg; dev + toward the thumb); `
81
+ + "a left hand on a prop anchor of it turns with it; "
82
+ + `the hand eases in and out over ${KEY_BLEND} frames. A REACH group "<id>: n cm off its keys" is what the hand could not reach; `
83
+ + "output.observations.held measures every key as drawn (deg off the asked +Y, cm off pos, the drawn +Y, the rot an aim key used).",
84
+ "free { keys?, fall? } moves what nobody holds: keys at any frame; fall drops it at frame at under gravity onto the still top below (onto: that one; else the floor), "
85
+ + "one small bounce (0: none). A carry falls before grab or after release.",
86
+ "A follow { follow: <ref>, offset?, aim?, visible?, level? } puts any record (an effect, a light, a part) on a body point every frame: "
87
+ + "aim sets its +Y (an effect emits along it): up (default), face (forward), a direction or a ref (toward it); offset is metres along its axes after aim. It is no obstacle.",
88
+ "The editor's motion.keyObject writes one key from a drag (a hinge: its channel key)."],
89
+ checks: ["Each entry adds QA groups: contacts CONTACT, orient ORIENT, below BELOW, clearance CLEARANCE, appear APPEAR; supports mark where a part rests on an object (no FLOAT, no balance there); a foot on an object's top is on the ground without one.",
90
+ "when: a weight channel (active above 0.99) or [f0, f1]; clearance uses frames.", "Check points take joint:, prop: and anchor: only; goals and probes take every ref (topic refs).",
91
+ "allow excuses a body part inside an object up to depth; limits override the QA limits. Unnamed entries are named by place, contacts[0].",
92
+ "Speed, acceleration, knee bend and balance are style: measured in output.observations, not judged. Naming speedCore/speedLimb, accCore/accLimb, knee or balance in limits makes it a check (SPEED, ACC, KNEE, BALANCE). observations.near: each hand's and foot's nearest object and gap (< 0 inside), measured, not judged.",
93
+ "motion.qa { checks } replaces every check for a re-measure."],
94
+ goals: ["Exactly one of near (distance <= tol), above (a.y - b.y >= by), moved (an object's base moved at least by from the scene pose; any other point ref, e.g. prop:bat.tip, at least by from where it is at at[0], at: [f0, f1]), still (stays within tol, default 0.01 m, of where moved measures from) or speed (the point reaches by m/s).",
95
+ "at is an absolute frame or [f0, f1]; mode all (every frame; the default) or any (one frame; speed's default). A failed goal is a GOAL group first in qa.groups and makes qa.ok false.",
96
+ "after / before: another goal's name; at is cut to the frames after (before) the first frame that goal holds, so cause and effect keep their order wherever the event lands (the can moves after the kick). If that goal never holds, this one fails with value null.",
97
+ "Intent lines as goals: a contact is near between the touching point (joint:RightHandIndex4, joint:RightToeBase) and the object, tol 0.02-0.03; a negative is still on the object before: \"<contact goal>\"; an effect is moved on the object after: \"<contact goal>\" (mode any); a strike is speed of the joint, by m/s, before: \"<contact goal>\"; an effect on something nobody holds (a can that drops, a machine that rocks) moves it by spec.objects keys or fall (topic: \"objects\"), not a hinge or a swapped copy.",
98
+ "A cup or can brought to the mouth: give its aim keys lean 20-30 so the elbow stays low (observations.wrist raised counts the frames with the elbow over the shoulder)."],
99
+ probes: ["motion.compile { probes } (at most 16); spec.probes are measured too, not stored; answered whether or not it installs.",
100
+ "distance [a, b] -> { min, minAt, max, maxAt, mean, first, last } in m; a bare object:<id> measures to its surface. position -> { at: [{ f, p }] }, at most 16 rows."],
101
+ channels: ["key.set names channels; values ease between keys and hold after the last key. step: [channel] jumps at f instead.",
102
+ "Flow (spec.flow, on by default): the spine, head, arm swing/bend and wrist carry their speed through a key (a small overshoot) and trail the body (spine 1, head 2, arms 3 frames; lag: { spine, head, arms } or a number); feet, root, hand targets, weights, poles, fingers and objects land on their keys on time. flow: false turns it off; { smooth: false } or { lag: false } one part.",
103
+ "w_<anchor>_<side> (0..1) weights a hand onto an anchor; the weights of one hand add up to at most 1.",
104
+ "Any other numeric channel must come from spec.channels, a hinge (objects.<id>.channel), a check's when or a visible switch; names ending _vis are visibility switches (shown above 0.5)."],
105
+ refs: ["A ref names a point: joint:/bone:<Bone>, prop:<prop>.<point>, anchor:<name>, landmark:mouth, object:<id>[.center|.top|.base].",
106
+ "object:<id> takes a body or a group (the box around its parts); in a distance a bare object:<id> means its surface.",
107
+ "Goals and probes take every kind; spec.checks keep joint:, prop: and anchor:."],
108
+ fix: [`spec.fix keys: ${FIX_KEYS.join(", ")}; false turns all off. output.fixed reports what each one changed.`,
109
+ "reach, slide and self are on by default; penetration and retime are opt-in.",
110
+ "self keeps the arms out of the body on its fitted skin (QA BODY measures the same skin): wrist targets inside it go onto it, elbows turn about the shoulder-wrist line, a hand a little inside is pushed out. A fit's target (the mouth) is never moved; what is left is BODY, with checks.allow { part, object: <body part>, depth } for a contact meant to touch (a hand on a knee)."],
111
+ };
@@ -0,0 +1,147 @@
1
+ // JSON Schema 2020-12 fragments for the fields of each table in schema/fields.js, keyed by the
2
+ // field name. The field lists themselves stay in fields.js: describe.js walks those lists and
3
+ // looks each field up here, and throws when one is missing, so a new field needs a type here.
4
+ // Shared shapes are $refs into DEFS (describe.js adds the ones an answer uses).
5
+ import { REF_KINDS, OBJECT_KEY_FIELDS } from "./fields.js";
6
+ import { CONVENTIONS } from "../compiler/vocab.js";
7
+ import { QA_LIMITS } from "../qa/checks.js";
8
+ import { CAPSULES } from "../qa/geometry.js";
9
+
10
+ const def = (d, extra) => ({ ...extra, ...(d ? { description: d } : {}) });
11
+ export const num = (d, extra) => def(d, { type: "number", ...extra });
12
+ export const int = (d, extra) => def(d, { type: "integer", ...extra });
13
+ export const str = (d, extra) => def(d, { type: "string", ...extra });
14
+ const bool = (d, extra) => def(d, { type: "boolean", ...extra });
15
+ export const ref = (name, d) => def(d, { $ref: `#/$defs/${name}` });
16
+ export const side = d => def(d, { enum: ["l", "r"] });
17
+ const pair = (items, d) => def(d, { type: "array", prefixItems: [items, items], minItems: 2, maxItems: 2 });
18
+
19
+ export const DEFS = {
20
+ vec3: { type: "array", items: { type: "number" }, minItems: 3, maxItems: 3 },
21
+ frameSpan: { type: "array", items: { type: "integer", minimum: 0 }, minItems: 2, maxItems: 2, description: "[f0, f1] inclusive" },
22
+ ref: { type: "string", pattern: `^(${REF_KINDS.join("|")}):.+$`, description: "a point ref (topic refs)" },
23
+ checkRef: { type: "string", pattern: "^(joint|prop|anchor):.+$", description: "joint:<Bone> | prop:<prop>.<point> | anchor:<name>" },
24
+ part: { type: "string", description: `a body capsule: ${CAPSULES.map(c => c[0]).join(", ")}; allow matches a prefix (hand = hand_l and hand_r)` },
25
+ when: { oneOf: [{ type: "string", description: "a weight channel: active where it is > 0.99" }, { $ref: "#/$defs/frameSpan" }] },
26
+ };
27
+
28
+ export const KEY_TYPES = {
29
+ f: int("frame", { minimum: 0 }), set: { type: "object", description: "{ channel: value } (topic channels)" },
30
+ step: { type: "array", items: { type: "string" }, description: "channels that jump at f instead of easing in" },
31
+ src: str("written by the skills expander; leave it out"),
32
+ };
33
+
34
+ export const USE_TYPES = { skill: str("a skill name (topic skills)"), args: { type: "object", description: "the skill's args (topic skills with name)" }, f0: int("first frame", { minimum: 0 }) };
35
+
36
+ export const WALK_TYPES = {
37
+ type: { const: "walk" }, f0: int("first frame; needs a standing pose keyed before it", { minimum: 0 }), steps: int("footsteps", { minimum: 1, default: 8 }),
38
+ step: num("stride, m", { default: 0.5 }), period: int("frames per step", { default: 20 }), swing: int("frames a foot is in the air", { default: 14 }),
39
+ halfWidth: num("feet half-width, m", { default: 0.08 }), lift: num("foot lift, m", { default: 0.08 }), heading: pair({ type: "number" }, `[h0, h1] degrees; ${CONVENTIONS.yaw}`),
40
+ turnDistance: num("m walked while the heading turns h0 -> h1", { default: 0.4 }), pelvisHigh: num("hips offset over the stance foot, m"),
41
+ pelvisLow: num("hips offset at double support, m"), firstStep: num("first stride, m", { default: 0.4 }), armSwing: num("degrees", { default: 14 }),
42
+ vary: num("0..2, uneven steps as people walk (build-up, slow stop, left/right, turns) around the averages above; 0 = every step period frames, step m", { default: 1, minimum: 0, maximum: 2 }),
43
+ };
44
+
45
+ export const SPEC_TYPES = {
46
+ schema: { const: "cozyclay.motion-spec.v1" }, fps: { const: 24 },
47
+ frames: { oneOf: [int(null, { minimum: 1, maximum: 20000 }), { const: "auto", description: "the last skill end, generator end or key f, plus 1 (open values at their upper bound); the stored spec keeps the number" }] },
48
+ label: str("a short name for the take"),
49
+ keys: { type: "array", items: { $ref: "#/$defs/key" } },
50
+ anchors: { type: "object", description: "name -> anchor (topic anchors)" }, props: { type: "object", description: "name -> held prop (topic props)" },
51
+ fits: { type: "array", description: "topic props" }, objects: { type: "object", description: "scene object id -> hinge, carry, switch, follow or free (topic objects)" },
52
+ generators: { type: "array", items: { $ref: "#/$defs/walk" } }, checks: { type: "object", description: "topic checks" },
53
+ fix: { oneOf: [{ const: false }, { type: "object" }], description: "topic fix" }, use: { type: "array", items: { $ref: "#/$defs/use" } },
54
+ channels: { type: "array", items: { type: "string" }, description: "extra numeric channels your keys set" },
55
+ detourRadius: num("m; a hand moving between targets arcs around the torso this far out", { default: 0.25 }),
56
+ search: { type: "object", properties: { budget: int("compiles at most", { minimum: 1, maximum: 64, default: 32 }) }, additionalProperties: false },
57
+ goals: { type: "array", description: "topic goals" },
58
+ flow: { oneOf: [{ const: false }, { type: "object" }] },
59
+ idle: { const: false, description: "held poses do not breathe" },
60
+ };
61
+
62
+ export const ANCHOR_TYPES = {
63
+ p: ref("vec3", `world: a world point (m); body: root-relative, ${CONVENTIONS.pole}`), bone: str("bone name"), offset: ref("vec3", "world offset, m"),
64
+ from: str("bone"), to: str("bone"), t: num("0 = from .. 1 = to", { default: 0.5 }), tMin: num("with reach: the lowest t to slide back to", { default: 0.15 }),
65
+ reach: side("slide toward `from` until this arm reaches"), object: str("scene object id"), local: ref("vec3", "point in the object's frame, m"),
66
+ name: { const: "mouth" }, prop: str("a prop held by the other hand"), point: str("a point of that prop, or origin"),
67
+ };
68
+
69
+ const palm = d => ref("vec3", `${d} [d, l, n] on the palm axes (d to the middle finger, l to the thumb side, n = d x l), m`);
70
+ /** Fields an anchor of each kind must have. */
71
+ export const ANCHOR_REQUIRED = { world: ["p"], body: ["p"], bone: ["bone"], segment: ["from", "to"], object: ["object"], landmark: ["name"], prop: ["prop", "point"] };
72
+
73
+ export const PROP_TYPES = {
74
+ hand: side(), origin: { type: "array", items: { type: "string" }, minItems: 1, description: "bones whose mean is the prop origin" },
75
+ points: { type: "object", additionalProperties: palm("point:"), description: "name -> point" },
76
+ };
77
+
78
+ export const FIT_TYPES = {
79
+ side: side(), anchor: str("an anchor name"),
80
+ effector: { oneOf: [{ type: "object", properties: { prop: str(), point: str() }, required: ["prop", "point"] }, { type: "object", properties: { joints: { type: "array", items: { type: "string" } } }, required: ["joints"] }],
81
+ description: "the hand point fitted onto the anchor" },
82
+ offset: ref("vec3", "world offset, m"), orient: { type: "boolean", description: "false: no grip turn" },
83
+ };
84
+
85
+ const OBJECT_KEY_TYPES = { f: int(), pos: ref("vec3"), rot: { type: "array", items: { type: "number" }, minItems: 4, maxItems: 4, description: "quat x, y, z, w" },
86
+ aim: ref("vec3", "or rot: +Y dir"), roll: num("deg about aim"), lean: num("aim tilt", { minimum: 0, maximum: 45 }) };
87
+
88
+ const FALL = { type: "object", properties: { at: int(), onto: str(), bounce: num(null, { default: 0.25, minimum: 0, maximum: 0.6 }) }, required: ["at"], additionalProperties: false };
89
+ /** A free entry's keys and fall (C17) are a carry's, at any frame: said once, not twice. */
90
+ const AS_CARRY = { description: "as carry; keys at any frame" };
91
+ export const FREE_TYPES = { keys: AS_CARRY, fall: AS_CARRY };
92
+
93
+ export const OBJECT_TYPES = {
94
+ pivot: ref("vec3", "world hinge point, m"), axis: ref("vec3", "default [0, 1, 0]"), channel: str("angle channel, deg"),
95
+ prop: str("spec.props name: it rides that hand"), at: ref("vec3", "palm offset [d, l, n], m"), along: ref("vec3", "its +Y on the palm, fixed"),
96
+ visible: str("channel: shown > 0.5"), level: str("channel: strength 0..4"), grab: int("the hand takes it", { default: 0 }), release: int("let go (else the end)"),
97
+ keys: { type: "array", items: { type: "object", properties: Object.fromEntries(OBJECT_KEY_FIELDS.map(f => [f, OBJECT_KEY_TYPES[f]])), required: ["f", "pos"], additionalProperties: false },
98
+ description: "world pose at f, in hand; the hand follows" },
99
+ fall: { ...FALL, description: "or a list; topic objects" },
100
+ follow: ref("ref"), offset: ref("vec3"), aim: { oneOf: [{ enum: ["face", "up"] }, { $ref: "#/$defs/vec3" }, { $ref: "#/$defs/ref" }], default: "up" },
101
+ };
102
+
103
+ export const CHECK_ENTRY_TYPES = {
104
+ name: str("the QA group's name"), point: ref("checkRef"), target: ref("checkRef"),
105
+ tol: num("m; default contacts 0.01, appear 0.035, supports 0.04"), when: ref("when"), from: ref("checkRef"), to: ref("checkRef"),
106
+ along: { oneOf: [{ enum: ["face", "up"] }, { $ref: "#/$defs/vec3" }] }, minCos: num("default 0.64"),
107
+ joint: str("bone"), ref: str("bone"), min: num("m; below default 0.08"), part: ref("part"),
108
+ object: str("scene object id"), frames: ref("frameSpan"), channel: str("a visibility channel"), anchor: str("an anchor name"), depth: num("allowed depth, m"),
109
+ };
110
+
111
+ /** Fields each checks entry must have. */
112
+ export const CHECK_REQUIRED = { contacts: ["point", "target"], orient: ["from", "to", "along"], below: ["joint", "ref"], clearance: ["part", "object", "min"],
113
+ appear: ["channel", "joint", "anchor"], supports: ["object"], allow: ["part", "object", "depth"] };
114
+
115
+ export const CHECKS_TYPES = {
116
+ limits: { type: "object", properties: Object.fromEntries(Object.entries(QA_LIMITS).map(([k, v]) => [k, num(null, { default: v })])), additionalProperties: false },
117
+ mouthPoints: { type: "array", items: str("prop.point"), description: "prop points allowed at the mouth" },
118
+ };
119
+
120
+ export const GOAL_TYPES = {
121
+ name: str(), near: pair({ $ref: "#/$defs/ref" }, "distance <= tol"), above: pair({ $ref: "#/$defs/ref" }, "a.y - b.y >= by"),
122
+ moved: str("a ref or an object id: an object's base moves at least `by` from the scene pose; any other point (prop:, joint:, landmark:, anchor:) at least `by` from where it is at at[0] (at: [f0, f1])"),
123
+ still: str("a ref or an object id: stays within `tol` of where moved measures from (an object: its scene pose; a point: where it is at at[0], at: [f0, f1])"),
124
+ speed: str("a point ref: its speed reaches `by` m/s (mode any by default)"),
125
+ tol: num("m; near default 0.05, still 0.01"), by: num("above m, default 0; moved m, default 0.05; speed m/s, needed"),
126
+ at: { oneOf: [int(null, { minimum: 0 }), { $ref: "#/$defs/frameSpan" }], description: "absolute frame or span" },
127
+ mode: { enum: ["all", "any"], description: "every frame of `at`, or one; default all, speed any" },
128
+ after: str("a goal's name: at starts after the first frame that goal holds"), before: str("a goal's name: at ends before the first frame that goal holds"),
129
+ };
130
+
131
+ export const PROBE_TYPES = {
132
+ name: str("the key of the answer"), distance: pair({ $ref: "#/$defs/ref" }, "min/max/mean/first/last m"), position: ref("ref", "world points"),
133
+ frames: ref("frameSpan", "absolute, default the whole take"), every: int("position: every n frames (<= 16 rows)", { minimum: 1 }),
134
+ };
135
+
136
+ export const FIX_TYPES = {
137
+ reach: bool("wrist targets past reach go onto it softly; hips lower for near-miss ankles", { default: true }),
138
+ slide: bool("lifts sunk soles; a planted heel or ball drifting under 1 cm stays put; a heel-up foot pivots on its ball", { default: true }),
139
+ penetration: { oneOf: [{ type: "boolean" }, { type: "number", minimum: 0, maximum: 0.05 }], default: 0, description: "push hands out of boxes up to this depth, m (true = 0.02)" },
140
+ self: bool("arms kept out of the body's skin (wrists, elbows)", { default: true }),
141
+ retime: bool("speed spikes borrow frames from the neighbouring keys", { default: false }),
142
+ };
143
+
144
+ export const REF_DOCS = {
145
+ joint: "joint:<Bone>, the bone's joint", bone: "bone:<Bone>, as joint:", prop: "prop:<prop>.<point> (origin always exists)",
146
+ anchor: "anchor:<name>, a spec anchor", landmark: "landmark:mouth", object: "object:<id>[.center|.top|.base], a body or group (Empty); bare = its surface in a distance",
147
+ };