cozyclay 2.1.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +12 -30
  3. package/bin/agent/agent-routes.mjs +40 -113
  4. package/bin/agent/agent-runner.mjs +9 -10
  5. package/bin/agent/cliproxy-provider.mjs +135 -0
  6. package/bin/agent/credential-store.mjs +30 -7
  7. package/bin/agent/pi-tools.mjs +4 -1
  8. package/bin/agent/provider-keys.mjs +32 -0
  9. package/bin/agent/provider-login.mjs +110 -0
  10. package/bin/agent/provider-routes.mjs +99 -0
  11. package/bin/agent/providers.mjs +19 -97
  12. package/bin/agent/script-tool.mjs +17 -4
  13. package/bin/agent/studio-motion-reference.mjs +23 -0
  14. package/bin/agent/studio-prompt.mjs +1 -1
  15. package/bin/agent/studio-rebase-text.mjs +32 -0
  16. package/bin/agent/studio-rebase.mjs +26 -39
  17. package/bin/agent/studio-tools.mjs +9 -28
  18. package/bin/agent/tool-arguments.mjs +49 -0
  19. package/bin/agent/turn-frames.mjs +66 -0
  20. package/bin/codex-auth.mjs +9 -2
  21. package/bin/cozyclay.mjs +10 -116
  22. package/bin/live/cli.mjs +3 -3
  23. package/bin/mcp-runtime.mjs +2 -12
  24. package/bin/package-signature.mjs +0 -4
  25. package/dist/app/index.html +7 -6
  26. package/dist/assets/EXRLoader-CvVIvGVE.js +1 -0
  27. package/dist/assets/analytics-C9sUnndd.js +1 -0
  28. package/dist/assets/app-CCh--1Hc.js +5087 -0
  29. package/dist/assets/app-f-fkV5uP.css +1 -0
  30. package/dist/assets/compile-worker-CkxiD6lH.js +5 -0
  31. package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
  32. package/dist/assets/{first-shot-handoff-msLI71g1.js → first-shot-handoff-CC4xe4HM.js} +1 -1
  33. package/dist/assets/{landing-ChUvB_zL.js → landing-DjHD8u7k.js} +1 -1
  34. package/dist/assets/scene-asset-sync-Hx_FzdOH.js +20 -0
  35. package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
  36. package/dist/assets/workflow-C4yKH1p4.js +179 -0
  37. package/dist/cozyclay-package.json +1 -1
  38. package/dist/index.html +3 -3
  39. package/dist/sw.js +3 -6
  40. package/dist/workflow/index.html +5 -4
  41. package/mcp/LIVE-PROTOCOL.md +7 -47
  42. package/mcp/README.md +16 -26
  43. package/mcp/live-hub.mjs +6 -10
  44. package/mcp/package.json +1 -3
  45. package/mcp/tool-handlers.mjs +4 -168
  46. package/package.json +3 -22
  47. package/src/App.jsx +150 -2624
  48. package/src/agent-progress.js +79 -0
  49. package/src/agent-turn-mark.js +30 -0
  50. package/src/analytics.js +1 -19
  51. package/src/app-context.js +5 -0
  52. package/src/app-stage.jsx +2 -34
  53. package/src/asset-pane.jsx +6 -5
  54. package/src/camera-block.js +21 -0
  55. package/src/camera-direction.js +120 -0
  56. package/src/character-kind.js +3 -9
  57. package/src/command-bus.js +8 -6
  58. package/src/commands/cast.js +5 -34
  59. package/src/commands/elements/character.js +1 -1
  60. package/src/commands/elements/motion.js +1 -6
  61. package/src/commands/elements/object.js +6 -2
  62. package/src/commands/elements/shot.js +4 -1
  63. package/src/commands/elements.js +38 -14
  64. package/src/commands/index.js +3 -1
  65. package/src/commands/kits.js +37 -0
  66. package/src/commands/motion-timing.js +57 -0
  67. package/src/commands/motion.js +9 -152
  68. package/src/commands/motion3-compile.js +65 -0
  69. package/src/commands/motion3.js +207 -0
  70. package/src/commands/objects.js +6 -4
  71. package/src/commands/shot.js +49 -11
  72. package/src/commands/stage.js +14 -1
  73. package/src/commands/view.js +4 -1
  74. package/src/document-mirrors.js +42 -0
  75. package/src/document-store.js +4 -0
  76. package/src/domains/cast.js +19 -194
  77. package/src/domains/motion/motion-range-pin-rules.js +1 -1
  78. package/src/domains/motion/take-source.js +51 -0
  79. package/src/domains/motion.js +60 -1838
  80. package/src/domains/scenes.js +12 -55
  81. package/src/domains/shots.js +2 -2
  82. package/src/domains/stage.js +4 -2
  83. package/src/draft-ghost.js +46 -0
  84. package/src/draft-ghost.jsx +129 -0
  85. package/src/dualview.jsx +4 -3
  86. package/src/effects/EffectsLayer.jsx +112 -0
  87. package/src/effects/effect-meshes.js +232 -0
  88. package/src/effects/effect-record.js +103 -0
  89. package/src/effects/emitter.js +59 -0
  90. package/src/effects/simulate.js +261 -0
  91. package/src/effects/state.js +59 -0
  92. package/src/execution-telemetry.js +2 -3
  93. package/src/first-success-guide.jsx +5 -5
  94. package/src/ghost-set.js +257 -0
  95. package/src/held-object-edit.jsx +113 -0
  96. package/src/held-object-pose.js +175 -0
  97. package/src/hierarchy-model.js +1 -1
  98. package/src/hierarchy-panel.jsx +1 -1
  99. package/src/imported-mesh.jsx +103 -0
  100. package/src/kits/held.js +84 -0
  101. package/src/kits/index.js +70 -0
  102. package/src/kits/smoking.js +57 -0
  103. package/src/light-blockers.js +93 -0
  104. package/src/motion/beat-board-model.js +84 -0
  105. package/src/motion/beat-board.css +124 -0
  106. package/src/motion/beat-board.jsx +59 -0
  107. package/src/motion/center-of-mass.js +66 -0
  108. package/src/motion/fix-collisions.js +850 -0
  109. package/src/motion/physics-review.js +118 -0
  110. package/src/{ardy → motion}/physics-support.js +1 -76
  111. package/src/motion/rig-snapshot.js +22 -0
  112. package/src/motion/take-segments.jsx +140 -0
  113. package/src/{ardy → motion}/timeline-coordinates.js +0 -21
  114. package/src/{ardy → motion}/timeline.css +1 -2
  115. package/src/{ardy → motion}/timeline.jsx +42 -413
  116. package/src/motion/waypoints.js +76 -0
  117. package/src/motion3/beats.js +83 -0
  118. package/src/motion3/body.js +158 -0
  119. package/src/motion3/bones.js +47 -0
  120. package/src/motion3/carried.js +47 -0
  121. package/src/motion3/compile-job.js +75 -0
  122. package/src/motion3/compile-worker.js +10 -0
  123. package/src/motion3/compiler/anchors.js +105 -0
  124. package/src/motion3/compiler/arm-orient.js +128 -0
  125. package/src/motion3/compiler/channels.js +125 -0
  126. package/src/motion3/compiler/compile.js +205 -0
  127. package/src/motion3/compiler/gait-rhythm.js +97 -0
  128. package/src/motion3/compiler/grip.js +171 -0
  129. package/src/motion3/compiler/head-steady.js +48 -0
  130. package/src/motion3/compiler/hold.js +134 -0
  131. package/src/motion3/compiler/idle.js +113 -0
  132. package/src/motion3/compiler/limbs.js +170 -0
  133. package/src/motion3/compiler/math.js +72 -0
  134. package/src/motion3/compiler/pose.js +162 -0
  135. package/src/motion3/compiler/quat.js +49 -0
  136. package/src/motion3/compiler/skeleton.js +74 -0
  137. package/src/motion3/compiler/validate-common.js +32 -0
  138. package/src/motion3/compiler/validate-goals.js +118 -0
  139. package/src/motion3/compiler/validate-objects.js +143 -0
  140. package/src/motion3/compiler/validate-parts.js +116 -0
  141. package/src/motion3/compiler/validate.js +122 -0
  142. package/src/motion3/compiler/vocab.js +73 -0
  143. package/src/motion3/compiler/walk-pelvis.js +275 -0
  144. package/src/motion3/compiler/walk.js +207 -0
  145. package/src/motion3/compiler/wrist-clamp.js +32 -0
  146. package/src/motion3/delta.js +47 -0
  147. package/src/motion3/describe.js +174 -0
  148. package/src/motion3/docs.js +27 -0
  149. package/src/motion3/edit-carry.js +21 -0
  150. package/src/motion3/fix/ease.js +16 -0
  151. package/src/motion3/fix/ground.js +37 -0
  152. package/src/motion3/fix/index.js +52 -0
  153. package/src/motion3/fix/push.js +71 -0
  154. package/src/motion3/fix/reach.js +46 -0
  155. package/src/motion3/fix/retime.js +79 -0
  156. package/src/motion3/fix/self.js +211 -0
  157. package/src/motion3/fix/slide.js +70 -0
  158. package/src/motion3/fix/turn.js +51 -0
  159. package/src/motion3/follow.js +39 -0
  160. package/src/motion3/free-motion.js +173 -0
  161. package/src/motion3/grip-choice.js +130 -0
  162. package/src/motion3/hold-plan.js +157 -0
  163. package/src/motion3/json-patch.js +77 -0
  164. package/src/motion3/key-aim.js +105 -0
  165. package/src/motion3/key-edit.js +82 -0
  166. package/src/motion3/lenient.js +127 -0
  167. package/src/motion3/object-keys.js +236 -0
  168. package/src/motion3/object-pose.js +182 -0
  169. package/src/motion3/object-tracks.js +12 -0
  170. package/src/motion3/pipeline.js +102 -0
  171. package/src/motion3/playback.js +51 -0
  172. package/src/motion3/probes.js +91 -0
  173. package/src/motion3/qa/body-checks.js +34 -0
  174. package/src/motion3/qa/check-names.js +14 -0
  175. package/src/motion3/qa/checks.js +121 -0
  176. package/src/motion3/qa/contact-checks.js +51 -0
  177. package/src/motion3/qa/explain.js +80 -0
  178. package/src/motion3/qa/fmt.js +5 -0
  179. package/src/motion3/qa/foot-checks.js +72 -0
  180. package/src/motion3/qa/geometry.js +77 -0
  181. package/src/motion3/qa/goals.js +191 -0
  182. package/src/motion3/qa/ground.js +60 -0
  183. package/src/motion3/qa/hints-contact.js +179 -0
  184. package/src/motion3/qa/hints-goal.js +160 -0
  185. package/src/motion3/qa/hints-knee.js +24 -0
  186. package/src/motion3/qa/hints-motion.js +209 -0
  187. package/src/motion3/qa/hints-object.js +91 -0
  188. package/src/motion3/qa/index.js +42 -0
  189. package/src/motion3/qa/key-checks.js +82 -0
  190. package/src/motion3/qa/near.js +96 -0
  191. package/src/motion3/qa/object-checks.js +135 -0
  192. package/src/motion3/qa/patch.js +161 -0
  193. package/src/motion3/qa/severity.js +38 -0
  194. package/src/motion3/qa/spec-checks.js +65 -0
  195. package/src/motion3/qa/style.js +218 -0
  196. package/src/motion3/qa/wrist-checks.js +69 -0
  197. package/src/motion3/qa/wrist-obs.js +60 -0
  198. package/src/motion3/refs.js +120 -0
  199. package/src/motion3/repair-tune.js +121 -0
  200. package/src/motion3/repair.js +83 -0
  201. package/src/motion3/report.js +67 -0
  202. package/src/motion3/rigs/index.js +14 -0
  203. package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
  204. package/src/motion3/rigs/x-bot-tpose.json +1 -0
  205. package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
  206. package/src/motion3/rigs/y-bot-tpose.json +1 -0
  207. package/src/motion3/scene.js +60 -0
  208. package/src/motion3/schema/brief.js +89 -0
  209. package/src/motion3/schema/fields.js +44 -0
  210. package/src/motion3/schema/spec-examples.js +46 -0
  211. package/src/motion3/schema/topics.js +111 -0
  212. package/src/motion3/schema/types.js +147 -0
  213. package/src/motion3/search.js +117 -0
  214. package/src/motion3/second-hand.js +112 -0
  215. package/src/motion3/skills/basic.js +82 -0
  216. package/src/motion3/skills/book.js +76 -0
  217. package/src/motion3/skills/car.js +145 -0
  218. package/src/motion3/skills/frames-auto.js +29 -0
  219. package/src/motion3/skills/index.js +83 -0
  220. package/src/motion3/skills/info.js +65 -0
  221. package/src/motion3/skills/smoke-kit.js +109 -0
  222. package/src/motion3/skills/smoke.js +160 -0
  223. package/src/motion3/spec-store.js +59 -0
  224. package/src/motion3/take-edit.js +155 -0
  225. package/src/motion3/take.js +63 -0
  226. package/src/motion3/timeline.js +127 -0
  227. package/src/motion3/views.js +121 -0
  228. package/src/motion3/walk-plan.js +119 -0
  229. package/src/object-catalog.jsx +7 -1
  230. package/src/object-colors.js +98 -0
  231. package/src/object-gizmo-parts.js +115 -0
  232. package/src/object-gizmo.jsx +37 -122
  233. package/src/object-glow.js +139 -0
  234. package/src/object-hidden.js +33 -0
  235. package/src/object-look.js +196 -0
  236. package/src/object-size.js +10 -0
  237. package/src/object-travel.js +71 -6
  238. package/src/panels/CameraPanel.jsx +7 -7
  239. package/src/panels/HdrEnvironmentControls.jsx +59 -0
  240. package/src/panels/LightPanel.jsx +25 -4
  241. package/src/panels/ObjectLookPanel.jsx +88 -0
  242. package/src/panels/PosePanel.jsx +2 -17
  243. package/src/panels/RigControlPanel.jsx +5 -53
  244. package/src/panels/SubjectBox.jsx +4 -1
  245. package/src/panels/details.css +14 -0
  246. package/src/posestudio.jsx +4 -27
  247. package/src/project-browser.jsx +3 -4
  248. package/src/project-resources.js +18 -31
  249. package/src/project.js +13 -104
  250. package/src/props.jsx +25 -280
  251. package/src/rail-dot-drag.js +23 -0
  252. package/src/render-passes.js +10 -0
  253. package/src/resource-status.jsx +1 -0
  254. package/src/result-modal.jsx +4 -19
  255. package/src/room.jsx +20 -12
  256. package/src/scene-assets.js +8 -6
  257. package/src/scene-light-place.js +72 -0
  258. package/src/scene-lights.jsx +148 -0
  259. package/src/scene-objects.js +31 -139
  260. package/src/scenes.js +15 -105
  261. package/src/semantic-edit.js +2 -5
  262. package/src/set-pieces.jsx +183 -0
  263. package/src/settings-menu.jsx +3 -11
  264. package/src/shell/BottomDock.jsx +9 -51
  265. package/src/shell/DetailsSlot.jsx +16 -200
  266. package/src/shell/GhostsMenuGroup.jsx +74 -0
  267. package/src/shell/LibrarySlot.jsx +1 -3
  268. package/src/shell/MenuBar.jsx +3 -3
  269. package/src/shell/PreferencesDialog.jsx +15 -264
  270. package/src/shell/PreferencesSlot.jsx +2 -8
  271. package/src/shell/TopBar.jsx +5 -84
  272. package/src/shell/ViewportToolbar.jsx +10 -70
  273. package/src/shell/agent-glass.css +19 -6
  274. package/src/shell/details-selection.js +42 -0
  275. package/src/shell/ghosts-menu.css +22 -0
  276. package/src/shell/glass-regions.css +29 -3
  277. package/src/shell/preferences.css +6 -1
  278. package/src/shot-authoring.js +4 -7
  279. package/src/soft-shadows.js +37 -0
  280. package/src/stage-attach-frames.js +12 -12
  281. package/src/stage-canvas-rigs.jsx +3 -3
  282. package/src/stage-capture.jsx +42 -8
  283. package/src/stage-characters.jsx +22 -216
  284. package/src/stage-editor-gizmos.jsx +6 -6
  285. package/src/stage-environment.js +93 -0
  286. package/src/stage-hdr-builtins.js +107 -0
  287. package/src/stage-hdr-image.js +116 -0
  288. package/src/stage-hdr-library.js +70 -0
  289. package/src/stage-hdr-map.js +94 -0
  290. package/src/stage-hdr.js +130 -0
  291. package/src/stage-lighting.js +149 -0
  292. package/src/stage-occlusion.js +210 -0
  293. package/src/stage-sky.jsx +159 -0
  294. package/src/stage-startup-defaults.js +5 -9
  295. package/src/studio-actions.js +12 -14
  296. package/src/studio-agent-commands.js +19 -16
  297. package/src/studio-agent-motion.js +9 -9
  298. package/src/studio-agent-protocol.js +41 -71
  299. package/src/studio-app-binding.js +25 -45
  300. package/src/studio-asset-list.js +17 -0
  301. package/src/studio-contact-sheet.js +37 -5
  302. package/src/studio-elements.js +27 -7
  303. package/src/studio-entity-bounds.js +18 -0
  304. package/src/studio-error-codes.js +8 -0
  305. package/src/studio-export-framing.js +152 -0
  306. package/src/studio-lighting-check.js +103 -0
  307. package/src/studio-motion-visual.js +150 -0
  308. package/src/studio-schema-errors.js +80 -0
  309. package/src/studio-support-gap.js +74 -0
  310. package/src/styles.css +1 -19
  311. package/src/timeline-defaults.js +5 -0
  312. package/src/timeline-extent.js +8 -20
  313. package/src/tutorial-walk.js +17 -0
  314. package/src/ui-scrub.js +1 -1
  315. package/src/use-shot-camera-tracks.js +12 -0
  316. package/src/view-ghosts.js +97 -0
  317. package/src/view-ghosts.jsx +49 -0
  318. package/src/workflow/AgentPanel.jsx +47 -166
  319. package/src/workflow/AgentProgressCard.jsx +107 -0
  320. package/src/workflow/AgentReplyText.jsx +37 -0
  321. package/src/workflow/AgentTurnSteps.jsx +84 -0
  322. package/src/workflow/LoginPanel.jsx +140 -0
  323. package/src/workflow/WorkflowBuilder.jsx +7 -23
  324. package/src/workflow/agent-client.js +54 -51
  325. package/src/workflow/agent-panel.css +71 -1
  326. package/src/workflow/agent-progress-card.css +167 -0
  327. package/src/workflow/agent-progress-view.js +47 -0
  328. package/src/workflow/agent-turn-steps.css +113 -0
  329. package/src/workflow/agent-turn.js +191 -0
  330. package/src/workflow/login-client.js +34 -0
  331. package/src/workflow/motion-input.js +18 -31
  332. package/src/workflow/node-schema.js +1 -1
  333. package/src/workflow/reply-markdown.js +69 -0
  334. package/src/workflow/scene-asset-sync.js +8 -8
  335. package/tools/agent-session-stats.mjs +61 -0
  336. package/tools/dev-full.mjs +5 -56
  337. package/tools/eslint-baseline.json +12 -13
  338. package/tools/knip-baseline.json +0 -179
  339. package/tools/loc-baseline.json +31 -81
  340. package/tools/motion3/extract-body.mjs +103 -0
  341. package/tools/motion3/extract-rig.mjs +85 -0
  342. package/tools/process-supervisor.mjs +0 -88
  343. package/tools/run-tests.mjs +8 -124
  344. package/bin/agent/motion-runtime.mjs +0 -76
  345. package/dist/ardy/cskel27-rest.json +0 -557
  346. package/dist/assets/analytics-C9pMpW7s.js +0 -1
  347. package/dist/assets/app-B_2XB9rw.css +0 -1
  348. package/dist/assets/app-DAuvKPP8.js +0 -4920
  349. package/dist/assets/config-Bx7pYsD9.js +0 -1
  350. package/dist/assets/config-DeoFTYzb.css +0 -1
  351. package/dist/assets/demo-CvKuBgy5.js +0 -1
  352. package/dist/assets/scene-asset-sync-DKkpjKBV.js +0 -19
  353. package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
  354. package/dist/assets/ticket-BPk2Ni95.js +0 -1
  355. package/dist/assets/workflow-jJRBR94Z.js +0 -179
  356. package/dist/demo/walk-then-stop.npz +0 -0
  357. package/mcp/ardy-prompts.mjs +0 -218
  358. package/src/ardy/auto-fix-panel.css +0 -108
  359. package/src/ardy/auto-physics.js +0 -1194
  360. package/src/ardy/client.js +0 -153
  361. package/src/ardy/convert.js +0 -313
  362. package/src/ardy/cskel27-neutral.js +0 -39
  363. package/src/ardy/cskel27.js +0 -77
  364. package/src/ardy/export.js +0 -165
  365. package/src/ardy/fix-collisions.js +0 -2257
  366. package/src/ardy/foot-lock.js +0 -230
  367. package/src/ardy/motion-calibration.js +0 -118
  368. package/src/ardy/motion-edit.js +0 -213
  369. package/src/ardy/motion-url.js +0 -55
  370. package/src/ardy/mp4-duration.js +0 -102
  371. package/src/ardy/npz.js +0 -595
  372. package/src/ardy/physics-panel.css +0 -21
  373. package/src/ardy/physics-panel.jsx +0 -89
  374. package/src/ardy/physics-refine.js +0 -111
  375. package/src/ardy/physics-review.js +0 -567
  376. package/src/ardy/physics-temporal.js +0 -54
  377. package/src/ardy/platform-fit-panel.css +0 -64
  378. package/src/ardy/platform-fit-panel.jsx +0 -41
  379. package/src/ardy/platform-fit.js +0 -326
  380. package/src/ardy/playback.js +0 -711
  381. package/src/ardy/pose-pin.js +0 -97
  382. package/src/ardy/prompt-clips.js +0 -30
  383. package/src/ardy/retime.js +0 -211
  384. package/src/ardy/root-drop.js +0 -369
  385. package/src/ardy/timeline-resize.js +0 -13
  386. package/src/ardy/to-cskel27.js +0 -225
  387. package/src/ardy/trim.js +0 -33
  388. package/src/ardy/waypoints.js +0 -369
  389. package/src/ardy-bridge-contract.js +0 -281
  390. package/src/domains/motion/motion-video-capture.js +0 -664
  391. package/src/i2v-motion-client.js +0 -77
  392. package/src/i2v-motion-studio.jsx +0 -180
  393. package/src/line-edit.js +0 -1348
  394. package/src/motion/generation.js +0 -105
  395. package/src/motion-readiness-ui.jsx +0 -67
  396. package/src/motion-readiness.js +0 -40
  397. package/src/motion-resources.js +0 -177
  398. package/src/motion-store.js +0 -65
  399. package/src/motion-trail.js +0 -601
  400. package/src/multimodel-ingest.js +0 -394
  401. package/src/panels/PromptBlocksPanel.jsx +0 -444
  402. package/src/panels/VideoCapturePanel.jsx +0 -181
  403. package/src/pose-extract/browser.js +0 -42
  404. package/src/pose-extract/detector.js +0 -100
  405. package/src/pose-extract/fit.js +0 -227
  406. package/src/pose-extract/image-frame.js +0 -51
  407. package/src/pose-extract/index.js +0 -58
  408. package/src/pose-extract/keyframes.js +0 -74
  409. package/src/pose-extract/landmarks.js +0 -162
  410. package/src/pose-extract/mirror.js +0 -153
  411. package/src/pose-extract/take.js +0 -131
  412. package/src/pose-extract/video-frames.js +0 -91
  413. package/src/take-recipe.js +0 -165
  414. package/src/trail-key-conflicts.js +0 -39
  415. package/src/trail-pick.js +0 -59
  416. package/src/use-i2v-capture-modal.js +0 -15
  417. package/tools/ardy/BRIDGE.md +0 -37
  418. package/tools/ardy/GVHMR-NPZ.md +0 -68
  419. package/tools/ardy/README.md +0 -124
  420. package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
  421. package/tools/ardy/artifacts.mjs +0 -34
  422. package/tools/ardy/bridge.mjs +0 -1732
  423. package/tools/ardy/bvh-cskel27.mjs +0 -1265
  424. package/tools/ardy/cclay_constrained_generate.py +0 -561
  425. package/tools/ardy/cclay_gvhmr_worker.py +0 -264
  426. package/tools/ardy/cclay_motion_edit.py +0 -510
  427. package/tools/ardy/cclay_sequence_generate.py +0 -705
  428. package/tools/ardy/cclay_worker.py +0 -304
  429. package/tools/ardy/dump-npz.py +0 -205
  430. package/tools/ardy/extract-rest.mjs +0 -299
  431. package/tools/ardy/extract.mjs +0 -507
  432. package/tools/ardy/footage.mjs +0 -467
  433. package/tools/ardy/gvhmr-floor.mjs +0 -102
  434. package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
  435. package/tools/ardy/gvhmr_fastpath.py +0 -168
  436. package/tools/ardy/gvhmr_trajectory.py +0 -240
  437. package/tools/ardy/merge-text-encoder.py +0 -160
  438. package/tools/ardy/mocap-metrics.mjs +0 -200
  439. package/tools/ardy/mocap-quality-gate.mjs +0 -110
  440. package/tools/ardy/motion-stabilize.mjs +0 -348
  441. package/tools/ardy/npz.mjs +0 -414
  442. package/tools/ardy/pose-to-npz.mjs +0 -106
  443. package/tools/ardy/prompt-limits.mjs +0 -5
  444. package/tools/ardy/run-edit-on-box.sh +0 -73
  445. package/tools/ardy/run-local.mjs +0 -233
  446. package/tools/ardy/run-on-box.sh +0 -593
  447. package/tools/ardy/run-sequence-on-box.sh +0 -177
  448. package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
  449. package/tools/ardy/runners/index.mjs +0 -18
  450. package/tools/ardy/runners/local.mjs +0 -455
  451. package/tools/ardy/runners/proc.mjs +0 -125
  452. package/tools/ardy/runners/remote.mjs +0 -252
  453. package/tools/ardy/setup-local.mjs +0 -189
  454. package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
  455. package/tools/ardy/setup-text-encoder.py +0 -306
  456. package/tools/ardy/smpl-cskel27.mjs +0 -178
  457. package/tools/ardy/visual-qa.mjs +0 -196
  458. package/tools/ardy/vq-car.mjs +0 -52
  459. package/tools/bench/EXP3.md +0 -61
  460. package/tools/bench/cclay_bench_extract_incam.py +0 -125
  461. package/tools/bench/cclay_bench_extract_obs.py +0 -204
  462. package/tools/bench/cclay_bench_runner.py +0 -42
  463. package/tools/bench/cube-contact.mjs +0 -162
  464. package/tools/bench/exp3.mjs +0 -152
  465. package/tools/bench/extract-bench-lib.mjs +0 -216
  466. package/tools/bench/extract-bench.mjs +0 -302
  467. package/tools/bench/fal-generate.mjs +0 -88
  468. package/tools/bench/fit/README.md +0 -189
  469. package/tools/bench/fit/camera.mjs +0 -59
  470. package/tools/bench/fit/contact.mjs +0 -419
  471. package/tools/bench/fit/footlock.mjs +0 -234
  472. package/tools/bench/fit/motion.mjs +0 -85
  473. package/tools/bench/fit/pin.mjs +0 -27
  474. package/tools/bench/fit/remote.mjs +0 -105
  475. package/tools/bench/fit-bench.mjs +0 -126
  476. package/tools/bench/fit-sanity.mjs +0 -45
  477. package/tools/bench/metrics.mjs +0 -313
  478. package/tools/bench/obs/depth.mjs +0 -258
  479. package/tools/bench/obs/extrinsics.mjs +0 -175
  480. package/tools/bench/obs/fit_mannequin_betas.py +0 -340
  481. package/tools/bench/obs/ground.mjs +0 -294
  482. package/tools/bench/obs/heading.mjs +0 -151
  483. package/tools/bench/obs/ladder.mjs +0 -555
  484. package/tools/bench/obs/mannequin-betas.json +0 -124
  485. package/tools/bench/obs/remote.mjs +0 -83
  486. package/tools/bench/obs/rest_joints.py +0 -52
  487. package/tools/bench/obs/ybot-targets.mjs +0 -49
  488. package/tools/bench/obs-bench.mjs +0 -520
  489. package/tools/bench/score.mjs +0 -343
  490. package/tools/bench/summarize.mjs +0 -86
  491. package/tools/demo-worker/README.md +0 -137
  492. package/tools/demo-worker/api-client.mjs +0 -233
  493. package/tools/demo-worker/generate.mjs +0 -301
  494. package/tools/demo-worker/index.mjs +0 -466
  495. package/tools/demo-worker/sign-core.mjs +0 -112
  496. package/tools/demo-worker/sign.mjs +0 -161
  497. package/tools/gt-render/browser.mjs +0 -182
  498. package/tools/gt-render/camera-math.mjs +0 -276
  499. package/tools/gt-render/page.mjs +0 -267
  500. package/tools/gt-render/render.mjs +0 -514
  501. package/tools/gt-render/scene-box.mjs +0 -31
  502. package/tools/gt-render/take-transform.mjs +0 -87
  503. package/tools/kimodo/compare-seam.mjs +0 -108
  504. package/tools/kimodo/constraints.mjs +0 -244
  505. package/tools/kimodo/edit.mjs +0 -259
  506. package/tools/kimodo/effector-constraints.mjs +0 -200
  507. package/tools/kimodo/generate.mjs +0 -646
  508. package/tools/kimodo/local-output.mjs +0 -265
  509. package/tools/kimodo/measure-pose.mjs +0 -65
  510. package/tools/kimodo/measure-preserve.mjs +0 -899
  511. package/tools/kimodo/measure-waypoints.mjs +0 -55
  512. package/tools/kimodo/mlx-generate.py +0 -111
  513. package/tools/kimodo/pose-constraints.mjs +0 -248
  514. package/tools/kimodo/preserve-mask.mjs +0 -543
  515. package/tools/kimodo/read-npz.mjs +0 -189
  516. package/tools/kimodo/run-edit-on-box.mjs +0 -155
  517. package/tools/kimodo/run-sequence-on-box.mjs +0 -178
  518. package/tools/kimodo/runner.mjs +0 -284
  519. package/tools/kimodo/seam-batch.mjs +0 -77
  520. package/tools/kimodo/setup-local.mjs +0 -30
  521. package/tools/kimodo/setup-on-box.sh +0 -339
  522. package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
  523. package/tools/morphgs/assets/gen_truth.py +0 -39
  524. package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
  525. package/tools/morphgs/assets/playback-check.mjs +0 -30
  526. package/tools/morphgs/demo-gate.sh +0 -26
  527. package/tools/morphgs/fbx2morphgs.mjs +0 -68
  528. package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
  529. package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
  530. package/tools/morphgs/setup-on-cluster.sh +0 -126
  531. package/tools/projflow/driver.py +0 -1069
  532. package/tools/projflow/generate.mjs +0 -805
  533. package/tools/projflow/hml22-to-cskel27.mjs +0 -735
  534. package/tools/projflow/line-edit-job.mjs +0 -547
  535. package/tools/projflow/replay.mjs +0 -452
  536. package/tools/projflow/runner.mjs +0 -269
  537. package/tools/projflow/service.mjs +0 -742
  538. package/tools/track/DESIGN.md +0 -513
  539. package/tools/track/backfill-provenance.mjs +0 -116
  540. package/tools/track/budget.mjs +0 -8
  541. package/tools/track/check-rig.mjs +0 -209
  542. package/tools/track/diagnostics.schema.json +0 -60
  543. package/tools/track/export-rig.mjs +0 -256
  544. package/tools/track/fallback.mjs +0 -7
  545. package/tools/track/fk-parity-fixture.mjs +0 -161
  546. package/tools/track/gate.mjs +0 -349
  547. package/tools/track/masks.mjs +0 -318
  548. package/tools/track/metrics.mjs +0 -201
  549. package/tools/track/publish-obs.mjs +0 -108
  550. package/tools/track/py/check_env.py +0 -61
  551. package/tools/track/py/eval_lr.py +0 -229
  552. package/tools/track/py/lr_viterbi.py +0 -294
  553. package/tools/track/py/masks.py +0 -405
  554. package/tools/track/py/objective.py +0 -382
  555. package/tools/track/py/rig.py +0 -508
  556. package/tools/track/py/scene.py +0 -326
  557. package/tools/track/py/test_joint_indices.py +0 -123
  558. package/tools/track/py/test_lr_viterbi.py +0 -195
  559. package/tools/track/py/test_masks.py +0 -229
  560. package/tools/track/py/test_rig.py +0 -288
  561. package/tools/track/py/test_scene.py +0 -354
  562. package/tools/track/py/test_track.py +0 -328
  563. package/tools/track/py/track.py +0 -411
  564. package/tools/track/remote.mjs +0 -140
  565. package/tools/track/rig-dump.mjs +0 -227
  566. package/tools/track/run-box-tests.mjs +0 -14
  567. package/tools/track/run-box.mjs +0 -168
  568. package/tools/track/setup-box.sh +0 -59
  569. package/tools/track/study-2d.mjs +0 -728
  570. /package/src/{ardy → motion}/collision-blockers.js +0 -0
  571. /package/src/{ardy → motion}/ground.js +0 -0
  572. /package/src/{ardy → motion}/ik-drag.js +0 -0
  573. /package/src/{ardy → motion}/ik-key-json.js +0 -0
  574. /package/src/{ardy → motion}/ik.js +0 -0
  575. /package/src/{ardy → motion}/physics-surface.js +0 -0
  576. /package/src/{ardy → motion}/playback-clock.js +0 -0
  577. /package/src/{ardy → motion}/range-pin.js +0 -0
