cozyclay 2.1.1 → 3.0.1

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 (585) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +12 -30
  3. package/bin/agent/agent-routes.mjs +43 -116
  4. package/bin/agent/agent-runner.mjs +14 -15
  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/session-store.mjs +2 -2
  14. package/bin/agent/studio-context-budget.mjs +93 -0
  15. package/bin/agent/studio-motion-reference.mjs +23 -0
  16. package/bin/agent/studio-prompt.mjs +1 -1
  17. package/bin/agent/studio-rebase-text.mjs +32 -0
  18. package/bin/agent/studio-rebase.mjs +26 -39
  19. package/bin/agent/studio-tools.mjs +9 -28
  20. package/bin/agent/tool-arguments.mjs +49 -0
  21. package/bin/agent/turn-frames.mjs +66 -0
  22. package/bin/codex-auth.mjs +9 -2
  23. package/bin/cozyclay.mjs +10 -116
  24. package/bin/live/cli.mjs +3 -3
  25. package/bin/mcp-runtime.mjs +2 -12
  26. package/bin/package-signature.mjs +0 -4
  27. package/dist/app/index.html +7 -6
  28. package/dist/assets/EXRLoader-CvVIvGVE.js +1 -0
  29. package/dist/assets/analytics-BWCqdgWA.js +1 -0
  30. package/dist/assets/app-DfTCxaKk.js +5087 -0
  31. package/dist/assets/app-f-fkV5uP.css +1 -0
  32. package/dist/assets/compile-worker-BxKXh07s.js +5 -0
  33. package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
  34. package/dist/assets/{first-shot-handoff-msLI71g1.js → first-shot-handoff-DNO8kv_N.js} +1 -1
  35. package/dist/assets/{landing-ChUvB_zL.js → landing-yfZaJkWc.js} +1 -1
  36. package/dist/assets/scene-asset-sync-U3kS2rvK.js +20 -0
  37. package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
  38. package/dist/assets/workflow-D78eiKTa.js +179 -0
  39. package/dist/cozyclay-package.json +1 -1
  40. package/dist/index.html +3 -3
  41. package/dist/sw.js +3 -6
  42. package/dist/workflow/index.html +5 -4
  43. package/mcp/LIVE-PROTOCOL.md +7 -47
  44. package/mcp/README.md +16 -26
  45. package/mcp/live-hub.mjs +6 -10
  46. package/mcp/package.json +1 -3
  47. package/mcp/tool-handlers.mjs +4 -168
  48. package/package.json +3 -22
  49. package/src/App.jsx +151 -2625
  50. package/src/agent-progress.js +80 -0
  51. package/src/agent-turn-mark.js +30 -0
  52. package/src/analytics.js +1 -19
  53. package/src/app-context.js +12 -2
  54. package/src/app-stage.jsx +2 -34
  55. package/src/asset-pane.jsx +6 -5
  56. package/src/camera-block.js +21 -0
  57. package/src/camera-direction.js +120 -0
  58. package/src/character-kind.js +3 -9
  59. package/src/command-bus.js +10 -8
  60. package/src/commands/cast.js +5 -34
  61. package/src/commands/elements/character.js +1 -1
  62. package/src/commands/elements/motion.js +1 -6
  63. package/src/commands/elements/object.js +6 -2
  64. package/src/commands/elements/shot.js +4 -1
  65. package/src/commands/elements.js +38 -14
  66. package/src/commands/index.js +3 -1
  67. package/src/commands/kits.js +37 -0
  68. package/src/commands/motion-timing.js +57 -0
  69. package/src/commands/motion.js +9 -152
  70. package/src/commands/motion3-compile.js +65 -0
  71. package/src/commands/motion3.js +214 -0
  72. package/src/commands/objects.js +6 -4
  73. package/src/commands/shot.js +55 -13
  74. package/src/commands/stage.js +14 -1
  75. package/src/commands/view.js +4 -1
  76. package/src/document-mirrors.js +42 -0
  77. package/src/document-store.js +4 -0
  78. package/src/domains/cast.js +19 -194
  79. package/src/domains/motion/motion-range-pin-rules.js +1 -1
  80. package/src/domains/motion/take-source.js +53 -0
  81. package/src/domains/motion.js +60 -1838
  82. package/src/domains/scenes.js +12 -55
  83. package/src/domains/shots.js +2 -2
  84. package/src/domains/stage.js +4 -2
  85. package/src/draft-ghost.js +47 -0
  86. package/src/draft-ghost.jsx +129 -0
  87. package/src/dualview.jsx +4 -3
  88. package/src/effects/EffectsLayer.jsx +112 -0
  89. package/src/effects/effect-meshes.js +232 -0
  90. package/src/effects/effect-record.js +103 -0
  91. package/src/effects/emitter.js +59 -0
  92. package/src/effects/simulate.js +261 -0
  93. package/src/effects/state.js +59 -0
  94. package/src/execution-telemetry.js +2 -3
  95. package/src/first-success-guide.jsx +5 -5
  96. package/src/ghost-set.js +257 -0
  97. package/src/held-object-edit.jsx +113 -0
  98. package/src/held-object-pose.js +175 -0
  99. package/src/hierarchy-model.js +1 -1
  100. package/src/hierarchy-panel.jsx +1 -1
  101. package/src/imported-mesh.jsx +103 -0
  102. package/src/kits/held.js +84 -0
  103. package/src/kits/index.js +70 -0
  104. package/src/kits/smoking.js +57 -0
  105. package/src/light-blockers.js +93 -0
  106. package/src/motion/beat-board-model.js +84 -0
  107. package/src/motion/beat-board.css +124 -0
  108. package/src/motion/beat-board.jsx +60 -0
  109. package/src/motion/center-of-mass.js +66 -0
  110. package/src/motion/fix-collisions.js +850 -0
  111. package/src/motion/physics-review.js +118 -0
  112. package/src/{ardy → motion}/physics-support.js +1 -76
  113. package/src/motion/rig-snapshot.js +22 -0
  114. package/src/motion/take-segments.jsx +140 -0
  115. package/src/{ardy → motion}/timeline-coordinates.js +0 -21
  116. package/src/{ardy → motion}/timeline.css +1 -2
  117. package/src/{ardy → motion}/timeline.jsx +42 -413
  118. package/src/motion/waypoints.js +76 -0
  119. package/src/motion3/beats.js +83 -0
  120. package/src/motion3/body.js +158 -0
  121. package/src/motion3/bones.js +47 -0
  122. package/src/motion3/carried.js +47 -0
  123. package/src/motion3/compile-job.js +79 -0
  124. package/src/motion3/compile-worker.js +10 -0
  125. package/src/motion3/compiler/anchors.js +113 -0
  126. package/src/motion3/compiler/arm-orient.js +128 -0
  127. package/src/motion3/compiler/channels.js +125 -0
  128. package/src/motion3/compiler/compile.js +205 -0
  129. package/src/motion3/compiler/gait-rhythm.js +97 -0
  130. package/src/motion3/compiler/grip.js +171 -0
  131. package/src/motion3/compiler/head-steady.js +48 -0
  132. package/src/motion3/compiler/hold.js +134 -0
  133. package/src/motion3/compiler/idle.js +113 -0
  134. package/src/motion3/compiler/limbs.js +197 -0
  135. package/src/motion3/compiler/math.js +72 -0
  136. package/src/motion3/compiler/pose.js +177 -0
  137. package/src/motion3/compiler/quat.js +49 -0
  138. package/src/motion3/compiler/skeleton.js +74 -0
  139. package/src/motion3/compiler/validate-common.js +32 -0
  140. package/src/motion3/compiler/validate-goals.js +118 -0
  141. package/src/motion3/compiler/validate-objects.js +144 -0
  142. package/src/motion3/compiler/validate-parts.js +118 -0
  143. package/src/motion3/compiler/validate.js +122 -0
  144. package/src/motion3/compiler/vocab.js +74 -0
  145. package/src/motion3/compiler/walk-pelvis.js +275 -0
  146. package/src/motion3/compiler/walk.js +207 -0
  147. package/src/motion3/compiler/wrist-clamp.js +32 -0
  148. package/src/motion3/delta.js +47 -0
  149. package/src/motion3/describe.js +177 -0
  150. package/src/motion3/docs.js +27 -0
  151. package/src/motion3/edit-carry.js +21 -0
  152. package/src/motion3/fix/ease.js +16 -0
  153. package/src/motion3/fix/ground.js +37 -0
  154. package/src/motion3/fix/index.js +52 -0
  155. package/src/motion3/fix/push.js +71 -0
  156. package/src/motion3/fix/reach.js +46 -0
  157. package/src/motion3/fix/retime.js +79 -0
  158. package/src/motion3/fix/self.js +211 -0
  159. package/src/motion3/fix/slide.js +70 -0
  160. package/src/motion3/fix/turn.js +51 -0
  161. package/src/motion3/follow.js +39 -0
  162. package/src/motion3/free-motion.js +204 -0
  163. package/src/motion3/grip-choice.js +130 -0
  164. package/src/motion3/hold-plan.js +157 -0
  165. package/src/motion3/json-patch.js +77 -0
  166. package/src/motion3/key-aim.js +105 -0
  167. package/src/motion3/key-edit.js +82 -0
  168. package/src/motion3/lenient.js +127 -0
  169. package/src/motion3/object-keys.js +236 -0
  170. package/src/motion3/object-pose.js +182 -0
  171. package/src/motion3/object-tracks.js +12 -0
  172. package/src/motion3/people.js +82 -0
  173. package/src/motion3/pipeline.js +102 -0
  174. package/src/motion3/playback.js +51 -0
  175. package/src/motion3/probes.js +91 -0
  176. package/src/motion3/qa/body-checks.js +34 -0
  177. package/src/motion3/qa/check-names.js +14 -0
  178. package/src/motion3/qa/checks.js +125 -0
  179. package/src/motion3/qa/contact-checks.js +51 -0
  180. package/src/motion3/qa/explain.js +80 -0
  181. package/src/motion3/qa/fmt.js +5 -0
  182. package/src/motion3/qa/foot-checks.js +72 -0
  183. package/src/motion3/qa/geometry.js +77 -0
  184. package/src/motion3/qa/goals.js +191 -0
  185. package/src/motion3/qa/ground.js +60 -0
  186. package/src/motion3/qa/hints-contact.js +195 -0
  187. package/src/motion3/qa/hints-goal.js +160 -0
  188. package/src/motion3/qa/hints-knee.js +24 -0
  189. package/src/motion3/qa/hints-motion.js +209 -0
  190. package/src/motion3/qa/hints-object.js +91 -0
  191. package/src/motion3/qa/index.js +44 -0
  192. package/src/motion3/qa/key-checks.js +82 -0
  193. package/src/motion3/qa/near.js +96 -0
  194. package/src/motion3/qa/object-checks.js +135 -0
  195. package/src/motion3/qa/patch.js +161 -0
  196. package/src/motion3/qa/people-checks.js +37 -0
  197. package/src/motion3/qa/severity.js +38 -0
  198. package/src/motion3/qa/spec-checks.js +65 -0
  199. package/src/motion3/qa/style.js +228 -0
  200. package/src/motion3/qa/wrist-checks.js +69 -0
  201. package/src/motion3/qa/wrist-obs.js +60 -0
  202. package/src/motion3/refs.js +129 -0
  203. package/src/motion3/repair-tune.js +121 -0
  204. package/src/motion3/repair.js +83 -0
  205. package/src/motion3/report.js +67 -0
  206. package/src/motion3/rigs/index.js +14 -0
  207. package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
  208. package/src/motion3/rigs/x-bot-tpose.json +1 -0
  209. package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
  210. package/src/motion3/rigs/y-bot-tpose.json +1 -0
  211. package/src/motion3/scene.js +60 -0
  212. package/src/motion3/schema/brief.js +89 -0
  213. package/src/motion3/schema/fields.js +44 -0
  214. package/src/motion3/schema/spec-examples.js +46 -0
  215. package/src/motion3/schema/topics.js +113 -0
  216. package/src/motion3/schema/types.js +149 -0
  217. package/src/motion3/search.js +117 -0
  218. package/src/motion3/second-hand.js +112 -0
  219. package/src/motion3/settle.js +136 -0
  220. package/src/motion3/skills/basic.js +83 -0
  221. package/src/motion3/skills/book.js +76 -0
  222. package/src/motion3/skills/car.js +145 -0
  223. package/src/motion3/skills/flip.js +200 -0
  224. package/src/motion3/skills/frames-auto.js +29 -0
  225. package/src/motion3/skills/impact.js +109 -0
  226. package/src/motion3/skills/index.js +85 -0
  227. package/src/motion3/skills/info.js +80 -0
  228. package/src/motion3/skills/smoke-kit.js +109 -0
  229. package/src/motion3/skills/smoke.js +160 -0
  230. package/src/motion3/spec-store.js +59 -0
  231. package/src/motion3/take-edit.js +155 -0
  232. package/src/motion3/take.js +63 -0
  233. package/src/motion3/timeline.js +127 -0
  234. package/src/motion3/views.js +121 -0
  235. package/src/motion3/walk-plan.js +119 -0
  236. package/src/object-catalog.jsx +7 -1
  237. package/src/object-colors.js +98 -0
  238. package/src/object-gizmo-parts.js +115 -0
  239. package/src/object-gizmo.jsx +37 -122
  240. package/src/object-glow.js +139 -0
  241. package/src/object-hidden.js +33 -0
  242. package/src/object-look.js +196 -0
  243. package/src/object-size.js +10 -0
  244. package/src/object-travel.js +71 -6
  245. package/src/panels/CameraPanel.jsx +7 -7
  246. package/src/panels/HdrEnvironmentControls.jsx +59 -0
  247. package/src/panels/LightPanel.jsx +25 -4
  248. package/src/panels/ObjectLookPanel.jsx +88 -0
  249. package/src/panels/PosePanel.jsx +2 -17
  250. package/src/panels/RigControlPanel.jsx +5 -53
  251. package/src/panels/SubjectBox.jsx +4 -1
  252. package/src/panels/details.css +14 -0
  253. package/src/posestudio.jsx +4 -27
  254. package/src/project-browser.jsx +3 -4
  255. package/src/project-resources.js +18 -31
  256. package/src/project.js +13 -104
  257. package/src/props.jsx +25 -280
  258. package/src/qa-label.js +25 -0
  259. package/src/rail-dot-drag.js +23 -0
  260. package/src/render-passes.js +10 -0
  261. package/src/resource-status.jsx +1 -0
  262. package/src/result-modal.jsx +4 -19
  263. package/src/room.jsx +20 -12
  264. package/src/scene-assets.js +8 -6
  265. package/src/scene-light-place.js +72 -0
  266. package/src/scene-lights.jsx +148 -0
  267. package/src/scene-objects.js +31 -139
  268. package/src/scenes.js +15 -105
  269. package/src/semantic-edit.js +2 -5
  270. package/src/set-pieces.jsx +183 -0
  271. package/src/settings-menu.jsx +3 -11
  272. package/src/shell/BottomDock.jsx +9 -51
  273. package/src/shell/DetailsSlot.jsx +16 -200
  274. package/src/shell/GhostsMenuGroup.jsx +74 -0
  275. package/src/shell/LibrarySlot.jsx +1 -3
  276. package/src/shell/MenuBar.jsx +3 -3
  277. package/src/shell/PreferencesDialog.jsx +15 -264
  278. package/src/shell/PreferencesSlot.jsx +2 -8
  279. package/src/shell/TopBar.jsx +5 -84
  280. package/src/shell/ViewportToolbar.jsx +10 -70
  281. package/src/shell/agent-glass.css +19 -6
  282. package/src/shell/details-selection.js +42 -0
  283. package/src/shell/ghosts-menu.css +22 -0
  284. package/src/shell/glass-regions.css +29 -3
  285. package/src/shell/preferences.css +6 -1
  286. package/src/shot-authoring.js +4 -7
  287. package/src/soft-shadows.js +37 -0
  288. package/src/stage-attach-frames.js +12 -12
  289. package/src/stage-canvas-rigs.jsx +3 -3
  290. package/src/stage-capture.jsx +42 -8
  291. package/src/stage-characters.jsx +22 -216
  292. package/src/stage-editor-gizmos.jsx +6 -6
  293. package/src/stage-environment.js +93 -0
  294. package/src/stage-hdr-builtins.js +107 -0
  295. package/src/stage-hdr-image.js +116 -0
  296. package/src/stage-hdr-library.js +70 -0
  297. package/src/stage-hdr-map.js +94 -0
  298. package/src/stage-hdr.js +130 -0
  299. package/src/stage-lighting.js +149 -0
  300. package/src/stage-occlusion.js +210 -0
  301. package/src/stage-sky.jsx +159 -0
  302. package/src/stage-startup-defaults.js +5 -9
  303. package/src/studio-actions.js +16 -14
  304. package/src/studio-agent-commands.js +19 -16
  305. package/src/studio-agent-motion.js +9 -9
  306. package/src/studio-agent-protocol.js +47 -77
  307. package/src/studio-app-binding.js +27 -47
  308. package/src/studio-asset-list.js +17 -0
  309. package/src/studio-contact-sheet.js +37 -5
  310. package/src/studio-elements.js +27 -7
  311. package/src/studio-entity-bounds.js +18 -0
  312. package/src/studio-error-codes.js +15 -0
  313. package/src/studio-export-framing.js +152 -0
  314. package/src/studio-lighting-check.js +103 -0
  315. package/src/studio-motion-visual.js +150 -0
  316. package/src/studio-schema-errors.js +80 -0
  317. package/src/studio-support-gap.js +74 -0
  318. package/src/styles.css +1 -19
  319. package/src/timeline-defaults.js +5 -0
  320. package/src/timeline-extent.js +8 -20
  321. package/src/tutorial-walk.js +17 -0
  322. package/src/ui-scrub.js +1 -1
  323. package/src/use-shot-camera-tracks.js +12 -0
  324. package/src/view-ghosts.js +97 -0
  325. package/src/view-ghosts.jsx +49 -0
  326. package/src/workflow/AgentPanel.jsx +47 -166
  327. package/src/workflow/AgentProgressCard.jsx +109 -0
  328. package/src/workflow/AgentReplyText.jsx +37 -0
  329. package/src/workflow/AgentTurnSteps.jsx +84 -0
  330. package/src/workflow/LoginPanel.jsx +140 -0
  331. package/src/workflow/WorkflowBuilder.jsx +7 -23
  332. package/src/workflow/agent-client.js +54 -51
  333. package/src/workflow/agent-panel.css +71 -1
  334. package/src/workflow/agent-progress-card.css +167 -0
  335. package/src/workflow/agent-progress-view.js +47 -0
  336. package/src/workflow/agent-turn-steps.css +113 -0
  337. package/src/workflow/agent-turn.js +191 -0
  338. package/src/workflow/login-client.js +34 -0
  339. package/src/workflow/motion-input.js +18 -31
  340. package/src/workflow/node-schema.js +1 -1
  341. package/src/workflow/reply-markdown.js +69 -0
  342. package/src/workflow/scene-asset-sync.js +8 -8
  343. package/tools/agent-session-stats.mjs +61 -0
  344. package/tools/dev-full.mjs +5 -56
  345. package/tools/eslint-baseline.json +12 -13
  346. package/tools/knip-baseline.json +0 -179
  347. package/tools/loc-baseline.json +31 -81
  348. package/tools/motion3/extract-body.mjs +103 -0
  349. package/tools/motion3/extract-rig.mjs +85 -0
  350. package/tools/process-supervisor.mjs +0 -88
  351. package/tools/run-tests.mjs +9 -125
  352. package/bin/agent/motion-runtime.mjs +0 -76
  353. package/dist/ardy/cskel27-rest.json +0 -557
  354. package/dist/assets/analytics-C9pMpW7s.js +0 -1
  355. package/dist/assets/app-B_2XB9rw.css +0 -1
  356. package/dist/assets/app-DAuvKPP8.js +0 -4920
  357. package/dist/assets/config-Bx7pYsD9.js +0 -1
  358. package/dist/assets/config-DeoFTYzb.css +0 -1
  359. package/dist/assets/demo-CvKuBgy5.js +0 -1
  360. package/dist/assets/scene-asset-sync-DKkpjKBV.js +0 -19
  361. package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
  362. package/dist/assets/ticket-BPk2Ni95.js +0 -1
  363. package/dist/assets/workflow-jJRBR94Z.js +0 -179
  364. package/dist/demo/walk-then-stop.npz +0 -0
  365. package/mcp/ardy-prompts.mjs +0 -218
  366. package/src/ardy/auto-fix-panel.css +0 -108
  367. package/src/ardy/auto-physics.js +0 -1194
  368. package/src/ardy/client.js +0 -153
  369. package/src/ardy/convert.js +0 -313
  370. package/src/ardy/cskel27-neutral.js +0 -39
  371. package/src/ardy/cskel27.js +0 -77
  372. package/src/ardy/export.js +0 -165
  373. package/src/ardy/fix-collisions.js +0 -2257
  374. package/src/ardy/foot-lock.js +0 -230
  375. package/src/ardy/motion-calibration.js +0 -118
  376. package/src/ardy/motion-edit.js +0 -213
  377. package/src/ardy/motion-url.js +0 -55
  378. package/src/ardy/mp4-duration.js +0 -102
  379. package/src/ardy/npz.js +0 -595
  380. package/src/ardy/physics-panel.css +0 -21
  381. package/src/ardy/physics-panel.jsx +0 -89
  382. package/src/ardy/physics-refine.js +0 -111
  383. package/src/ardy/physics-review.js +0 -567
  384. package/src/ardy/physics-temporal.js +0 -54
  385. package/src/ardy/platform-fit-panel.css +0 -64
  386. package/src/ardy/platform-fit-panel.jsx +0 -41
  387. package/src/ardy/platform-fit.js +0 -326
  388. package/src/ardy/playback.js +0 -711
  389. package/src/ardy/pose-pin.js +0 -97
  390. package/src/ardy/prompt-clips.js +0 -30
  391. package/src/ardy/retime.js +0 -211
  392. package/src/ardy/root-drop.js +0 -369
  393. package/src/ardy/timeline-resize.js +0 -13
  394. package/src/ardy/to-cskel27.js +0 -225
  395. package/src/ardy/trim.js +0 -33
  396. package/src/ardy/waypoints.js +0 -369
  397. package/src/ardy-bridge-contract.js +0 -281
  398. package/src/domains/motion/motion-video-capture.js +0 -664
  399. package/src/i2v-motion-client.js +0 -77
  400. package/src/i2v-motion-studio.jsx +0 -180
  401. package/src/line-edit.js +0 -1348
  402. package/src/motion/generation.js +0 -105
  403. package/src/motion-readiness-ui.jsx +0 -67
  404. package/src/motion-readiness.js +0 -40
  405. package/src/motion-resources.js +0 -177
  406. package/src/motion-store.js +0 -65
  407. package/src/motion-trail.js +0 -601
  408. package/src/multimodel-ingest.js +0 -394
  409. package/src/panels/PromptBlocksPanel.jsx +0 -444
  410. package/src/panels/VideoCapturePanel.jsx +0 -181
  411. package/src/pose-extract/browser.js +0 -42
  412. package/src/pose-extract/detector.js +0 -100
  413. package/src/pose-extract/fit.js +0 -227
  414. package/src/pose-extract/image-frame.js +0 -51
  415. package/src/pose-extract/index.js +0 -58
  416. package/src/pose-extract/keyframes.js +0 -74
  417. package/src/pose-extract/landmarks.js +0 -162
  418. package/src/pose-extract/mirror.js +0 -153
  419. package/src/pose-extract/take.js +0 -131
  420. package/src/pose-extract/video-frames.js +0 -91
  421. package/src/take-recipe.js +0 -165
  422. package/src/trail-key-conflicts.js +0 -39
  423. package/src/trail-pick.js +0 -59
  424. package/src/use-i2v-capture-modal.js +0 -15
  425. package/tools/ardy/BRIDGE.md +0 -37
  426. package/tools/ardy/GVHMR-NPZ.md +0 -68
  427. package/tools/ardy/README.md +0 -124
  428. package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
  429. package/tools/ardy/artifacts.mjs +0 -34
  430. package/tools/ardy/bridge.mjs +0 -1732
  431. package/tools/ardy/bvh-cskel27.mjs +0 -1265
  432. package/tools/ardy/cclay_constrained_generate.py +0 -561
  433. package/tools/ardy/cclay_gvhmr_worker.py +0 -264
  434. package/tools/ardy/cclay_motion_edit.py +0 -510
  435. package/tools/ardy/cclay_sequence_generate.py +0 -705
  436. package/tools/ardy/cclay_worker.py +0 -304
  437. package/tools/ardy/dump-npz.py +0 -205
  438. package/tools/ardy/extract-rest.mjs +0 -299
  439. package/tools/ardy/extract.mjs +0 -507
  440. package/tools/ardy/footage.mjs +0 -467
  441. package/tools/ardy/gvhmr-floor.mjs +0 -102
  442. package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
  443. package/tools/ardy/gvhmr_fastpath.py +0 -168
  444. package/tools/ardy/gvhmr_trajectory.py +0 -240
  445. package/tools/ardy/merge-text-encoder.py +0 -160
  446. package/tools/ardy/mocap-metrics.mjs +0 -200
  447. package/tools/ardy/mocap-quality-gate.mjs +0 -110
  448. package/tools/ardy/motion-stabilize.mjs +0 -348
  449. package/tools/ardy/npz.mjs +0 -414
  450. package/tools/ardy/pose-to-npz.mjs +0 -106
  451. package/tools/ardy/prompt-limits.mjs +0 -5
  452. package/tools/ardy/run-edit-on-box.sh +0 -73
  453. package/tools/ardy/run-local.mjs +0 -233
  454. package/tools/ardy/run-on-box.sh +0 -593
  455. package/tools/ardy/run-sequence-on-box.sh +0 -177
  456. package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
  457. package/tools/ardy/runners/index.mjs +0 -18
  458. package/tools/ardy/runners/local.mjs +0 -455
  459. package/tools/ardy/runners/proc.mjs +0 -125
  460. package/tools/ardy/runners/remote.mjs +0 -252
  461. package/tools/ardy/setup-local.mjs +0 -189
  462. package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
  463. package/tools/ardy/setup-text-encoder.py +0 -306
  464. package/tools/ardy/smpl-cskel27.mjs +0 -178
  465. package/tools/ardy/visual-qa.mjs +0 -196
  466. package/tools/ardy/vq-car.mjs +0 -52
  467. package/tools/bench/EXP3.md +0 -61
  468. package/tools/bench/cclay_bench_extract_incam.py +0 -125
  469. package/tools/bench/cclay_bench_extract_obs.py +0 -204
  470. package/tools/bench/cclay_bench_runner.py +0 -42
  471. package/tools/bench/cube-contact.mjs +0 -162
  472. package/tools/bench/exp3.mjs +0 -152
  473. package/tools/bench/extract-bench-lib.mjs +0 -216
  474. package/tools/bench/extract-bench.mjs +0 -302
  475. package/tools/bench/fal-generate.mjs +0 -88
  476. package/tools/bench/fit/README.md +0 -189
  477. package/tools/bench/fit/camera.mjs +0 -59
  478. package/tools/bench/fit/contact.mjs +0 -419
  479. package/tools/bench/fit/footlock.mjs +0 -234
  480. package/tools/bench/fit/motion.mjs +0 -85
  481. package/tools/bench/fit/pin.mjs +0 -27
  482. package/tools/bench/fit/remote.mjs +0 -105
  483. package/tools/bench/fit-bench.mjs +0 -126
  484. package/tools/bench/fit-sanity.mjs +0 -45
  485. package/tools/bench/metrics.mjs +0 -313
  486. package/tools/bench/obs/depth.mjs +0 -258
  487. package/tools/bench/obs/extrinsics.mjs +0 -175
  488. package/tools/bench/obs/fit_mannequin_betas.py +0 -340
  489. package/tools/bench/obs/ground.mjs +0 -294
  490. package/tools/bench/obs/heading.mjs +0 -151
  491. package/tools/bench/obs/ladder.mjs +0 -555
  492. package/tools/bench/obs/mannequin-betas.json +0 -124
  493. package/tools/bench/obs/remote.mjs +0 -83
  494. package/tools/bench/obs/rest_joints.py +0 -52
  495. package/tools/bench/obs/ybot-targets.mjs +0 -49
  496. package/tools/bench/obs-bench.mjs +0 -520
  497. package/tools/bench/score.mjs +0 -343
  498. package/tools/bench/summarize.mjs +0 -86
  499. package/tools/demo-worker/README.md +0 -137
  500. package/tools/demo-worker/api-client.mjs +0 -233
  501. package/tools/demo-worker/generate.mjs +0 -301
  502. package/tools/demo-worker/index.mjs +0 -466
  503. package/tools/demo-worker/sign-core.mjs +0 -112
  504. package/tools/demo-worker/sign.mjs +0 -161
  505. package/tools/gt-render/browser.mjs +0 -182
  506. package/tools/gt-render/camera-math.mjs +0 -276
  507. package/tools/gt-render/page.mjs +0 -267
  508. package/tools/gt-render/render.mjs +0 -514
  509. package/tools/gt-render/scene-box.mjs +0 -31
  510. package/tools/gt-render/take-transform.mjs +0 -87
  511. package/tools/kimodo/compare-seam.mjs +0 -108
  512. package/tools/kimodo/constraints.mjs +0 -244
  513. package/tools/kimodo/edit.mjs +0 -259
  514. package/tools/kimodo/effector-constraints.mjs +0 -200
  515. package/tools/kimodo/generate.mjs +0 -646
  516. package/tools/kimodo/local-output.mjs +0 -265
  517. package/tools/kimodo/measure-pose.mjs +0 -65
  518. package/tools/kimodo/measure-preserve.mjs +0 -899
  519. package/tools/kimodo/measure-waypoints.mjs +0 -55
  520. package/tools/kimodo/mlx-generate.py +0 -111
  521. package/tools/kimodo/pose-constraints.mjs +0 -248
  522. package/tools/kimodo/preserve-mask.mjs +0 -543
  523. package/tools/kimodo/read-npz.mjs +0 -189
  524. package/tools/kimodo/run-edit-on-box.mjs +0 -155
  525. package/tools/kimodo/run-sequence-on-box.mjs +0 -178
  526. package/tools/kimodo/runner.mjs +0 -284
  527. package/tools/kimodo/seam-batch.mjs +0 -77
  528. package/tools/kimodo/setup-local.mjs +0 -30
  529. package/tools/kimodo/setup-on-box.sh +0 -339
  530. package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
  531. package/tools/morphgs/assets/gen_truth.py +0 -39
  532. package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
  533. package/tools/morphgs/assets/playback-check.mjs +0 -30
  534. package/tools/morphgs/demo-gate.sh +0 -26
  535. package/tools/morphgs/fbx2morphgs.mjs +0 -68
  536. package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
  537. package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
  538. package/tools/morphgs/setup-on-cluster.sh +0 -126
  539. package/tools/projflow/driver.py +0 -1069
  540. package/tools/projflow/generate.mjs +0 -805
  541. package/tools/projflow/hml22-to-cskel27.mjs +0 -735
  542. package/tools/projflow/line-edit-job.mjs +0 -547
  543. package/tools/projflow/replay.mjs +0 -452
  544. package/tools/projflow/runner.mjs +0 -269
  545. package/tools/projflow/service.mjs +0 -742
  546. package/tools/track/DESIGN.md +0 -513
  547. package/tools/track/backfill-provenance.mjs +0 -116
  548. package/tools/track/budget.mjs +0 -8
  549. package/tools/track/check-rig.mjs +0 -209
  550. package/tools/track/diagnostics.schema.json +0 -60
  551. package/tools/track/export-rig.mjs +0 -256
  552. package/tools/track/fallback.mjs +0 -7
  553. package/tools/track/fk-parity-fixture.mjs +0 -161
  554. package/tools/track/gate.mjs +0 -349
  555. package/tools/track/masks.mjs +0 -318
  556. package/tools/track/metrics.mjs +0 -201
  557. package/tools/track/publish-obs.mjs +0 -108
  558. package/tools/track/py/check_env.py +0 -61
  559. package/tools/track/py/eval_lr.py +0 -229
  560. package/tools/track/py/lr_viterbi.py +0 -294
  561. package/tools/track/py/masks.py +0 -405
  562. package/tools/track/py/objective.py +0 -382
  563. package/tools/track/py/rig.py +0 -508
  564. package/tools/track/py/scene.py +0 -326
  565. package/tools/track/py/test_joint_indices.py +0 -123
  566. package/tools/track/py/test_lr_viterbi.py +0 -195
  567. package/tools/track/py/test_masks.py +0 -229
  568. package/tools/track/py/test_rig.py +0 -288
  569. package/tools/track/py/test_scene.py +0 -354
  570. package/tools/track/py/test_track.py +0 -328
  571. package/tools/track/py/track.py +0 -411
  572. package/tools/track/remote.mjs +0 -140
  573. package/tools/track/rig-dump.mjs +0 -227
  574. package/tools/track/run-box-tests.mjs +0 -14
  575. package/tools/track/run-box.mjs +0 -168
  576. package/tools/track/setup-box.sh +0 -59
  577. package/tools/track/study-2d.mjs +0 -728
  578. /package/src/{ardy → motion}/collision-blockers.js +0 -0
  579. /package/src/{ardy → motion}/ground.js +0 -0
  580. /package/src/{ardy → motion}/ik-drag.js +0 -0
  581. /package/src/{ardy → motion}/ik-key-json.js +0 -0
  582. /package/src/{ardy → motion}/ik.js +0 -0
  583. /package/src/{ardy → motion}/physics-surface.js +0 -0
  584. /package/src/{ardy → motion}/playback-clock.js +0 -0
  585. /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
- }