cozyclay 2.1.0 → 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 (583) hide show
  1. package/CHANGELOG.md +65 -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 +22 -6
  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-BlT33CGf.js → first-shot-handoff-CC4xe4HM.js} +1 -1
  33. package/dist/assets/{landing-BSesrCpL.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/llms.txt +14 -0
  40. package/dist/sw.js +3 -6
  41. package/dist/workflow/index.html +5 -4
  42. package/mcp/LIVE-PROTOCOL.md +7 -47
  43. package/mcp/README.md +16 -26
  44. package/mcp/live-hub.mjs +6 -10
  45. package/mcp/package.json +1 -3
  46. package/mcp/tool-handlers.mjs +4 -168
  47. package/package.json +3 -22
  48. package/src/App.jsx +174 -2639
  49. package/src/agent-progress.js +79 -0
  50. package/src/agent-turn-mark.js +30 -0
  51. package/src/analytics.js +1 -19
  52. package/src/app-context.js +5 -0
  53. package/src/app-stage.jsx +2 -34
  54. package/src/asset-pane.jsx +6 -5
  55. package/src/camera-block.js +21 -0
  56. package/src/camera-direction.js +120 -0
  57. package/src/character-kind.js +3 -9
  58. package/src/command-bus.js +8 -6
  59. package/src/commands/cast.js +5 -34
  60. package/src/commands/elements/character.js +1 -1
  61. package/src/commands/elements/motion.js +1 -6
  62. package/src/commands/elements/object.js +6 -2
  63. package/src/commands/elements/shot.js +4 -1
  64. package/src/commands/elements.js +38 -14
  65. package/src/commands/index.js +3 -1
  66. package/src/commands/kits.js +37 -0
  67. package/src/commands/motion-timing.js +57 -0
  68. package/src/commands/motion.js +9 -152
  69. package/src/commands/motion3-compile.js +65 -0
  70. package/src/commands/motion3.js +207 -0
  71. package/src/commands/objects.js +6 -4
  72. package/src/commands/shot.js +49 -11
  73. package/src/commands/stage.js +14 -1
  74. package/src/commands/view.js +4 -1
  75. package/src/document-mirrors.js +42 -0
  76. package/src/document-store.js +4 -0
  77. package/src/domains/cast.js +19 -194
  78. package/src/domains/motion/motion-range-pin-rules.js +1 -1
  79. package/src/domains/motion/take-source.js +51 -0
  80. package/src/domains/motion.js +60 -1838
  81. package/src/domains/scenes.js +12 -55
  82. package/src/domains/shots.js +2 -2
  83. package/src/domains/stage.js +4 -2
  84. package/src/draft-ghost.js +46 -0
  85. package/src/draft-ghost.jsx +129 -0
  86. package/src/dualview.jsx +4 -3
  87. package/src/effects/EffectsLayer.jsx +112 -0
  88. package/src/effects/effect-meshes.js +232 -0
  89. package/src/effects/effect-record.js +103 -0
  90. package/src/effects/emitter.js +59 -0
  91. package/src/effects/simulate.js +261 -0
  92. package/src/effects/state.js +59 -0
  93. package/src/execution-telemetry.js +2 -3
  94. package/src/first-success-guide.jsx +5 -5
  95. package/src/ghost-set.js +257 -0
  96. package/src/held-object-edit.jsx +113 -0
  97. package/src/held-object-pose.js +175 -0
  98. package/src/hierarchy-model.js +1 -1
  99. package/src/hierarchy-panel.jsx +1 -1
  100. package/src/imported-mesh.jsx +103 -0
  101. package/src/kits/held.js +84 -0
  102. package/src/kits/index.js +70 -0
  103. package/src/kits/smoking.js +57 -0
  104. package/src/light-blockers.js +93 -0
  105. package/src/motion/beat-board-model.js +84 -0
  106. package/src/motion/beat-board.css +124 -0
  107. package/src/motion/beat-board.jsx +59 -0
  108. package/src/motion/center-of-mass.js +66 -0
  109. package/src/motion/fix-collisions.js +850 -0
  110. package/src/motion/physics-review.js +118 -0
  111. package/src/{ardy → motion}/physics-support.js +1 -76
  112. package/src/motion/rig-snapshot.js +22 -0
  113. package/src/motion/take-segments.jsx +140 -0
  114. package/src/{ardy → motion}/timeline-coordinates.js +0 -21
  115. package/src/{ardy → motion}/timeline.css +1 -2
  116. package/src/{ardy → motion}/timeline.jsx +48 -419
  117. package/src/motion/waypoints.js +76 -0
  118. package/src/motion3/beats.js +83 -0
  119. package/src/motion3/body.js +158 -0
  120. package/src/motion3/bones.js +47 -0
  121. package/src/motion3/carried.js +47 -0
  122. package/src/motion3/compile-job.js +75 -0
  123. package/src/motion3/compile-worker.js +10 -0
  124. package/src/motion3/compiler/anchors.js +105 -0
  125. package/src/motion3/compiler/arm-orient.js +128 -0
  126. package/src/motion3/compiler/channels.js +125 -0
  127. package/src/motion3/compiler/compile.js +205 -0
  128. package/src/motion3/compiler/gait-rhythm.js +97 -0
  129. package/src/motion3/compiler/grip.js +171 -0
  130. package/src/motion3/compiler/head-steady.js +48 -0
  131. package/src/motion3/compiler/hold.js +134 -0
  132. package/src/motion3/compiler/idle.js +113 -0
  133. package/src/motion3/compiler/limbs.js +170 -0
  134. package/src/motion3/compiler/math.js +72 -0
  135. package/src/motion3/compiler/pose.js +162 -0
  136. package/src/motion3/compiler/quat.js +49 -0
  137. package/src/motion3/compiler/skeleton.js +74 -0
  138. package/src/motion3/compiler/validate-common.js +32 -0
  139. package/src/motion3/compiler/validate-goals.js +118 -0
  140. package/src/motion3/compiler/validate-objects.js +143 -0
  141. package/src/motion3/compiler/validate-parts.js +116 -0
  142. package/src/motion3/compiler/validate.js +122 -0
  143. package/src/motion3/compiler/vocab.js +73 -0
  144. package/src/motion3/compiler/walk-pelvis.js +275 -0
  145. package/src/motion3/compiler/walk.js +207 -0
  146. package/src/motion3/compiler/wrist-clamp.js +32 -0
  147. package/src/motion3/delta.js +47 -0
  148. package/src/motion3/describe.js +174 -0
  149. package/src/motion3/docs.js +27 -0
  150. package/src/motion3/edit-carry.js +21 -0
  151. package/src/motion3/fix/ease.js +16 -0
  152. package/src/motion3/fix/ground.js +37 -0
  153. package/src/motion3/fix/index.js +52 -0
  154. package/src/motion3/fix/push.js +71 -0
  155. package/src/motion3/fix/reach.js +46 -0
  156. package/src/motion3/fix/retime.js +79 -0
  157. package/src/motion3/fix/self.js +211 -0
  158. package/src/motion3/fix/slide.js +70 -0
  159. package/src/motion3/fix/turn.js +51 -0
  160. package/src/motion3/follow.js +39 -0
  161. package/src/motion3/free-motion.js +173 -0
  162. package/src/motion3/grip-choice.js +130 -0
  163. package/src/motion3/hold-plan.js +157 -0
  164. package/src/motion3/json-patch.js +77 -0
  165. package/src/motion3/key-aim.js +105 -0
  166. package/src/motion3/key-edit.js +82 -0
  167. package/src/motion3/lenient.js +127 -0
  168. package/src/motion3/object-keys.js +236 -0
  169. package/src/motion3/object-pose.js +182 -0
  170. package/src/motion3/object-tracks.js +12 -0
  171. package/src/motion3/pipeline.js +102 -0
  172. package/src/motion3/playback.js +51 -0
  173. package/src/motion3/probes.js +91 -0
  174. package/src/motion3/qa/body-checks.js +34 -0
  175. package/src/motion3/qa/check-names.js +14 -0
  176. package/src/motion3/qa/checks.js +121 -0
  177. package/src/motion3/qa/contact-checks.js +51 -0
  178. package/src/motion3/qa/explain.js +80 -0
  179. package/src/motion3/qa/fmt.js +5 -0
  180. package/src/motion3/qa/foot-checks.js +72 -0
  181. package/src/motion3/qa/geometry.js +77 -0
  182. package/src/motion3/qa/goals.js +191 -0
  183. package/src/motion3/qa/ground.js +60 -0
  184. package/src/motion3/qa/hints-contact.js +179 -0
  185. package/src/motion3/qa/hints-goal.js +160 -0
  186. package/src/motion3/qa/hints-knee.js +24 -0
  187. package/src/motion3/qa/hints-motion.js +209 -0
  188. package/src/motion3/qa/hints-object.js +91 -0
  189. package/src/motion3/qa/index.js +42 -0
  190. package/src/motion3/qa/key-checks.js +82 -0
  191. package/src/motion3/qa/near.js +96 -0
  192. package/src/motion3/qa/object-checks.js +135 -0
  193. package/src/motion3/qa/patch.js +161 -0
  194. package/src/motion3/qa/severity.js +38 -0
  195. package/src/motion3/qa/spec-checks.js +65 -0
  196. package/src/motion3/qa/style.js +218 -0
  197. package/src/motion3/qa/wrist-checks.js +69 -0
  198. package/src/motion3/qa/wrist-obs.js +60 -0
  199. package/src/motion3/refs.js +120 -0
  200. package/src/motion3/repair-tune.js +121 -0
  201. package/src/motion3/repair.js +83 -0
  202. package/src/motion3/report.js +67 -0
  203. package/src/motion3/rigs/index.js +14 -0
  204. package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
  205. package/src/motion3/rigs/x-bot-tpose.json +1 -0
  206. package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
  207. package/src/motion3/rigs/y-bot-tpose.json +1 -0
  208. package/src/motion3/scene.js +60 -0
  209. package/src/motion3/schema/brief.js +89 -0
  210. package/src/motion3/schema/fields.js +44 -0
  211. package/src/motion3/schema/spec-examples.js +46 -0
  212. package/src/motion3/schema/topics.js +111 -0
  213. package/src/motion3/schema/types.js +147 -0
  214. package/src/motion3/search.js +117 -0
  215. package/src/motion3/second-hand.js +112 -0
  216. package/src/motion3/skills/basic.js +82 -0
  217. package/src/motion3/skills/book.js +76 -0
  218. package/src/motion3/skills/car.js +145 -0
  219. package/src/motion3/skills/frames-auto.js +29 -0
  220. package/src/motion3/skills/index.js +83 -0
  221. package/src/motion3/skills/info.js +65 -0
  222. package/src/motion3/skills/smoke-kit.js +109 -0
  223. package/src/motion3/skills/smoke.js +160 -0
  224. package/src/motion3/spec-store.js +59 -0
  225. package/src/motion3/take-edit.js +155 -0
  226. package/src/motion3/take.js +63 -0
  227. package/src/motion3/timeline.js +127 -0
  228. package/src/motion3/views.js +121 -0
  229. package/src/motion3/walk-plan.js +119 -0
  230. package/src/object-catalog.jsx +7 -1
  231. package/src/object-colors.js +98 -0
  232. package/src/object-gizmo-parts.js +115 -0
  233. package/src/object-gizmo.jsx +37 -122
  234. package/src/object-glow.js +139 -0
  235. package/src/object-hidden.js +33 -0
  236. package/src/object-look.js +196 -0
  237. package/src/object-size.js +10 -0
  238. package/src/object-travel.js +71 -6
  239. package/src/panels/CameraPanel.jsx +7 -7
  240. package/src/panels/HdrEnvironmentControls.jsx +59 -0
  241. package/src/panels/LightPanel.jsx +25 -4
  242. package/src/panels/ObjectLookPanel.jsx +88 -0
  243. package/src/panels/PoseImagePanel.jsx +1 -1
  244. package/src/panels/PosePanel.jsx +2 -17
  245. package/src/panels/RigControlPanel.jsx +5 -53
  246. package/src/panels/SubjectBox.jsx +4 -1
  247. package/src/panels/details.css +14 -0
  248. package/src/posestudio.jsx +4 -27
  249. package/src/project-browser.jsx +3 -4
  250. package/src/project-resources.js +18 -31
  251. package/src/project.js +13 -104
  252. package/src/props.jsx +25 -280
  253. package/src/rail-dot-drag.js +23 -0
  254. package/src/render-passes.js +10 -0
  255. package/src/resource-status.jsx +1 -0
  256. package/src/result-modal.jsx +4 -19
  257. package/src/room.jsx +20 -12
  258. package/src/scene-assets.js +8 -6
  259. package/src/scene-light-place.js +72 -0
  260. package/src/scene-lights.jsx +148 -0
  261. package/src/scene-objects.js +31 -139
  262. package/src/scenes.js +15 -105
  263. package/src/semantic-edit.js +2 -5
  264. package/src/set-pieces.jsx +183 -0
  265. package/src/settings-menu.jsx +3 -11
  266. package/src/shell/BottomDock.jsx +11 -53
  267. package/src/shell/CompositionGuideButton.jsx +20 -0
  268. package/src/shell/DetailsSlot.jsx +16 -200
  269. package/src/shell/GhostsMenuGroup.jsx +74 -0
  270. package/src/shell/LibrarySlot.jsx +1 -3
  271. package/src/shell/MenuBar.jsx +3 -3
  272. package/src/shell/PreferencesDialog.jsx +15 -264
  273. package/src/shell/PreferencesSlot.jsx +2 -8
  274. package/src/shell/ShotPreviewHeader.jsx +17 -0
  275. package/src/shell/TopBar.jsx +5 -83
  276. package/src/shell/ViewportToolbar.jsx +23 -93
  277. package/src/shell/agent-glass.css +19 -6
  278. package/src/shell/details-selection.js +42 -0
  279. package/src/shell/ghosts-menu.css +22 -0
  280. package/src/shell/glass-regions.css +29 -3
  281. package/src/shell/preferences.css +6 -1
  282. package/src/shell/viewport.css +12 -0
  283. package/src/shot-authoring.js +4 -7
  284. package/src/soft-shadows.js +37 -0
  285. package/src/stage-attach-frames.js +12 -12
  286. package/src/stage-canvas-rigs.jsx +3 -3
  287. package/src/stage-capture.jsx +42 -8
  288. package/src/stage-characters.jsx +22 -216
  289. package/src/stage-editor-gizmos.jsx +6 -6
  290. package/src/stage-environment.js +93 -0
  291. package/src/stage-hdr-builtins.js +107 -0
  292. package/src/stage-hdr-image.js +116 -0
  293. package/src/stage-hdr-library.js +70 -0
  294. package/src/stage-hdr-map.js +94 -0
  295. package/src/stage-hdr.js +130 -0
  296. package/src/stage-lighting.js +149 -0
  297. package/src/stage-occlusion.js +210 -0
  298. package/src/stage-sky.jsx +159 -0
  299. package/src/stage-startup-defaults.js +5 -9
  300. package/src/studio-actions.js +12 -14
  301. package/src/studio-agent-commands.js +46 -16
  302. package/src/studio-agent-motion.js +9 -9
  303. package/src/studio-agent-protocol.js +46 -73
  304. package/src/studio-app-binding.js +29 -45
  305. package/src/studio-asset-list.js +17 -0
  306. package/src/studio-contact-sheet.js +37 -5
  307. package/src/studio-elements.js +27 -7
  308. package/src/studio-entity-bounds.js +18 -0
  309. package/src/studio-error-codes.js +8 -0
  310. package/src/studio-export-framing.js +152 -0
  311. package/src/studio-lighting-check.js +103 -0
  312. package/src/studio-motion-visual.js +150 -0
  313. package/src/studio-schema-errors.js +80 -0
  314. package/src/studio-support-gap.js +74 -0
  315. package/src/styles.css +1 -19
  316. package/src/timeline-defaults.js +5 -0
  317. package/src/timeline-extent.js +8 -20
  318. package/src/tutorial-walk.js +17 -0
  319. package/src/ui-scrub.js +1 -1
  320. package/src/use-shot-camera-tracks.js +12 -0
  321. package/src/view-ghosts.js +97 -0
  322. package/src/view-ghosts.jsx +49 -0
  323. package/src/workflow/AgentPanel.jsx +47 -166
  324. package/src/workflow/AgentProgressCard.jsx +107 -0
  325. package/src/workflow/AgentReplyText.jsx +37 -0
  326. package/src/workflow/AgentTurnSteps.jsx +84 -0
  327. package/src/workflow/LoginPanel.jsx +140 -0
  328. package/src/workflow/WorkflowBuilder.jsx +7 -23
  329. package/src/workflow/agent-client.js +54 -51
  330. package/src/workflow/agent-panel.css +71 -1
  331. package/src/workflow/agent-progress-card.css +167 -0
  332. package/src/workflow/agent-progress-view.js +47 -0
  333. package/src/workflow/agent-turn-steps.css +113 -0
  334. package/src/workflow/agent-turn.js +191 -0
  335. package/src/workflow/login-client.js +34 -0
  336. package/src/workflow/motion-input.js +18 -31
  337. package/src/workflow/node-schema.js +1 -1
  338. package/src/workflow/reply-markdown.js +69 -0
  339. package/src/workflow/scene-asset-sync.js +8 -8
  340. package/tools/agent-session-stats.mjs +61 -0
  341. package/tools/dev-full.mjs +5 -56
  342. package/tools/eslint-baseline.json +12 -13
  343. package/tools/headless-studio.mjs +85 -0
  344. package/tools/knip-baseline.json +0 -179
  345. package/tools/loc-baseline.json +33 -83
  346. package/tools/motion3/extract-body.mjs +103 -0
  347. package/tools/motion3/extract-rig.mjs +85 -0
  348. package/tools/process-supervisor.mjs +0 -88
  349. package/tools/run-tests.mjs +9 -124
  350. package/bin/agent/motion-runtime.mjs +0 -76
  351. package/dist/ardy/cskel27-rest.json +0 -557
  352. package/dist/assets/analytics-B41FmPYI.js +0 -1
  353. package/dist/assets/app-Do-Og5Pu.css +0 -1
  354. package/dist/assets/app-DwP-tl2x.js +0 -4920
  355. package/dist/assets/config-Bx7pYsD9.js +0 -1
  356. package/dist/assets/config-DeoFTYzb.css +0 -1
  357. package/dist/assets/demo-Dt0qZfS7.js +0 -1
  358. package/dist/assets/scene-asset-sync-BCWDJB1d.js +0 -19
  359. package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
  360. package/dist/assets/ticket-jqMhqL88.js +0 -1
  361. package/dist/assets/workflow-Br-K7Srs.js +0 -179
  362. package/dist/demo/walk-then-stop.npz +0 -0
  363. package/mcp/ardy-prompts.mjs +0 -218
  364. package/src/ardy/auto-fix-panel.css +0 -108
  365. package/src/ardy/auto-physics.js +0 -1194
  366. package/src/ardy/client.js +0 -153
  367. package/src/ardy/convert.js +0 -313
  368. package/src/ardy/cskel27-neutral.js +0 -39
  369. package/src/ardy/cskel27.js +0 -77
  370. package/src/ardy/export.js +0 -165
  371. package/src/ardy/fix-collisions.js +0 -2257
  372. package/src/ardy/foot-lock.js +0 -230
  373. package/src/ardy/motion-calibration.js +0 -118
  374. package/src/ardy/motion-edit.js +0 -213
  375. package/src/ardy/motion-url.js +0 -55
  376. package/src/ardy/mp4-duration.js +0 -102
  377. package/src/ardy/npz.js +0 -595
  378. package/src/ardy/physics-panel.css +0 -21
  379. package/src/ardy/physics-panel.jsx +0 -89
  380. package/src/ardy/physics-refine.js +0 -111
  381. package/src/ardy/physics-review.js +0 -567
  382. package/src/ardy/physics-temporal.js +0 -54
  383. package/src/ardy/platform-fit-panel.css +0 -64
  384. package/src/ardy/platform-fit-panel.jsx +0 -41
  385. package/src/ardy/platform-fit.js +0 -326
  386. package/src/ardy/playback.js +0 -711
  387. package/src/ardy/pose-pin.js +0 -97
  388. package/src/ardy/prompt-clips.js +0 -30
  389. package/src/ardy/retime.js +0 -211
  390. package/src/ardy/root-drop.js +0 -369
  391. package/src/ardy/timeline-resize.js +0 -13
  392. package/src/ardy/to-cskel27.js +0 -225
  393. package/src/ardy/trim.js +0 -33
  394. package/src/ardy/waypoints.js +0 -369
  395. package/src/ardy-bridge-contract.js +0 -281
  396. package/src/domains/motion/motion-video-capture.js +0 -664
  397. package/src/i2v-motion-client.js +0 -77
  398. package/src/i2v-motion-studio.jsx +0 -180
  399. package/src/line-edit.js +0 -1348
  400. package/src/motion/generation.js +0 -105
  401. package/src/motion-readiness-ui.jsx +0 -67
  402. package/src/motion-readiness.js +0 -40
  403. package/src/motion-resources.js +0 -177
  404. package/src/motion-store.js +0 -65
  405. package/src/motion-trail.js +0 -601
  406. package/src/multimodel-ingest.js +0 -394
  407. package/src/panels/PromptBlocksPanel.jsx +0 -444
  408. package/src/panels/VideoCapturePanel.jsx +0 -181
  409. package/src/pose-extract/browser.js +0 -42
  410. package/src/pose-extract/detector.js +0 -100
  411. package/src/pose-extract/fit.js +0 -227
  412. package/src/pose-extract/image-frame.js +0 -51
  413. package/src/pose-extract/index.js +0 -58
  414. package/src/pose-extract/keyframes.js +0 -74
  415. package/src/pose-extract/landmarks.js +0 -162
  416. package/src/pose-extract/mirror.js +0 -153
  417. package/src/pose-extract/take.js +0 -131
  418. package/src/pose-extract/video-frames.js +0 -91
  419. package/src/take-recipe.js +0 -165
  420. package/src/trail-key-conflicts.js +0 -39
  421. package/src/trail-pick.js +0 -59
  422. package/src/use-i2v-capture-modal.js +0 -15
  423. package/tools/ardy/BRIDGE.md +0 -37
  424. package/tools/ardy/GVHMR-NPZ.md +0 -68
  425. package/tools/ardy/README.md +0 -124
  426. package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
  427. package/tools/ardy/artifacts.mjs +0 -34
  428. package/tools/ardy/bridge.mjs +0 -1732
  429. package/tools/ardy/bvh-cskel27.mjs +0 -1265
  430. package/tools/ardy/cclay_constrained_generate.py +0 -561
  431. package/tools/ardy/cclay_gvhmr_worker.py +0 -264
  432. package/tools/ardy/cclay_motion_edit.py +0 -510
  433. package/tools/ardy/cclay_sequence_generate.py +0 -705
  434. package/tools/ardy/cclay_worker.py +0 -304
  435. package/tools/ardy/dump-npz.py +0 -205
  436. package/tools/ardy/extract-rest.mjs +0 -299
  437. package/tools/ardy/extract.mjs +0 -507
  438. package/tools/ardy/footage.mjs +0 -467
  439. package/tools/ardy/gvhmr-floor.mjs +0 -102
  440. package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
  441. package/tools/ardy/gvhmr_fastpath.py +0 -168
  442. package/tools/ardy/gvhmr_trajectory.py +0 -240
  443. package/tools/ardy/merge-text-encoder.py +0 -160
  444. package/tools/ardy/mocap-metrics.mjs +0 -200
  445. package/tools/ardy/mocap-quality-gate.mjs +0 -110
  446. package/tools/ardy/motion-stabilize.mjs +0 -348
  447. package/tools/ardy/npz.mjs +0 -414
  448. package/tools/ardy/pose-to-npz.mjs +0 -106
  449. package/tools/ardy/prompt-limits.mjs +0 -5
  450. package/tools/ardy/run-edit-on-box.sh +0 -73
  451. package/tools/ardy/run-local.mjs +0 -233
  452. package/tools/ardy/run-on-box.sh +0 -593
  453. package/tools/ardy/run-sequence-on-box.sh +0 -177
  454. package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
  455. package/tools/ardy/runners/index.mjs +0 -18
  456. package/tools/ardy/runners/local.mjs +0 -455
  457. package/tools/ardy/runners/proc.mjs +0 -125
  458. package/tools/ardy/runners/remote.mjs +0 -252
  459. package/tools/ardy/setup-local.mjs +0 -189
  460. package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
  461. package/tools/ardy/setup-text-encoder.py +0 -306
  462. package/tools/ardy/smpl-cskel27.mjs +0 -178
  463. package/tools/ardy/visual-qa.mjs +0 -196
  464. package/tools/ardy/vq-car.mjs +0 -52
  465. package/tools/bench/EXP3.md +0 -61
  466. package/tools/bench/cclay_bench_extract_incam.py +0 -125
  467. package/tools/bench/cclay_bench_extract_obs.py +0 -204
  468. package/tools/bench/cclay_bench_runner.py +0 -42
  469. package/tools/bench/cube-contact.mjs +0 -162
  470. package/tools/bench/exp3.mjs +0 -152
  471. package/tools/bench/extract-bench-lib.mjs +0 -216
  472. package/tools/bench/extract-bench.mjs +0 -302
  473. package/tools/bench/fal-generate.mjs +0 -88
  474. package/tools/bench/fit/README.md +0 -189
  475. package/tools/bench/fit/camera.mjs +0 -59
  476. package/tools/bench/fit/contact.mjs +0 -419
  477. package/tools/bench/fit/footlock.mjs +0 -234
  478. package/tools/bench/fit/motion.mjs +0 -85
  479. package/tools/bench/fit/pin.mjs +0 -27
  480. package/tools/bench/fit/remote.mjs +0 -105
  481. package/tools/bench/fit-bench.mjs +0 -126
  482. package/tools/bench/fit-sanity.mjs +0 -45
  483. package/tools/bench/metrics.mjs +0 -313
  484. package/tools/bench/obs/depth.mjs +0 -258
  485. package/tools/bench/obs/extrinsics.mjs +0 -175
  486. package/tools/bench/obs/fit_mannequin_betas.py +0 -340
  487. package/tools/bench/obs/ground.mjs +0 -294
  488. package/tools/bench/obs/heading.mjs +0 -151
  489. package/tools/bench/obs/ladder.mjs +0 -555
  490. package/tools/bench/obs/mannequin-betas.json +0 -124
  491. package/tools/bench/obs/remote.mjs +0 -83
  492. package/tools/bench/obs/rest_joints.py +0 -52
  493. package/tools/bench/obs/ybot-targets.mjs +0 -49
  494. package/tools/bench/obs-bench.mjs +0 -520
  495. package/tools/bench/score.mjs +0 -343
  496. package/tools/bench/summarize.mjs +0 -86
  497. package/tools/demo-worker/README.md +0 -137
  498. package/tools/demo-worker/api-client.mjs +0 -233
  499. package/tools/demo-worker/generate.mjs +0 -301
  500. package/tools/demo-worker/index.mjs +0 -466
  501. package/tools/demo-worker/sign-core.mjs +0 -112
  502. package/tools/demo-worker/sign.mjs +0 -161
  503. package/tools/gt-render/browser.mjs +0 -159
  504. package/tools/gt-render/camera-math.mjs +0 -276
  505. package/tools/gt-render/page.mjs +0 -267
  506. package/tools/gt-render/render.mjs +0 -514
  507. package/tools/gt-render/scene-box.mjs +0 -31
  508. package/tools/gt-render/take-transform.mjs +0 -87
  509. package/tools/kimodo/compare-seam.mjs +0 -108
  510. package/tools/kimodo/constraints.mjs +0 -244
  511. package/tools/kimodo/edit.mjs +0 -259
  512. package/tools/kimodo/effector-constraints.mjs +0 -200
  513. package/tools/kimodo/generate.mjs +0 -646
  514. package/tools/kimodo/local-output.mjs +0 -265
  515. package/tools/kimodo/measure-pose.mjs +0 -65
  516. package/tools/kimodo/measure-preserve.mjs +0 -899
  517. package/tools/kimodo/measure-waypoints.mjs +0 -55
  518. package/tools/kimodo/mlx-generate.py +0 -111
  519. package/tools/kimodo/pose-constraints.mjs +0 -248
  520. package/tools/kimodo/preserve-mask.mjs +0 -543
  521. package/tools/kimodo/read-npz.mjs +0 -189
  522. package/tools/kimodo/run-edit-on-box.mjs +0 -155
  523. package/tools/kimodo/run-sequence-on-box.mjs +0 -178
  524. package/tools/kimodo/runner.mjs +0 -284
  525. package/tools/kimodo/seam-batch.mjs +0 -77
  526. package/tools/kimodo/setup-local.mjs +0 -30
  527. package/tools/kimodo/setup-on-box.sh +0 -339
  528. package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
  529. package/tools/morphgs/assets/gen_truth.py +0 -39
  530. package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
  531. package/tools/morphgs/assets/playback-check.mjs +0 -30
  532. package/tools/morphgs/demo-gate.sh +0 -26
  533. package/tools/morphgs/fbx2morphgs.mjs +0 -68
  534. package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
  535. package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
  536. package/tools/morphgs/setup-on-cluster.sh +0 -126
  537. package/tools/projflow/driver.py +0 -1069
  538. package/tools/projflow/generate.mjs +0 -805
  539. package/tools/projflow/hml22-to-cskel27.mjs +0 -735
  540. package/tools/projflow/line-edit-job.mjs +0 -547
  541. package/tools/projflow/replay.mjs +0 -452
  542. package/tools/projflow/runner.mjs +0 -269
  543. package/tools/projflow/service.mjs +0 -742
  544. package/tools/track/DESIGN.md +0 -513
  545. package/tools/track/backfill-provenance.mjs +0 -116
  546. package/tools/track/budget.mjs +0 -8
  547. package/tools/track/check-rig.mjs +0 -209
  548. package/tools/track/diagnostics.schema.json +0 -60
  549. package/tools/track/export-rig.mjs +0 -256
  550. package/tools/track/fallback.mjs +0 -7
  551. package/tools/track/fk-parity-fixture.mjs +0 -161
  552. package/tools/track/gate.mjs +0 -349
  553. package/tools/track/masks.mjs +0 -318
  554. package/tools/track/metrics.mjs +0 -201
  555. package/tools/track/publish-obs.mjs +0 -108
  556. package/tools/track/py/check_env.py +0 -61
  557. package/tools/track/py/eval_lr.py +0 -229
  558. package/tools/track/py/lr_viterbi.py +0 -294
  559. package/tools/track/py/masks.py +0 -405
  560. package/tools/track/py/objective.py +0 -382
  561. package/tools/track/py/rig.py +0 -508
  562. package/tools/track/py/scene.py +0 -326
  563. package/tools/track/py/test_joint_indices.py +0 -123
  564. package/tools/track/py/test_lr_viterbi.py +0 -195
  565. package/tools/track/py/test_masks.py +0 -229
  566. package/tools/track/py/test_rig.py +0 -288
  567. package/tools/track/py/test_scene.py +0 -354
  568. package/tools/track/py/test_track.py +0 -328
  569. package/tools/track/py/track.py +0 -411
  570. package/tools/track/remote.mjs +0 -140
  571. package/tools/track/rig-dump.mjs +0 -227
  572. package/tools/track/run-box-tests.mjs +0 -14
  573. package/tools/track/run-box.mjs +0 -168
  574. package/tools/track/setup-box.sh +0 -59
  575. package/tools/track/study-2d.mjs +0 -728
  576. /package/src/{ardy → motion}/collision-blockers.js +0 -0
  577. /package/src/{ardy → motion}/ground.js +0 -0
  578. /package/src/{ardy → motion}/ik-drag.js +0 -0
  579. /package/src/{ardy → motion}/ik-key-json.js +0 -0
  580. /package/src/{ardy → motion}/ik.js +0 -0
  581. /package/src/{ardy → motion}/physics-surface.js +0 -0
  582. /package/src/{ardy → motion}/playback-clock.js +0 -0
  583. /package/src/{ardy → motion}/range-pin.js +0 -0
@@ -1,444 +0,0 @@
1
- import { useState } from "react";
2
- import Foldout from "./Foldout.jsx";
3
- import { ko, isKo } from "../locale.js";
4
- import { Field, Dropdown } from "../ui.jsx";
5
- import { LINE_EDIT_TRACK_OPTIONS, MIN_CURVE_POINTS, lineTrackLabel } from "../app-stage.jsx";
6
- import { LINE_EDIT_PINS_MAX, DRAG_RADIUS_MIN, DRAG_RADIUS_MAX, MAX_LINE_POINTS, PINNED_CURVE_ENDS } from "../line-edit.js";
7
- import { motionReadinessMessage, MotionReadiness } from "../motion-readiness-ui.jsx";
8
- import { useCastTransaction } from '../domains/cast.js';
9
- import { useMotionCommands } from '../domains/motion.js';
10
- import { useStudioShell } from '../shell/studio-shell-context.js';
11
- import "./motion.css";
12
-
13
- export default function PromptBlocksPanel({
14
- isCharacterSelection, promptBlocksReveal, promptClips, selectedPromptId, setSelectedPromptId,
15
- setArdyPrompt, setTlFrame, tlFrameCount, ardySeed, changeArdySeed, motion, lineEditMode,
16
- toggleLineEditMode, linePreviewUrl, lineCurve, lineDrifted, lineTrack, setLineTrack, linePinMode,
17
- setLinePinMode, linePins, lineClipFrames, lineEditRange, setLineRange, lineRadius, changeLineRadius,
18
- lineCurveDirty, lineEditFrom, lineEditTo, lineCurvePointCount, lineDriftHint, lineCurveHidden,
19
- linePreviewBusy, linePreviewMs, linePreviewError, generationBusy, bridgeChecking, bridge,
20
- lineReadinessState, runLineEdit, openMotionSetup, recheckMotionHealth, resetLineCurve, exitLineEditMode,
21
- readinessState, ardyRunning, cancelArdy, ardyStatus, ardyOutcome,
22
- }) {
23
- const { run, begin, commit, characterId } = useCastTransaction();
24
- const { refineDisabledReason, workflowMode, previsMode } = useStudioShell();
25
- const selectedClip = promptClips.find((clip) => clip.id === selectedPromptId) ?? null;
26
- const refineReason = refineDisabledReason();
27
- // A storyboard has no prompt blocks to author or edit.
28
- if (previsMode === "storyboard") return null;
29
- // Generate, Start over, Take it again and Add block live in the top bar's
30
- // Generate Motion button and its caret menu, their one home (R1).
31
- return (
32
- <>
33
- <Foldout hidden={!isCharacterSelection} defaultOpen={false} openSignal={promptBlocksReveal} title={ko("Prompt Blocks", "프롬프트 블록")}>
34
- <p className="inspector-hint">{ko("Blocks define what is generated over each frame range. Selecting one also moves editing context to that prompt.", "블록은 각 프레임 범위에서 생성될 내용을 정합니다. 블록을 선택하면 편집 기준도 해당 프롬프트로 이동합니다.")}</p>
35
- <div className="inspector-list">
36
- {promptClips.map((clip) => (
37
- <button
38
- type="button"
39
- key={clip.id}
40
- className={selectedPromptId === clip.id ? "active" : ""}
41
- onClick={() => {
42
- setSelectedPromptId(clip.id);
43
- setArdyPrompt(clip.text);
44
- setTlFrame(Math.min(clip.startFrame, tlFrameCount - 1));
45
- }}
46
- >
47
- <span>{clip.text || ko("Untitled motion", "이름 없는 모션")}</span>
48
- <small>{clip.startFrame}–{clip.endFrame}f</small>
49
- </button>
50
- ))}
51
- </div>
52
- {selectedClip && (
53
- <Field label={ko("Range", "구간")}>
54
- <span className="motion-block-range" data-block-range={`${selectedClip.startFrame}-${selectedClip.endFrame}`}>
55
- {selectedClip.startFrame}–{selectedClip.endFrame} f
56
- </span>
57
- </Field>
58
- )}
59
- {selectedPromptId && (
60
- <Field label={ko("Prompt", "프롬프트")}>
61
- <input
62
- type="text"
63
- value={promptClips.find((clip) => clip.id === selectedPromptId)?.text ?? ""}
64
- onBlur={commit}
65
- onChange={(event) => {
66
- begin();
67
- run('character.changePromptBlock', { characterId, id: selectedPromptId, text: event.target.value });
68
- setArdyPrompt(event.target.value);
69
- }}
70
- placeholder={ko("describe this motion block", "이 모션 블록을 설명하세요")}
71
- />
72
- </Field>
73
- )}
74
- {/* The seed belongs with the button that consumes it. Duration does
75
- not appear at all: the blocks' own frame ranges are the length. */}
76
- <Field label={ko("Seed", "시드")}>
77
- <input
78
- type="text"
79
- inputMode="numeric"
80
- value={ardySeed}
81
- onChange={(e) => changeArdySeed(e.target.value)}
82
- placeholder={ko("empty = random", "비우면 랜덤")}
83
- />
84
- </Field>
85
- {/* Scheduled inpainting used to live here, beside the batch button.
86
- It now folds into Scene > Advanced above the timeline (contract
87
- C12): it is a dial on a regeneration, so it belongs with the
88
- regeneration entry rather than with the block list. */}
89
- {/* Line editing (contract C6). It sits beside the preserve slider
90
- because it answers the same question from the other side —
91
- preserve says how much of the take to KEEP, a line says exactly
92
- where one joint must GO — and because both need a take with a
93
- bridge source, so the whole section is absent until there is one
94
- rather than present and inert. */}
95
- {motion?.url && (
96
- <Field label={ko("Line editing", "라인 편집")}>
97
- {/* Refine: the take bar's second entry, until it becomes motion tool E. */}
98
- <button
99
- type="button"
100
- className={"btn full" + (lineEditMode ? " primary" : "")}
101
- data-take-mode="refine"
102
- data-disabled-reason={refineReason || undefined}
103
- aria-pressed={lineEditMode}
104
- title={ko(
105
- "The joint's own path is drawn on the viewport — grab a point on it and pull, or draw a new path on empty space; the joint then follows it exactly. The view still orbits normally (Alt+drag).",
106
- "관절이 지나가는 궤적이 뷰포트에 그려집니다 — 궤적 위의 점을 잡아 끌거나, 빈 곳에 새 궤적을 그리면 관절이 그 경로를 정확히 따라갑니다. 시점은 평소처럼 돌릴 수 있어요 (Alt+드래그).",
107
- )}
108
- onClick={toggleLineEditMode}
109
- >
110
- {lineEditMode ? ko("Path editing on", "궤적 편집 켜짐") : ko("Drag the path", "궤적을 잡아 끌기")}
111
- </button>
112
- {lineEditMode && (
113
- <div
114
- className="line-edit-panel"
115
- data-line-preview={linePreviewUrl ? "true" : undefined}
116
- // "The line is detached from this view" — the panel's own copy of
117
- // what the stage already carries, so a test (or a screenshot) can
118
- // read the state from whichever of the two it is looking at.
119
- data-line-drift={lineCurve && lineDrifted ? "true" : undefined}
120
- >
121
- <Field label={ko("Joint", "관절")}>
122
- <Dropdown
123
- value={lineTrack}
124
- options={LINE_EDIT_TRACK_OPTIONS}
125
- onChange={setLineTrack}
126
- ariaLabel={ko("Joint whose path is edited", "궤적을 편집할 관절")}
127
- />
128
- </Field>
129
- {/* THE GESTURE SELECTOR. Pressing on the joint is how BOTH a
130
- curve drag and a pin start, so the two cannot share a
131
- press and a modal toggle is the honest way to say which
132
- one the next press means. Named for what it does at the
133
- moment it does it, not for the wire field. */}
134
- <button
135
- type="button"
136
- className={"btn full" + (linePinMode ? " primary" : "")}
137
- data-line-pin-mode={linePinMode ? "true" : "false"}
138
- onClick={() => setLinePinMode((on) => !on)}
139
- >
140
- {linePinMode
141
- ? ko("Pinning moments", "순간 찍는 중")
142
- : ko("Pin a moment", "순간 찍기")}
143
- </button>
144
- {linePinMode && (
145
- <p className="inspector-hint">
146
- {linePins.length
147
- ? (isKo
148
- ? `${linePins.length}개(최대 ${LINE_EDIT_PINS_MAX}개)를 찍었어요 — 프레임 ${linePins.map((pin) => pin.frame).join(", ")}. 사이 동작은 모델이 채웁니다`
149
- : `${linePins.length} pinned (max ${LINE_EDIT_PINS_MAX}) — frames ${linePins.map((pin) => pin.frame).join(", ")}. The model fills the movement between them`)
150
- : ko(
151
- "Scrub to a moment, then drag the green handle to where the joint should be. The take keeps its own timing; only that instant is pinned.",
152
- "원하는 순간으로 재생 위치를 옮긴 뒤, 초록 손잡이를 관절이 있어야 할 자리로 끌어 주세요. 그 순간만 고정되고 나머지 타이밍은 그대로예요.",
153
- )}
154
- </p>
155
- )}
156
- {/* No range picker exists elsewhere in the app that a line
157
- edit could borrow, so the whole clip is the default and
158
- these two numbers only ever NARROW it. endFrame is
159
- exclusive, like every other half-open range on this wire. */}
160
- <Field label={ko("Frame range", "프레임 구간")}>
161
- <div className="line-edit-range-row">
162
- <input
163
- type="number"
164
- min={0}
165
- max={Math.max(0, lineClipFrames - 2)}
166
- value={lineEditRange?.startFrame ?? 0}
167
- onChange={(event) => setLineRange((current) => ({
168
- startFrame: Math.round(Number(event.target.value)) || 0,
169
- endFrame: current?.endFrame ?? lineClipFrames,
170
- }))}
171
- />
172
- <span aria-hidden="true">–</span>
173
- <input
174
- type="number"
175
- min={2}
176
- max={lineClipFrames}
177
- value={lineEditRange?.endFrame ?? lineClipFrames}
178
- onChange={(event) => setLineRange((current) => ({
179
- startFrame: current?.startFrame ?? 0,
180
- endFrame: Math.round(Number(event.target.value)) || 0,
181
- }))}
182
- />
183
- </div>
184
- </Field>
185
- {/* How far a pull carries along the path, in FRAMES — the
186
- sigma of the Gaussian falloff, said in the unit the user
187
- is looking at. Narrow is a beat, wide is a whole gesture. */}
188
- <Field label={ko("Influence", "영향 범위")}>
189
- <div className="line-edit-radius-row">
190
- <input
191
- type="range"
192
- min={DRAG_RADIUS_MIN}
193
- max={DRAG_RADIUS_MAX}
194
- step={1}
195
- value={lineRadius}
196
- aria-label={ko("How many frames a pull carries along the path", "잡아당길 때 궤적을 따라 함께 움직이는 프레임 수")}
197
- onChange={(event) => changeLineRadius(event.target.value)}
198
- />
199
- <span className="line-edit-radius-value">
200
- {isKo ? `${lineRadius}프레임` : `${lineRadius} frames`}
201
- </span>
202
- </div>
203
- </Field>
204
- <p className="inspector-hint">
205
- {lineCurveDirty
206
- ? (isKo
207
- ? `${lineEditFrom}–${lineEditTo} 프레임을 편집했어요 — ${lineCurvePointCount}개 점(최대 ${MAX_LINE_POINTS}개)을 보내고, 양 끝은 원래 궤적에서 부드럽게 이어져 이음매가 튀지 않아요. 다시 끌거나 다시 그려서 다듬을 수 있어요`
208
- : `Frames ${lineEditFrom}–${lineEditTo} edited — ${lineCurvePointCount} points (max ${MAX_LINE_POINTS}); both ends ease out of the original path, so the seams do not pop. Pull it again, or draw over it, to refine`)
209
- : ko(
210
- "Draw along the path to reroute that section — the frames you drew over become the range, and the take's own timing is kept. Or grab a yellow dot and pull.",
211
- "궤적을 따라 그리면 그 구간만 새로 지나갑니다 — 그린 만큼이 편집 구간이 되고, 원래 속도감은 그대로 유지돼요. 노란 점을 잡아 끌어도 됩니다.",
212
- )}
213
- </p>
214
- {/* The one thing users assume a modal viewport tool takes away.
215
- Said out loud, because "can I still orbit?" is the first
216
- question and the answer decides whether the mode is usable. */}
217
- {/* THE DETACHED STATE. Said inline, next to the edit it is about,
218
- and in the same words the refused gesture answers with. It is
219
- a status, not a warning: nothing was lost and nothing needs
220
- doing — the only thing that changed is that the line cannot be
221
- drawn in a view it was not aimed through. */}
222
- {lineCurve && lineDrifted && (
223
- <p className="inspector-hint line-edit-drift" aria-live="polite">
224
- {lineDriftHint()}
225
- </p>
226
- )}
227
- <p className="inspector-hint">
228
- {lineCurveDirty
229
- ? ko(
230
- "You can still orbit (Alt+drag), pan and fly freely — the edit survives it. It was aimed through one lens, so while the view is elsewhere the line is drawn ghosted and a new pull waits; Generate, undo and Reset work from anywhere.",
231
- "시점은 자유롭게 돌리고(Alt+드래그) 옮길 수 있어요 — 편집은 그대로 남습니다. 다만 이 궤적은 처음 시점 기준이라, 시점을 옮기면 흐리게만 보이고 새로 끌기는 잠시 멈춰요. 생성·되돌리기·원래대로는 언제든 됩니다.",
232
- )
233
- : ko(
234
- "You can still orbit (Alt+drag), pan and fly freely; the path follows the view until you pull or draw it.",
235
- "시점은 평소처럼 자유롭게 돌리고(Alt+드래그) 옮길 수 있어요. 끌거나 그리기 전까지 궤적은 시점을 따라갑니다.",
236
- )}
237
- </p>
238
- {lineEditRange && lineEditRange.endFrame - lineEditRange.startFrame < MIN_CURVE_POINTS && (
239
- <p className="inspector-hint">
240
- {isKo
241
- ? `구간이 너무 짧아요 — 양 끝 ${PINNED_CURVE_ENDS}프레임씩이 고정이라 ${MIN_CURVE_POINTS}프레임 이상이어야 잡을 점이 생겨요`
242
- : `This range is too short — with ${PINNED_CURVE_ENDS} pinned frames at each end it needs at least ${MIN_CURVE_POINTS} frames before anything can be grabbed`}
243
- </p>
244
- )}
245
- {lineCurveHidden > 0 && (
246
- <p className="inspector-hint">
247
- {isKo
248
- ? `${lineCurveHidden}프레임이 화면 밖이라 잡을 수 없어요 — 구간 전체가 보이도록 카메라를 잡아 주세요`
249
- : `${lineCurveHidden} frame(s) are outside the frame and cannot be grabbed — frame the whole range in view`}
250
- </p>
251
- )}
252
- {/* ------------------------- the preview line -------------------
253
- One quiet row that says which of three things is true: a
254
- draft is being made, a draft is on screen (and how long it
255
- took), or the last one failed and the curve is still here.
256
- Deliberately not a spinner over the viewport — the artist
257
- is LOOKING at the viewport, and the answer arrives there. */}
258
- {linePreviewBusy && (
259
- <p className="inspector-hint line-preview-busy" aria-live="polite">
260
- {ko("Previewing the pull…", "당긴 결과 미리보는 중…")}
261
- </p>
262
- )}
263
- {!linePreviewBusy && linePreviewUrl && (
264
- <p className="inspector-hint line-preview-live">
265
- {ko(
266
- "The viewport is showing this edit at full quality — press Generate to keep it as the take.",
267
- "뷰포트가 지금 이 편집의 최종 품질 결과예요 — 아래 생성을 누르면 테이크로 확정됩니다.",
268
- )}
269
- {linePreviewMs > 0 && (
270
- <span className="line-preview-time">
271
- {isKo ? ` 미리보기 ${(linePreviewMs / 1000).toFixed(1)}s` : ` preview ${(linePreviewMs / 1000).toFixed(1)}s`}
272
- </span>
273
- )}
274
- </p>
275
- )}
276
- {/* A failed draft is not a failed edit: the pull survives it and
277
- the button below still runs the real thing. */}
278
- {linePreviewError && (
279
- <p className="inspector-hint line-preview-error">
280
- {isKo ? `미리보기 실패 — ${linePreviewError} (생성은 그대로 됩니다)` : `Preview failed — ${linePreviewError} (Generate still works)`}
281
- </p>
282
- )}
283
- <button
284
- type="button"
285
- className="btn primary full generate"
286
- disabled={!lineCurveDirty || generationBusy || bridgeChecking || bridge === null}
287
- title={generationBusy ? ko("A generation is already running", "이미 생성이 돌고 있어요")
288
- : !lineCurveDirty
289
- ? ko("Pull the path on the viewport first", "먼저 뷰포트에서 궤적을 잡아당겨 주세요")
290
- : motionReadinessMessage(lineReadinessState)}
291
- onClick={runLineEdit}
292
- >
293
- {ko("Generate the line edit", "라인 편집 생성")}
294
- </button>
295
- <MotionReadiness state={lineReadinessState} checking={bridgeChecking} onSetup={() => openMotionSetup("line")} onRetry={recheckMotionHealth} />
296
- <button type="button" className="btn ghost full" disabled={!lineCurveDirty} onClick={resetLineCurve}>
297
- {ko("Reset the curve", "원래대로")}
298
- </button>
299
- <button type="button" className="btn ghost full" onClick={exitLineEditMode}>
300
- {ko("Exit line editing (Esc)", "라인 편집 끝내기 (Esc)")}
301
- </button>
302
- </div>
303
- )}
304
- </Field>
305
- )}
306
- {ardyRunning && (
307
- <button type="button" className="btn ghost full" onClick={cancelArdy}>
308
- {ko("Cancel run", "실행 취소")}
309
- </button>
310
- )}
311
- {!lineEditMode && <MotionReadiness state={readinessState} checking={bridgeChecking} onSetup={openMotionSetup} onRetry={recheckMotionHealth} />}
312
- {ardyRunning && ardyStatus && <p className="ardy-status" role="status">{ardyStatus}</p>}
313
- {!ardyRunning && ardyOutcome?.ok === false && <p className="ardy-status" role="alert">{ardyOutcome.message}</p>}
314
- {!ardyRunning && ardyOutcome?.ok === true && <p className="ardy-status" role="status">{ko("Motion generation complete", "모션 생성 완료")}</p>}
315
- {motion?.url && <MotionAdvanced />}
316
- </Foldout>
317
- <TakesSection hidden={!isCharacterSelection || workflowMode === "scene" || workflowMode === "camera"} />
318
- </>
319
- );
320
- }
321
-
322
- /* Motion › Advanced: the dials that decide how much of the loaded take a
323
- regeneration keeps. Folded away because the default (half preserved, whole
324
- body free) is right almost always. */
325
- function MotionAdvanced() {
326
- const { preserveStrength, setPreserveStrength, waypointMode, preserveTracksLine } = useStudioShell();
327
- const [open, setOpen] = useState(false);
328
- return (
329
- <div className="motion-advanced">
330
- <button type="button" className="motion-advanced-head" aria-expanded={open} onClick={() => setOpen((value) => !value)}>
331
- <span className="v2-details-foldout-arrow foldout-arrow" data-open={open ? "true" : "false"} aria-hidden="true" />
332
- {ko("Advanced", "고급")}
333
- </button>
334
- {open && (
335
- <div className="motion-advanced-body">
336
- <label className="row">
337
- <span>{ko("Keep current take", "현재 테이크 유지")}</span>
338
- <input
339
- type="range"
340
- data-preserve-strength
341
- min={0}
342
- max={1}
343
- step={0.05}
344
- value={preserveStrength}
345
- title={ko(
346
- "How hard the regeneration holds the loaded take outside the frames you edited.",
347
- "수정하지 않은 프레임에서 로드된 테이크를 얼마나 강하게 유지할지 정합니다.",
348
- )}
349
- onChange={(event) => setPreserveStrength(Number(event.target.value))}
350
- />
351
- <span className="val preserve-strength-value">{Math.round(preserveStrength * 100)}%</span>
352
- </label>
353
- {/* The slider value IS the preserve strength: 0 (left) is a fresh
354
- take and 1 (right) holds the original hardest. */}
355
- <p className="inspector-hint motion-preserve-scale">
356
- <span>{ko("generate fresh", "새로 생성")}</span>
357
- <span>{ko("keep original", "원본 유지")}</span>
358
- </p>
359
- {waypointMode && preserveStrength > 0 && (
360
- <p className="inspector-hint">
361
- {ko(
362
- "the drawn path replaces the root; the body keeps the take's style",
363
- "경로는 새로 그려지고, 동작 스타일은 원본을 유지해요",
364
- )}
365
- </p>
366
- )}
367
- {preserveStrength > 0 && preserveTracksLine && (
368
- <p className="inspector-hint preserve-tracks-summary">{preserveTracksLine}</p>
369
- )}
370
- </div>
371
- )}
372
- </div>
373
- );
374
- }
375
-
376
- /* Takes (G6): every successful run leaves a checkpoint. Clicking a row loads
377
- that take back and restores the recipe it was saved with; loading never
378
- drops a row, so an experiment can always be walked back. */
379
- function TakesSection({ hidden }) {
380
- const { run } = useMotionCommands();
381
- const { takeVersions, takeSourceUrl, takeRecipe, replayNotices, linePreviewUrl } = useStudioShell();
382
- return (
383
- <Foldout hidden={hidden} title={ko("Takes", "테이크")}>
384
- <div
385
- className="motion-takes"
386
- data-take-source={takeSourceUrl || undefined}
387
- // The draft's url beside the take's own, so "the viewport swapped but
388
- // the take did not" is one comparison rather than an inference.
389
- data-line-preview={linePreviewUrl ? "true" : undefined}
390
- data-line-preview-url={linePreviewUrl || undefined}
391
- >
392
- {takeVersions.length > 0 ? (
393
- <div className="motion-take-list" role="group" aria-label={ko("Take versions", "테이크 버전")}>
394
- {takeVersions.map((entry, index) => {
395
- const current = entry.motionUrl === takeSourceUrl;
396
- return (
397
- <button
398
- type="button"
399
- key={entry.motionUrl}
400
- className={"motion-take-row" + (current ? " current" : "")}
401
- data-version-url={entry.motionUrl}
402
- data-version-current={current ? "true" : undefined}
403
- aria-pressed={current}
404
- title={`${entry.label} · ${new Date(entry.savedAt).toLocaleTimeString()}`}
405
- onClick={() => run('motion.loadVersion', { motionUrl: entry.motionUrl })}
406
- >
407
- <span className="motion-take-index">v{index + 1}</span>
408
- <span className="motion-take-label">{entry.label}</span>
409
- <span className="motion-take-time">
410
- {new Date(entry.savedAt).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hourCycle: "h23" })}
411
- </span>
412
- </button>
413
- );
414
- })}
415
- </div>
416
- ) : (
417
- <p className="inspector-hint">{ko("No takes yet. Generate creates one.", "아직 테이크가 없어요. 생성하면 하나가 생깁니다.")}</p>
418
- )}
419
- {/* C10's per-entry replay verdict. Non-blocking: the take is loaded,
420
- one refinement just did not survive the trip onto it. */}
421
- {replayNotices.map((entry) => (
422
- <p className="inspector-hint replay-notice" key={`${entry.index}-${entry.track}`} data-replay-index={entry.index} data-replay-track={entry.track}>
423
- {entry.ok === false
424
- ? (isKo
425
- ? `다듬기 ${entry.index + 1}(${lineTrackLabel(entry.track)})은 다시 적용되지 않았어요 — 나머지는 그대로 이어졌습니다${entry.error ? ` (${entry.error})` : ""}`
426
- : `Refinement ${entry.index + 1} (${lineTrackLabel(entry.track)}) was not re-applied — the rest carried over${entry.error ? ` (${entry.error})` : ""}`)
427
- : (isKo
428
- ? `다듬기 ${entry.index + 1}(${lineTrackLabel(entry.track)})은 블록 경계에 걸쳐 있어요 — 결과가 이전과 조금 다를 수 있습니다`
429
- : `Refinement ${entry.index + 1} (${lineTrackLabel(entry.track)}) straddles a block boundary — the result may differ slightly from before`)}
430
- </p>
431
- ))}
432
- {/* A seedless recipe is an IMPORTED take: it reloads but cannot be
433
- rebuilt, so the footer says so rather than printing "seed null". */}
434
- {takeRecipe && (
435
- <p className="motion-takes-footer take-recipe-summary">
436
- {isKo
437
- ? `시드 ${Number.isInteger(takeRecipe.seed) ? takeRecipe.seed : "알 수 없음(불러온 테이크)"} · 블록 ${takeRecipe.blocks.length}개 · 다듬기 ${takeRecipe.lineEdits.length}개`
438
- : `Seed ${Number.isInteger(takeRecipe.seed) ? takeRecipe.seed : "unknown (imported take)"} · ${takeRecipe.blocks.length} block(s) · ${takeRecipe.lineEdits.length} refinement(s)`}
439
- </p>
440
- )}
441
- </div>
442
- </Foldout>
443
- );
444
- }
@@ -1,181 +0,0 @@
1
- import Foldout from "./Foldout.jsx";
2
- import { ko, isKo } from "../locale.js";
3
- import { footageSummary, trajectoryReceipt, segmentationReceipt } from "../multimodel-ingest.js";
4
- import { isImeComposing } from "../ime.js";
5
-
6
- export default function VideoCapturePanel({
7
- isCharacterSelection, multiModelStatus, multiModelStage, multiModelFileRef, chooseMultiModelFile,
8
- multiModelSource, multiModelUrl, setMultiModelUrl, useMultiModelUrl, pasteMultiModelUrl,
9
- multiModelProgress, multiModelError, multiModelFootage, extractMultiModelMotion, multiModelExtract,
10
- multiModelTake, multiModelExtractProgress, multiModelExtractError, activeChar, bridge,
11
- }) {
12
- return (
13
- <Foldout hidden={!isCharacterSelection} defaultOpen={false} title={ko("Video capture", "영상 모캡")}>
14
- <div className="multimodel-card v2-details-video-card">
15
- <div className="multimodel-card-head">
16
- <div>
17
- <strong>{ko("Footage → motion", "영상 → 모션")}</strong>
18
- <span>{ko("Prepare a source inside the Motion workspace.", "모션 작업공간에서 입력 영상을 준비하세요.")}</span>
19
- </div>
20
- <span className={"multimodel-status " + multiModelStatus}>
21
- {multiModelStatus === "ready"
22
- ? ko("READY", "준비됨")
23
- : multiModelStatus === "error"
24
- ? ko("CHECK", "확인 필요")
25
- : multiModelStatus === "busy"
26
- ? (multiModelStage === "fetching" ? ko("FETCHING", "받는 중") : ko("PROBING", "분석 중"))
27
- : ko("IDLE", "대기")}
28
- </span>
29
- </div>
30
- <div className="multimodel-input-block">
31
- <div className="multimodel-input-label">
32
- <strong>{ko("Local video file", "로컬 비디오 파일")}</strong>
33
- <span>{ko("Upload from this computer", "이 컴퓨터에서 업로드")}</span>
34
- </div>
35
- <div className="multimodel-source-row">
36
- <button type="button" className="btn ghost" onClick={() => multiModelFileRef.current?.click()}>
37
- {ko("Choose video", "영상 선택")}
38
- </button>
39
- <input ref={multiModelFileRef} className="multimodel-file-input" type="file" accept="video/*" onChange={chooseMultiModelFile} />
40
- <span className="multimodel-file-name">{multiModelSource?.kind === "file" ? multiModelSource.name : ko("No file selected", "파일이 선택되지 않음")}</span>
41
- </div>
42
- </div>
43
- <div className="multimodel-input-block">
44
- <div className="multimodel-input-label">
45
- <strong>{ko("Video URL", "비디오 URL")}</strong>
46
- <span>{ko("Use a hosted or local route", "호스팅 또는 로컬 경로 사용")}</span>
47
- </div>
48
- <input
49
- className="multimodel-url-input"
50
- type="text"
51
- value={multiModelUrl}
52
- onChange={(event) => setMultiModelUrl(event.target.value)}
53
- onKeyDown={(event) => { if (event.key === "Enter" && !isImeComposing(event)) useMultiModelUrl(); }}
54
- placeholder={ko("https://…/boxing.mp4", "https://…/boxing.mp4")}
55
- aria-label={ko("Multi-Model video URL", "멀티 모델 영상 URL")}
56
- spellCheck={false}
57
- />
58
- <div className="multimodel-url-actions">
59
- <button type="button" className="btn ghost" onClick={pasteMultiModelUrl}>
60
- {ko("Paste", "붙여넣기")}
61
- </button>
62
- <button type="button" className="btn ghost" onClick={() => setMultiModelUrl("")} disabled={!multiModelUrl}>
63
- {ko("Clear", "지우기")}
64
- </button>
65
- <button type="button" className="btn primary" onClick={useMultiModelUrl} disabled={!multiModelUrl.trim()}>
66
- {ko("Use URL", "URL 사용")}
67
- </button>
68
- </div>
69
- </div>
70
- {multiModelStatus === "busy" && (
71
- <div className="multimodel-progress">
72
- <div className="multimodel-progress-track">
73
- <div
74
- className={"multimodel-progress-bar" + (multiModelProgress === null ? " indeterminate" : "")}
75
- style={multiModelProgress === null ? undefined : { width: `${Math.round(multiModelProgress * 100)}%` }}
76
- />
77
- </div>
78
- <span>
79
- {multiModelStage === "fetching"
80
- ? (multiModelProgress === null
81
- ? ko("Downloading…", "다운로드 중…")
82
- : `${Math.round(multiModelProgress * 100)}%`)
83
- : ko("Decoding…", "디코딩 중…")}
84
- </span>
85
- </div>
86
- )}
87
- {multiModelError && <p className="multimodel-error">{multiModelError}</p>}
88
- {multiModelFootage && (
89
- <div className="multimodel-receipt">
90
- <video className="multimodel-preview" src={multiModelFootage.objectUrl} muted playsInline preload="metadata" />
91
- <div className="multimodel-receipt-body">
92
- <strong>{multiModelSource?.name}</strong>
93
- <span>{footageSummary(multiModelFootage)}</span>
94
- <span className="multimodel-receipt-timeline">
95
- {isKo
96
- ? `타임라인 0–${multiModelFootage.frames - 1} 프레임으로 맞춤`
97
- : `Timeline sized to frames 0–${multiModelFootage.frames - 1}`}
98
- </span>
99
- </div>
100
- </div>
101
- )}
102
- {multiModelFootage && (
103
- <div className="multimodel-extract">
104
- <button
105
- type="button"
106
- className="btn primary"
107
- onClick={extractMultiModelMotion}
108
- disabled={multiModelExtract === "running"}
109
- >
110
- {multiModelExtract === "running"
111
- ? ko("Extracting…", "추출 중…")
112
- : multiModelTake
113
- ? ko("Extract again", "다시 추출")
114
- : ko("Extract motion", "모션 추출")}
115
- </button>
116
- {multiModelExtract === "running" && (
117
- <div className="multimodel-progress">
118
- <div className="multimodel-progress-track">
119
- <div
120
- className={"multimodel-progress-bar" + (multiModelExtractProgress === null ? " indeterminate" : "")}
121
- style={multiModelExtractProgress === null ? undefined : { width: `${Math.round(multiModelExtractProgress * 100)}%` }}
122
- />
123
- </div>
124
- <span>
125
- {multiModelExtractProgress === null
126
- ? ko("Engine…", "엔진 준비…")
127
- : `${Math.round(multiModelExtractProgress * 100)}%`}
128
- </span>
129
- </div>
130
- )}
131
- {multiModelExtract === "error" && <p className="multimodel-error">{multiModelExtractError}</p>}
132
- {multiModelTake && (
133
- <p className="multimodel-extract-receipt">
134
- {multiModelTake.gpu
135
- ? (isKo
136
- ? `GVHMR 테이크 ${multiModelTake.frames}프레임 추출됨 — 타임라인에서 재생하세요`
137
- : `GVHMR take extracted, ${multiModelTake.frames} frames — press play on the timeline`)
138
- : (isKo
139
- ? `${multiModelTake.frames}프레임 테이크 구움 (실측 ${multiModelTake.fitted} · 유지 ${multiModelTake.held}) — 타임라인에서 재생하세요`
140
- : `Baked a ${multiModelTake.frames}-frame take (${multiModelTake.fitted} measured · ${multiModelTake.held} held) — press play on the timeline`)}
141
- </p>
142
- )}
143
- {multiModelTake?.trajectory && <p className="multimodel-note" data-testid="trajectory-receipt">{trajectoryReceipt(multiModelTake.trajectory, isKo)}</p>}
144
- {multiModelTake?.segmentation && <p className="multimodel-note" data-testid="segmentation-receipt">{segmentationReceipt(multiModelTake.segmentation, isKo)}</p>}
145
- {multiModelTake?.quality && <p className="multimodel-note" data-testid="mocap-quality-receipt">
146
- {multiModelTake.quality.pass
147
- ? ko("Mocap quality gate passed", "모캡 품질 게이트 통과")
148
- : ko(`Mocap quality warning: ${multiModelTake.quality.checks?.filter((check) => !check.pass).map((check) => check.name).join(", ") || "review required"}`, `모캡 품질 게이트 경고: ${multiModelTake.quality.checks?.filter((check) => !check.pass).map((check) => check.name).join(", ") || "확인 필요"}`)}
149
- </p>}
150
- {multiModelTake?.gpu && Math.abs(activeChar.y ?? 0) > .001 && <p className="multimodel-note" data-testid="trajectory-stage-offset">{isKo ? `씬 높이 ${(activeChar.y * 100).toFixed(1)}cm가 모션에 추가돼요 (Subject → Y)` : `Scene height ${(activeChar.y * 100).toFixed(1)}cm is added to the motion (Subject → Y)`}</p>}
151
- {multiModelTake?.persons > 1 && (
152
- <p className="multimodel-extract-receipt">
153
- {isKo
154
- ? `${multiModelTake.persons}명의 테이크를 각 인물 레이어에 배치했어요`
155
- : `${multiModelTake.persons} performers landed on their own subject layers`}
156
- </p>
157
- )}
158
- {multiModelExtract === "idle" && !multiModelTake && (
159
- <p className="multimodel-note">
160
- {bridge === null
161
- ? ko("Checking for the dev bridge…", "개발 브리지를 확인하는 중…")
162
- : bridge.ok && bridge.extractionBackend === "gvhmr"
163
- ? ko(
164
- "GVHMR extraction runs on the GPU box (about a minute per 15 s of footage).",
165
- "GVHMR 추출은 GPU 박스에서 돌아갑니다(영상 15초당 약 1분)."
166
- )
167
- : ko(
168
- "GVHMR extraction is unavailable until the local GPU bridge is connected.",
169
- "로컬 GPU 브리지가 연결될 때까지 GVHMR 추출을 사용할 수 없어요."
170
- )}
171
- </p>
172
- )}
173
- </div>
174
- )}
175
- <p className="multimodel-note">
176
- {ko("Locked-off footage with both performers in frame is best.", "두 사람이 함께 보이는 고정 카메라 영상이 가장 적합합니다.")}
177
- </p>
178
- </div>
179
- </Foldout>
180
- );
181
- }