@@ -11,6 +11,7 @@ import { elementByPath } from "../studio-elements.js";
11
11
  import { saveAutoColor } from "../auto-color.js";
12
12
  import { trackFeature } from "../analytics.js";
13
13
  import { GUIDE_LABELS, nextGuideMode } from "../shot-guides.js";
14
+ import GhostsMenuGroup from "./GhostsMenuGroup.jsx";
14
15
  import "./viewport.css";
15
16
 
16
17
  // G1: the single mode+tool pill. Keys 1-5 and W/E/R are bound in App's
@@ -40,7 +41,6 @@ const ICON = {
40
41
  rotate: "M13.25 8A5.25 5.25 0 1 1 11.7 4.3 M13.25 2.5v2.75H10.5",
41
42
  scale: "M2.5 8.5v4a1 1 0 0 0 1 1h4 M8.5 2.5h5v5 M13.5 2.5 7.5 8.5",
42
43
  ik: "M2.5 13.5 6.5 9l3 2.2 4-7.7 M6.5 9h.01 M9.5 11.2h.01",
43
- trail: "M2 12.5c3 0 3-9 6-9s3 9 6 9",
44
44
  pin: "M8 14.5v-4 M5 2h6 M6.2 2v3.6L4.5 10.5h7L9.8 5.6V2",
45
45
  blocks: "M2 3.5h7.5v3.5H2z M6.5 9h7.5v3.5H6.5z",
46
46
  refine: "M10.5 2.5l3 3L6 13H3v-3z",
@@ -63,12 +63,10 @@ function RailIcon({ name, size = 16 }) {
63
63
 
64
64
  // The gizmo's snap increments (TRANSLATE_SNAP / ROTATE_SNAP in
65
65
  // src/scene-objects.js). They are fixed, so the value group names them.
66
- const SNAP_MOVE = "5cm";
67
- const SNAP_TURN = "5°";
66
+ const SNAP_MOVE = "5cm", SNAP_TURN = "5°";
68
67
 
69
68
  // Editor lens range: shotsDomain.changeLens and the FOV slider take 14-90°.
70
- const FOV_MIN = 14;
71
- const FOV_MAX = 90;
69
+ const FOV_MIN = 14, FOV_MAX = 90;
72
70
 
73
71
  // "+ Add › Character" stands the new body one metre along X per existing
74
72
  // character, inside the same stage clamp the Content drag applies.
@@ -117,15 +115,14 @@ function MenuItem({ checked, role = "menuitemradio", className = "", children, .
117
115
  export default function ViewportToolbar() {
118
116
  const {
119
117
  workflowMode, selectWorkflowMode, poseRefusal, gizmoMode, setGizmoMode, snapEnabled,
120
- setSnapEnabled, preset, applyPreset, cameraPresetId, i2vMotionCameraLocked,
118
+ setSnapEnabled, preset, applyPreset, cameraPresetId,
121
119
  runStudioAction, shotAspectKey, fovDeg, shotsDomain, shot, shots, activeShot,
122
120
  setNonce, workspaceLayout, viewMenuTriggerRef, viewMenuOpen,
123
121
  setViewMenuOpen, viewLooksActive, gridView, setGridView, guideMode,
124
122
  autoColor, setAutoColor, isCharacterSelection, partColoursChoice, embedMode,
125
123
  agentCollapsed, addSceneObject, spawnCharacter, characters, flySpeed,
126
- ikEditTool, setIkEditTool, showTrails, setShowTrails, motion, setRangePinPartPick,
127
- trailFalloffS, setTrailFalloffS, lineEditMode, exitLineEditMode, enterRefineMode,
128
- refineDisabledReason, previsMode, sculptView, requestSculptView,
124
+ ikEditTool, setIkEditTool, motion, setRangePinPartPick,
125
+ previsMode, sculptView, requestSculptView,
129
126
  } = useStudioShell();
130
127
  const menu = useOverlayMenu();
131
128
 
@@ -136,7 +133,6 @@ export default function ViewportToolbar() {
136
133
  setAutoColor(next);
137
134
  };
138
135
 
139
- const refineReason = lineEditMode ? null : refineDisabledReason();
140
136
  const tools = {
141
137
  scene: [
142
138
  { key: "W", id: "move", name: ko("Move", "이동"), active: gizmoMode === "move", pick: () => setGizmoMode("move") },
@@ -145,11 +141,7 @@ export default function ViewportToolbar() {
145
141
  ],
146
142
  pose: [
147
143
  { key: "W", id: "ik", name: ko("Pose fix (IK parts)", "포즈 수정 (IK 파츠)"), active: ikEditTool === "ik", pick: () => setIkEditTool("ik") },
148
- {
149
- key: "E", id: "trail", name: ko("Path fix (motion trail)", "경로 수정 (궤적선)"), active: ikEditTool === "trail",
150
- refused: showTrails ? null : ko("Turn Trails on in Show to edit the motion path", "경로를 수정하려면 표시에서 궤적선을 켜세요"),
151
- pick: () => setIkEditTool("trail"),
152
- },
144
+
153
145
  {
154
146
  key: "R", id: "pin", name: ko("Pin (range pin)", "고정 (범위 고정)"), active: ikEditTool === "pin",
155
147
  refused: motion ? null : ko("Pinning needs a motion take", "고정하려면 모션 테이크가 필요해요"),
@@ -160,16 +152,8 @@ export default function ViewportToolbar() {
160
152
  { key: "W", id: "move", name: ko("Move camera", "카메라 이동"), active: gizmoMode === "move", pick: () => setGizmoMode("move") },
161
153
  { key: "E", id: "rotate", name: ko("Rotate camera", "카메라 회전"), active: gizmoMode === "rotate", pick: () => setGizmoMode("rotate") },
162
154
  ],
163
- motion: [
164
- {
165
- key: "W", id: "blocks", name: ko("Blocks (select and move prompt blocks)", "블록 (프롬프트 블록 선택·이동)"), active: !lineEditMode,
166
- pick: () => { if (lineEditMode) exitLineEditMode(); },
167
- },
168
- {
169
- key: "E", id: "refine", name: ko("Refine (edit the path line)", "다듬기 (경로선 편집)"), active: lineEditMode,
170
- refused: refineReason, pick: () => { if (!lineEditMode) enterRefineMode(); },
171
- },
172
- ],
155
+ // Motion is compiled by the agent (motion.compile); the department has no tools of its own.
156
+ motion: [],
173
157
  // Sculpt mode's W/E/R swing the turntable camera to a reference view.
174
158
  sculpt: [
175
159
  { key: "W", id: "front", name: ko("Front view", "정면 보기"), active: sculptView?.view === "front", pick: () => requestSculptView("front") },
@@ -200,33 +184,6 @@ export default function ViewportToolbar() {
200
184
  <span className="vp-value-part"><RailIcon name="grid" size={14} />{SNAP_MOVE}</span>
201
185
  <span className="vp-value-part"><RailIcon name="angle" size={14} />{SNAP_TURN}</span>
202
186
  </button>
203
- ) : workflowMode === "pose" ? (
204
- <div className="vp-menu-wrap" data-vp-menu="influence">
205
- <button
206
- type="button"
207
- className="vp-value"
208
- aria-haspopup="dialog"
209
- aria-expanded={menu.open === "influence"}
210
- title={ko("Influence range — how far an edit blends into nearby frames", "영향 범위 — 수정이 주변 프레임에 섞이는 길이")}
211
- onClick={() => menu.toggle("influence")}
212
- >
213
- {trimNumber(trailFalloffS)}s
214
- </button>
215
- {menu.open === "influence" && (
216
- <div className="vp-menu vp-slider-popover" role="dialog" aria-label={ko("Influence range", "영향 범위")}>
217
- <input
218
- type="range"
219
- min={0.1}
220
- max={2}
221
- step={0.1}
222
- value={trailFalloffS}
223
- aria-label={ko("Influence range", "영향 범위")}
224
- onChange={(event) => setTrailFalloffS(Number(event.target.value))}
225
- />
226
- <output>{trimNumber(trailFalloffS)}s</output>
227
- </div>
228
- )}
229
- </div>
230
187
  ) : workflowMode === "camera" ? (
231
188
  <>
232
189
  <div className="vp-menu-wrap" data-vp-menu="lens">
@@ -248,7 +205,6 @@ export default function ViewportToolbar() {
248
205
  key={mm}
249
206
  data-lens={mm}
250
207
  checked={shot.focalMm === mm}
251
- disabled={i2vMotionCameraLocked}
252
208
  onClick={() => { shotsDomain.changeLens(fov); menu.close(); }}
253
209
  >
254
210
  {mm}mm
@@ -262,7 +218,6 @@ export default function ViewportToolbar() {
262
218
  max={FOV_MAX}
263
219
  step="1"
264
220
  value={fovDeg}
265
- disabled={i2vMotionCameraLocked}
266
221
  onChange={(event) => shotsDomain.changeLens(Number(event.target.value))}
267
222
  />
268
223
  <output>{Math.round(fovDeg)}°</output>
@@ -460,7 +415,6 @@ export default function ViewportToolbar() {
460
415
  <select
461
416
  aria-label={ko("Camera preset", "카메라 프리셋")}
462
417
  value={cameraPresetId ?? ""}
463
- disabled={i2vMotionCameraLocked}
464
418
  onChange={(event) => {
465
419
  const id = event.target.value;
466
420
  if (!id) { runStudioAction("stage.setFilmback", { cameraPresetId: null }); return; }
@@ -577,21 +531,7 @@ export default function ViewportToolbar() {
577
531
  {ko("Composition guides", "구도 가이드")}
578
532
  <small>{ko(GUIDE_LABELS[guideMode].en, GUIDE_LABELS[guideMode].ko)}</small>
579
533
  </button>
580
- <button
581
- type="button"
582
- role="menuitemcheckbox"
583
- className={"view-menu-item trails-toggle" + (showTrails ? " active" : "")}
584
- aria-checked={showTrails}
585
- aria-pressed={showTrails}
586
- title={ko("Motion trails while posing", "포즈 편집 중 궤적선")}
587
- onClick={() => {
588
- if (showTrails && ikEditTool === "trail") setIkEditTool("ik");
589
- setShowTrails(!showTrails);
590
- }}
591
- >
592
- <span className="view-menu-mark" aria-hidden="true">{showTrails ? "✓" : ""}</span>
593
- {ko("Trails", "궤적선")}
594
- </button>
534
+ <GhostsMenuGroup />
595
535
  {/* Part colours repaint a BODY, so the section only exists
596
536
  while a character is selected (R2). */}
597
537
  {isCharacterSelection && (
@@ -23,7 +23,14 @@
23
23
  border: 0;
24
24
  background: none;
25
25
  }
26
- .app[data-shell="glass"] .studio-agent-inspector .agent-title { font: 600 13px var(--sans); color: var(--text-1); }
26
+ .app[data-shell="glass"] .studio-agent-inspector .agent-title {
27
+ min-width: 0;
28
+ overflow: hidden;
29
+ color: var(--text-1);
30
+ font: 600 13px var(--sans);
31
+ white-space: nowrap;
32
+ text-overflow: ellipsis;
33
+ }
27
34
  .app[data-shell="glass"] .studio-agent-inspector .agent-status-dot { display: none; }
28
35
  .app[data-shell="glass"] .studio-agent-inspector .agent-icon-button {
29
36
  display: grid;
@@ -227,7 +234,9 @@
227
234
  font: 400 12.5px/1.5 var(--sans);
228
235
  }
229
236
  .app[data-shell="glass"] .studio-agent-inspector .agent-composer textarea::placeholder { color: var(--text-3); }
230
- .app[data-shell="glass"] .studio-agent-inspector .agent-composer-controls { gap: 2px; margin: 4px 0 0 -6px; }
237
+ /* A narrow dock wraps the controls to a second row instead of crushing the
238
+ model name to its caret or pushing Send past the field's edge. */
239
+ .app[data-shell="glass"] .studio-agent-inspector .agent-composer-controls { flex-wrap: wrap; gap: 4px 2px; margin: 4px 0 0 -6px; }
231
240
  .app[data-shell="glass"] .studio-agent-inspector .agent-attach-chip {
232
241
  display: grid;
233
242
  place-items: center;
@@ -248,9 +257,9 @@
248
257
  .app[data-shell="glass"] .studio-agent-inspector .agent-model-select {
249
258
  -webkit-appearance: none;
250
259
  appearance: none;
251
- flex: 0 1 auto;
252
- min-width: 0;
253
- max-width: 132px;
260
+ flex: 1 1 96px;
261
+ min-width: 96px;
262
+ max-width: none;
254
263
  height: 26px;
255
264
  padding: 0 18px 0 8px;
256
265
  border: 0;
@@ -262,7 +271,7 @@
262
271
  cursor: pointer;
263
272
  }
264
273
  .app[data-shell="glass"] .studio-agent-inspector .agent-model-select:hover { background-color: var(--chip-fill); color: var(--text-1); }
265
- .app[data-shell="glass"] .studio-agent-inspector .agent-effort-select { flex: none; max-width: none; }
274
+ .app[data-shell="glass"] .studio-agent-inspector .agent-effort-select { flex: none; min-width: 0; max-width: none; }
266
275
  .app[data-shell="glass"] .studio-agent-inspector .agent-model-select optgroup,
267
276
  .app[data-shell="glass"] .studio-agent-inspector .agent-model-select option { background: var(--surface-raised); color: var(--text-1); }
268
277
  .app[data-shell="glass"] .studio-agent-inspector .agent-send {
@@ -293,4 +302,8 @@
293
302
 
294
303
  /* Provider keys: the same quiet rows. */
295
304
  .app[data-shell="glass"] .studio-agent-inspector .agent-keys { margin: 0 10px 8px; border: 0; border-radius: 12px; background: var(--card-fill); box-shadow: var(--card-ring); }
305
+ /* Connect a model takes the panel body while it is open: one scroll, and no
306
+ second "Connect a model" card showing through behind it. */
307
+ .app[data-shell="glass"] .studio-agent-inspector .agent-login { flex: 1 1 auto; min-height: 0; max-height: none; }
308
+ .app[data-shell="glass"] .studio-agent-inspector .agent-login ~ .agent-transcript { display: none; }
296
309
  .app[data-shell="glass"] .studio-agent-inspector .agent-key-input { border: 0; border-radius: 8px; background: var(--field-fill); color: var(--text-1); }
@@ -0,0 +1,42 @@
1
+ // The Details panel's selection header: the selected item's name and its
2
+ // "Kind · detail" type line.
3
+ import { ko } from "../locale.js";
4
+ import { sceneObjectNameDisplayKo, HIERARCHY_INSPECTOR_TITLES, CHARACTER_MODEL_LABELS } from "../app-stage.jsx";
5
+ import { CUTOUT_KIND, EMPTY_KIND, SCULPT_KIND } from "../scene-objects.js";
6
+ import { LIGHT_KIND } from "../object-look.js";
7
+
8
+ const characterIndexForRow = (rowId, characters) => rowId === "characterA" ? 0
9
+ : rowId === "characterB" ? 1
10
+ : characters.findIndex((entry) => `character:${entry.id}` === rowId);
11
+ const characterTitle = (index) => ko(`Character ${index + 1}`, `인물 ${index + 1}`);
12
+
13
+ /** The 2a selection header: the selected item's name and a "Kind · detail"
14
+ * type line. Null when nothing that owns settings is selected. */
15
+ export function detailsSelection({ selectedHierarchyId: id, selectedSceneObject, rigSelection, characters, shot, inspectorHasContent }) {
16
+ if (!inspectorHasContent) return null;
17
+ if (selectedSceneObject) {
18
+ const { renderer, light } = selectedSceneObject;
19
+ if (renderer === LIGHT_KIND) return { name: sceneObjectNameDisplayKo(selectedSceneObject.name), type: `${ko("Light", "조명")} · ${light?.type === "spot" ? ko("Spot", "스포트") : ko("Point", "점")}` };
20
+ const kind = renderer === CUTOUT_KIND ? ko("Cutout", "컷아웃") : renderer === EMPTY_KIND ? ko("Empty", "빈 오브젝트") : renderer === SCULPT_KIND ? ko("Sculpt", "조형") : ko("Mesh", "메시");
21
+ return { name: sceneObjectNameDisplayKo(selectedSceneObject.name), type: `${renderer === EMPTY_KIND ? ko("Node", "노드") : ko("Prop", "소품")} · ${kind}` };
22
+ }
23
+ if (rigSelection) {
24
+ const index = characterIndexForRow(rigSelection.rowId, characters);
25
+ const kind = rigSelection.token === "rig" ? ko("Rig", "리그") : ko("Bone", "본");
26
+ return { name: HIERARCHY_INSPECTOR_TITLES[rigSelection.token] ?? kind, type: index >= 0 ? `${kind} · ${characterTitle(index)}` : kind };
27
+ }
28
+ if (id === "camera") return { name: HIERARCHY_INSPECTOR_TITLES.camera, type: `${ko("Camera", "카메라")} · ${shot.focalMm}mm` };
29
+ if (id === "characterA" || id === "characterB" || id.startsWith("character:")) {
30
+ const index = characterIndexForRow(id, characters);
31
+ const model = CHARACTER_MODEL_LABELS[characters[index]?.model];
32
+ return { name: characterTitle(Math.max(index, 0)), type: model ? `${ko("Character", "인물")} · ${model}` : ko("Character", "인물") };
33
+ }
34
+ const types = {
35
+ shot: ko("Scene", "장면"),
36
+ light: ko("Light", "조명"),
37
+ characters: ko("Folder", "폴더"),
38
+ environment: ko("Environment", "환경"),
39
+ props: ko("Folder", "폴더"),
40
+ };
41
+ return { name: HIERARCHY_INSPECTOR_TITLES[id] ?? ko("Selection", "선택 항목"), type: types[id] ?? "" };
42
+ }
@@ -0,0 +1,22 @@
1
+ /* The View menu's Ghosts group (GhostsMenuGroup.jsx): two colour chips in the heading and
2
+ compact number steppers that keep the 24px menu rows. */
3
+ .ghosts-menu .view-menu-label { display: flex; align-items: center; gap: 4px; }
4
+ .ghosts-menu .ghost-swatch { display: inline-block; width: 8px; height: 8px; border-radius: 2px; opacity: 0.8; }
5
+ .ghosts-menu .ghost-swatch:first-of-type { margin-left: 4px; }
6
+ .ghosts-menu .view-menu-item.ghost-stepper { cursor: default; }
7
+ .ghosts-menu .ghost-stepper.disabled { opacity: 0.45; }
8
+ .ghosts-menu .ghost-stepper-label { flex: 1; }
9
+ .ghosts-menu .ghost-stepper button {
10
+ width: 18px;
11
+ height: 18px;
12
+ padding: 0;
13
+ border: 1px solid var(--row-divider, var(--line));
14
+ border-radius: 4px;
15
+ background: none;
16
+ color: inherit;
17
+ font: inherit;
18
+ line-height: 1;
19
+ cursor: pointer;
20
+ }
21
+ .ghosts-menu .ghost-stepper button:disabled { cursor: default; opacity: 0.5; }
22
+ .ghosts-menu .ghost-stepper-value { min-width: 16px; text-align: center; font-variant-numeric: tabular-nums; }
@@ -431,9 +431,9 @@
431
431
  --tl-ruler-height: 24px;
432
432
  --tl-track-row-height: 22px;
433
433
  --tl-track-group-height: 66px;
434
- /* The surface is exactly its rows (ruler + 2 lanes + 2 lane groups), so it
434
+ /* The surface is exactly its rows (ruler + 1 lane + 2 lane groups), so it
435
435
  never asks the body for more height than the dock gives it. */
436
- --tl-surface-height: calc(var(--tl-ruler-height) + var(--tl-track-row-height) * 2 + var(--tl-track-group-height) * 2);
436
+ --tl-surface-height: calc(var(--tl-ruler-height) + var(--tl-track-row-height) + var(--tl-track-group-height) * 2);
437
437
  --tl-camera-bar-height: 28px;
438
438
  --tl-track-tree-width: 170px;
439
439
  --tl-clip-inset: 4px;
@@ -446,7 +446,8 @@
446
446
  height: auto;
447
447
  min-height: 48px;
448
448
  gap: 12px;
449
- padding: 0 16px;
449
+ /* The right inset keeps the pinned collapse toggle clear of the controls. */
450
+ padding: 0 52px 0 16px;
450
451
  border: 0;
451
452
  background: none;
452
453
  }
@@ -500,6 +501,31 @@
500
501
  .app[data-shell="glass"]:not([data-embed-mode]) .v2-sequencer .tl-seq-action:hover:not(:disabled),
501
502
  .app[data-shell="glass"]:not([data-embed-mode]) .v2-sequencer .tl-head-group .tl-btn:hover:not(:disabled) { background: var(--chip-fill); color: var(--text-1); }
502
503
  .app[data-shell="glass"]:not([data-embed-mode]) .v2-sequencer .tl-seq-action:disabled { opacity: .4; }
504
+ /* The take's segment speed sits in the same quiet chip grammar as its neighbours. */
505
+ .app[data-shell="glass"]:not([data-embed-mode]) .v2-sequencer .tl-motion-speed-editor {
506
+ min-width: 0;
507
+ height: 26px;
508
+ gap: 6px;
509
+ padding: 0 8px;
510
+ border: 0;
511
+ border-radius: 13px;
512
+ background: none;
513
+ color: var(--label);
514
+ font: 500 12px var(--sans);
515
+ }
516
+ .app[data-shell="glass"]:not([data-embed-mode]) .v2-sequencer .tl-motion-speed-editor > span { font-weight: 500; }
517
+ .app[data-shell="glass"]:not([data-embed-mode]) .v2-sequencer .tl-motion-speed-editor input[type="range"] { width: 72px; accent-color: var(--primary-fill, var(--select)); }
518
+ .app[data-shell="glass"]:not([data-embed-mode]) .v2-sequencer .tl-motion-speed-editor input[type="number"] {
519
+ width: 40px;
520
+ height: 22px;
521
+ padding: 0 4px;
522
+ border: 0;
523
+ border-radius: 6px;
524
+ background: var(--chip-fill);
525
+ color: var(--text-1);
526
+ font: 500 12px var(--sans);
527
+ }
528
+ .app[data-shell="glass"]:not([data-embed-mode]) .v2-sequencer .tl-motion-speed-editor small { color: var(--label); }
503
529
  .app[data-shell="glass"]:not([data-embed-mode]) .v2-sequencer .tl-btn.wp.on { background: var(--seg-on); box-shadow: var(--seg-on-shadow); color: var(--seg-on-text); }
504
530
  .app[data-shell="glass"]:not([data-embed-mode]) .v2-sequencer .tl-badge {
505
531
  height: 22px;
@@ -381,6 +381,9 @@
381
381
  }
382
382
 
383
383
  .v2-preferences .v2-preferences__language {
384
+ display: inline-flex;
385
+ align-items: center;
386
+ justify-content: center;
384
387
  height: var(--h-control, 28px);
385
388
  padding: 0 var(--sp-2, 12px);
386
389
  border: 0;
@@ -512,6 +515,8 @@
512
515
  color: var(--text-3, #636369);
513
516
  font-size: var(--prefs-secondary-size, 11px);
514
517
  font-weight: 500;
518
+ letter-spacing: 0;
519
+ text-transform: none;
515
520
  }
516
521
 
517
522
  .v2-preferences .v2-preferences__help button {
@@ -519,7 +524,7 @@
519
524
  padding: 0 var(--sp-2, 12px);
520
525
  border: 0;
521
526
  border-radius: var(--r-1, 4px);
522
- background: transparent;
527
+ background: var(--field-fill, var(--surface-raised, #1e1e21));
523
528
  color: var(--text-2, #9b9ba1);
524
529
  font: inherit;
525
530
  font-size: var(--prefs-secondary-size, 11px);
@@ -6,6 +6,7 @@
6
6
 
7
7
  import { createTiming, timingIsFlat } from "./speed-envelope.js";
8
8
  import { createShot } from "./cuts.js";
9
+ import { railShotFields } from "./camera-block.js";
9
10
  import { normalizeStableItems } from "./stable-items.js";
10
11
  import { VIDEO_MODEL_PRESETS } from "./model-presets.js";
11
12
  import { elementByPath } from "./studio-elements.js";
@@ -110,7 +111,7 @@ const FOLLOW_BOUNDS = {
110
111
  height: [0.2, Number.POSITIVE_INFINITY],
111
112
  response: [0.1, 3],
112
113
  lead: [0, 1],
113
- maxDollySpeed: [0.2, 8],
114
+ maxDollySpeed: [0.2, 40],
114
115
  pitchOffsetDeg: [-170, 170],
115
116
  orbitOffsetDeg: [-180, 180],
116
117
  };
@@ -299,6 +300,7 @@ function repairCamera(value) {
299
300
  // The dolly's speed curve rides the rail the same way; the envelope
300
301
  // module owns its repair (parse-don't-validate, flat heals to null).
301
302
  dollyTiming: cameraRail ? repairDollyTiming(source.dollyTiming) : null,
303
+ ...railShotFields(source, cameraRail),
302
304
  };
303
305
  }
304
306
 
@@ -310,12 +312,7 @@ function repairDollyTiming(value) {
310
312
  function migratedCamera(followCam, cameraRail, railFollow = null) {
311
313
  const rail = repairRail(cameraRail);
312
314
  const enabled = followCam?.enabled === true;
313
- return repairCamera({
314
- mode: enabled ? (rail ? "rail" : "follow") : "keys",
315
- followCam,
316
- cameraRail: rail,
317
- railFollow,
318
- });
315
+ return repairCamera({ mode: enabled ? (rail ? "rail" : "follow") : "keys", followCam, cameraRail: rail, railFollow });
319
316
  }
320
317
 
321
318
  function repairShared(parsed, frameCount, ids) {
@@ -0,0 +1,37 @@
1
+ // Soft key shadows in the same pass. three r185's PCF filter takes five taps
2
+ // on a Vogel disk of shadow.radius texels, rotated per pixel by interleaved
3
+ // gradient noise; past a radius of about two texels those five taps show as a
4
+ // cross-hatched grain over every penumbra. A wider radius (stage.lighting
5
+ // shadowSoftness) therefore takes SOFT_SHADOW_TAPS taps instead, which keeps
6
+ // the same disk and noise rotation but averages the grain away. Radius 1 —
7
+ // every stage before the look was authorable — runs the original five-tap code
8
+ // unchanged, so studio frames stay pixel-identical.
9
+ //
10
+ // Evaluated against the alternatives: PCFSoftShadowMap is deprecated in r185
11
+ // (it falls back to PCF); VSMShadowMap blurs smoothly but loses contact shadows
12
+ // (a leg's shadow on a box beside it vanished), cannot shadow point lights, and
13
+ // is renderer-wide, so it would restyle the studio look too.
14
+ import { ShaderChunk } from "three";
15
+
16
+ const SOFT_SHADOW_TAPS = 16;
17
+ const tap = (index) => `texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( ${index}, 5, phi ) * radius, shadowCoord.z ) )`;
18
+ const FIVE_TAPS = `shadow = (\n${[0, 1, 2, 3, 4].map((index) => `\t\t\t\t\t${tap(index)}`).join(" +\n")}\n\t\t\t\t) * 0.2;`;
19
+ const SOFT_TAPS = `if ( shadowRadius <= 1.0 ) {
20
+ ${FIVE_TAPS}
21
+ } else {
22
+ shadow = 0.0;
23
+ for ( int i = 0; i < ${SOFT_SHADOW_TAPS}; i ++ ) shadow += texture( shadowMap, vec3( shadowCoord.xy + vogelDiskSample( i, ${SOFT_SHADOW_TAPS}, phi ) * radius, shadowCoord.z ) );
24
+ shadow /= ${SOFT_SHADOW_TAPS}.0;
25
+ }`;
26
+
27
+ /** Patch the directional/spot PCF filter once; answers whether the soft path is in. */
28
+ export function installSoftShadows(chunks = ShaderChunk) {
29
+ const source = chunks.shadowmap_pars_fragment;
30
+ if (source.includes(SOFT_TAPS)) return true;
31
+ // A three upgrade that rewrites the filter leaves the stock one in place.
32
+ if (!source.includes(FIVE_TAPS)) return false;
33
+ chunks.shadowmap_pars_fragment = source.replace(FIVE_TAPS, SOFT_TAPS);
34
+ return true;
35
+ }
36
+
37
+ installSoftShadows();
@@ -1,6 +1,6 @@
1
1
  import * as THREE from "three";
2
2
  import { SCENE_ATTACH_BONES } from "./scene-objects.js";
3
- import { TRAIL_EFFECTOR_JOINTS } from "./motion-trail.js";
3
+
4
4
  import { normalizeBoneName } from "./poses.js";
5
5
 
6
6
  /** The rig rows that ARE an attach frame: `rig.<track id>`, the same camel
@@ -8,14 +8,14 @@ import { normalizeBoneName } from "./poses.js";
8
8
  * rig.leftArm …) name a limb, not a frame, so they are deliberately absent. */
9
9
  export const ATTACH_BONE_ROWS = new Map(SCENE_ATTACH_BONES.map((bone) => [`rig.${bone}`, bone]));
10
10
 
11
- /** Attach track id -> the Mixamo bone carrying that frame on the shipped rigs.
12
- * TRAIL_EFFECTOR_JOINTS names the cskel27 joint, and cskel27 and Mixamo agree
13
- * everywhere except the spine, which sits one bone up the Mixamo chain (the
14
- * same shift ardy/playback.js SKINNING_MAP makes). */
15
- export const ATTACH_BONE_NAMES = Object.fromEntries(SCENE_ATTACH_BONES.map((bone) => {
16
- const joint = TRAIL_EFFECTOR_JOINTS[bone];
17
- return [bone, joint === "Spine1" ? "Spine" : joint === "Spine2" ? "Spine1" : joint];
18
- }));
11
+ /** Attach track id -> the Mixamo bone carrying that frame on the shipped rigs. */
12
+ const MIXAMO_ATTACH_BONES = {
13
+ hips: "Hips", spine: "Spine", chest: "Spine1", neck: "Neck", head: "Head",
14
+ leftShoulder: "LeftArm", leftElbow: "LeftForeArm", leftHand: "LeftHand",
15
+ rightShoulder: "RightArm", rightElbow: "RightForeArm", rightHand: "RightHand",
16
+ leftKnee: "LeftLeg", leftFoot: "LeftFoot", rightKnee: "RightLeg", rightFoot: "RightFoot",
17
+ };
18
+ export const ATTACH_BONE_NAMES = Object.fromEntries(SCENE_ATTACH_BONES.map((bone) => [bone, MIXAMO_ATTACH_BONES[bone]]));
19
19
 
20
20
  // One scratch set for the whole module: resolving a frame runs per attached
21
21
  // prop per frame and must never allocate.
@@ -36,7 +36,7 @@ export const placeEuler = new THREE.Euler();
36
36
 
37
37
  /** The bone a rig offers under `mixamoName`, by the project's matching rule
38
38
  * (normalised names equal, or one a suffix of the other; first depth-first
39
- * match wins — poses.js and ardy/playback.js agree). Cached per rig: this is
39
+ * match wins — poses.js and motion3/playback.js agree). Cached per rig: this is
40
40
  * asked once per attached prop per rendered frame. */
41
41
  export const attachBoneCache = new WeakMap();
42
42
  export function attachBoneOf(rig, mixamoName) {
@@ -65,8 +65,8 @@ export function attachBoneOf(rig, mixamoName) {
65
65
  * A carried prop takes the bone's place and facing; its size stays its own.
66
66
  *
67
67
  * `bone === null` is the character's animated ROOT: the hips' travel (during
68
- * playback the whole root trajectory lives in the bones — see
69
- * ardy/playback.js) carried at the character's own yaw, so a prop dropped on
68
+ * playback the hips travel lives in the bones — see motion3/playback.js)
69
+ * carried at the character's own yaw, so a prop dropped on
70
70
  * the character walks with the body instead of rolling with the hips.
71
71
  */
72
72
  export function attachFrameMatrix(rig, bone, out = new THREE.Matrix4()) {
@@ -212,9 +212,7 @@ export function FollowCamRig({ enabled, frame, frameRef, scene, shot, camRef, lo
212
212
  applied.current = null;
213
213
  if (enabled) invalidate();
214
214
  }, [scene, shot, enabled, invalidate]);
215
- useEffect(() => {
216
- if (enabled) invalidate();
217
- }, [frame, enabled, invalidate]);
215
+ useEffect(() => { if (enabled) invalidate(); }, [frame, enabled, invalidate]);
218
216
  useFrame(() => {
219
217
  if (!enabled) return;
220
218
  if (isInterrupted?.()) return; // the user is flying; yield until released
@@ -227,6 +225,8 @@ export function FollowCamRig({ enabled, frame, frameRef, scene, shot, camRef, lo
227
225
  cam.position.set(sample.pos.x, sample.pos.y, sample.pos.z);
228
226
  look.current.yaw = sample.yaw;
229
227
  look.current.pitch = sample.pitch;
228
+ // A rail with a lens of its own carries it; otherwise this is the scene lens.
229
+ if (Math.abs(cam.fov - sample.fovDeg) > 1e-3) { cam.fov = sample.fovDeg; cam.updateProjectionMatrix(); }
230
230
  invalidate();
231
231
  });
232
232
  return null;
@@ -25,7 +25,9 @@ export function CaptureRig({ apiRef, camRef, width = CAPTURE_W, height = CAPTURE
25
25
  useEffect(() => {
26
26
  // Each attempt owns its target independently of the live output size.
27
27
  // Resizing the editor cannot dispose an in-flight export's resources.
28
- function createExportCapture({ width, height }) {
28
+ // `camera` makes the camera of each render: a clone of the shot camera unless a caller
29
+ // (renderView) brings its own; the shot camera itself is never moved.
30
+ function createExportCapture({ width, height }, camera = () => camRef.current?.clone()) {
29
31
  const target = new THREE.WebGLRenderTarget(width, height, {
30
32
  colorSpace: THREE.SRGBColorSpace,
31
33
  samples: 4,
@@ -35,9 +37,8 @@ export function CaptureRig({ apiRef, camRef, width = CAPTURE_W, height = CAPTURE
35
37
  scene,
36
38
  dispose: () => target.dispose(),
37
39
  render() {
38
- const source = camRef.current;
39
- if (!source) return null;
40
- const cam = source.clone();
40
+ const cam = camera();
41
+ if (!cam) return null;
41
42
  // the transform gizmo is UI: it never reaches an exported frame
42
43
  cam.layers.disable(GIZMO_LAYER);
43
44
  // QA hook: the layer mask the export camera actually renders
@@ -53,13 +54,27 @@ export function CaptureRig({ apiRef, camRef, width = CAPTURE_W, height = CAPTURE
53
54
  // exported frame wants the opposite: the horizon IS the vanishing
54
55
  // point, and without it the floor has no far edge to read depth
55
56
  // against. Push the falloff back for this draw only, then restore
56
- // it so the viewport is untouched.
57
+ // it so the viewport is untouched. Haze (stage.lighting.fog, set by
58
+ // StageAtmosphere) is part of the look, so it brings its own range.
57
59
  const fog = scene.fog;
58
60
  const fogNear = fog?.near;
59
61
  const fogFar = fog?.far;
62
+ const look = scene.userData.stageCapture;
60
63
  if (fog) {
61
- fog.near = CAPTURE_FOG_NEAR;
62
- fog.far = CAPTURE_FOG_FAR;
64
+ fog.near = look?.fog?.near ?? CAPTURE_FOG_NEAR;
65
+ fog.far = look?.fog?.far ?? CAPTURE_FOG_FAR;
66
+ }
67
+ // three tone-maps only the canvas, never a render target, so the
68
+ // viewport's exposure reaches an export as light: every light, and
69
+ // the environment light, is scaled by it for this draw and put back after.
70
+ const scaled = [], environmentIntensity = scene.environmentIntensity, backgroundIntensity = scene.backgroundIntensity, fogColor = fog?.color.clone();
71
+ if (look && look.exposure !== 1) scene.traverse((node) => { if (node.isLight) scaled.push([node, node.intensity]); });
72
+ for (const [light, intensity] of scaled) light.intensity = intensity * look.exposure;
73
+ if (look && look.exposure !== 1) scene.environmentIntensity = environmentIntensity * look.exposure;
74
+ // An HDR backdrop (stage.lighting.hdrBackground) is light too, and so is the horizon the deck fades into.
75
+ if (look?.backdrop && look.exposure !== 1) {
76
+ scene.backgroundIntensity = backgroundIntensity * look.exposure;
77
+ fog?.color.multiplyScalar(look.exposure);
63
78
  }
64
79
  try {
65
80
  gl.setRenderTarget(target);
@@ -71,12 +86,31 @@ export function CaptureRig({ apiRef, camRef, width = CAPTURE_W, height = CAPTURE
71
86
  fog.near = fogNear;
72
87
  fog.far = fogFar;
73
88
  }
89
+ for (const [light, intensity] of scaled) light.intensity = intensity;
90
+ scene.environmentIntensity = environmentIntensity;
91
+ scene.backgroundIntensity = backgroundIntensity;
92
+ if (fogColor) fog.color.copy(fogColor);
74
93
  }
75
94
  return buffer;
76
95
  },
77
96
  };
78
97
  }
79
- const api = { ...createExportCapture({ width, height }), createExportCapture };
98
+ // verify_result's own views (src/motion3/views.js): one read-back, rows bottom-up, from a
99
+ // camera at eye with quaternion [x, y, z, w] and a vertical fov, on a target of its own size.
100
+ function renderView({ eye, quaternion, fovDeg, output }) {
101
+ const own = createExportCapture(output, () => {
102
+ const source = camRef.current;
103
+ if (!source) return null;
104
+ const cam = source.clone();
105
+ cam.clearViewOffset();
106
+ cam.position.set(...eye);
107
+ cam.quaternion.set(...quaternion);
108
+ cam.fov = fovDeg;
109
+ return cam;
110
+ });
111
+ try { return own.render(); } finally { own.dispose(); }
112
+ }
113
+ const api = { ...createExportCapture({ width, height }), createExportCapture, renderView };
80
114
  apiRef.current = api;
81
115
  if (width === MCP_CAPTURE_W && height === MCP_CAPTURE_H) {
82
116
  window.__cozyclayMcpCaptureReady = true;