cozyclay 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/README.md +12 -30
- package/bin/agent/agent-routes.mjs +40 -113
- package/bin/agent/agent-runner.mjs +9 -10
- package/bin/agent/cliproxy-provider.mjs +135 -0
- package/bin/agent/credential-store.mjs +30 -7
- package/bin/agent/pi-tools.mjs +4 -1
- package/bin/agent/provider-keys.mjs +32 -0
- package/bin/agent/provider-login.mjs +110 -0
- package/bin/agent/provider-routes.mjs +99 -0
- package/bin/agent/providers.mjs +19 -97
- package/bin/agent/script-tool.mjs +17 -4
- package/bin/agent/studio-motion-reference.mjs +23 -0
- package/bin/agent/studio-prompt.mjs +1 -1
- package/bin/agent/studio-rebase-text.mjs +32 -0
- package/bin/agent/studio-rebase.mjs +26 -39
- package/bin/agent/studio-tools.mjs +9 -28
- package/bin/agent/tool-arguments.mjs +49 -0
- package/bin/agent/turn-frames.mjs +66 -0
- package/bin/codex-auth.mjs +9 -2
- package/bin/cozyclay.mjs +10 -116
- package/bin/live/cli.mjs +22 -6
- package/bin/mcp-runtime.mjs +2 -12
- package/bin/package-signature.mjs +0 -4
- package/dist/app/index.html +7 -6
- package/dist/assets/EXRLoader-CvVIvGVE.js +1 -0
- package/dist/assets/analytics-C9sUnndd.js +1 -0
- package/dist/assets/app-CCh--1Hc.js +5087 -0
- package/dist/assets/app-f-fkV5uP.css +1 -0
- package/dist/assets/compile-worker-CkxiD6lH.js +5 -0
- package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
- package/dist/assets/{first-shot-handoff-BlT33CGf.js → first-shot-handoff-CC4xe4HM.js} +1 -1
- package/dist/assets/{landing-BSesrCpL.js → landing-DjHD8u7k.js} +1 -1
- package/dist/assets/scene-asset-sync-Hx_FzdOH.js +20 -0
- package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
- package/dist/assets/workflow-C4yKH1p4.js +179 -0
- package/dist/cozyclay-package.json +1 -1
- package/dist/index.html +3 -3
- package/dist/llms.txt +14 -0
- package/dist/sw.js +3 -6
- package/dist/workflow/index.html +5 -4
- package/mcp/LIVE-PROTOCOL.md +7 -47
- package/mcp/README.md +16 -26
- package/mcp/live-hub.mjs +6 -10
- package/mcp/package.json +1 -3
- package/mcp/tool-handlers.mjs +4 -168
- package/package.json +3 -22
- package/src/App.jsx +174 -2639
- package/src/agent-progress.js +79 -0
- package/src/agent-turn-mark.js +30 -0
- package/src/analytics.js +1 -19
- package/src/app-context.js +5 -0
- package/src/app-stage.jsx +2 -34
- package/src/asset-pane.jsx +6 -5
- package/src/camera-block.js +21 -0
- package/src/camera-direction.js +120 -0
- package/src/character-kind.js +3 -9
- package/src/command-bus.js +8 -6
- package/src/commands/cast.js +5 -34
- package/src/commands/elements/character.js +1 -1
- package/src/commands/elements/motion.js +1 -6
- package/src/commands/elements/object.js +6 -2
- package/src/commands/elements/shot.js +4 -1
- package/src/commands/elements.js +38 -14
- package/src/commands/index.js +3 -1
- package/src/commands/kits.js +37 -0
- package/src/commands/motion-timing.js +57 -0
- package/src/commands/motion.js +9 -152
- package/src/commands/motion3-compile.js +65 -0
- package/src/commands/motion3.js +207 -0
- package/src/commands/objects.js +6 -4
- package/src/commands/shot.js +49 -11
- package/src/commands/stage.js +14 -1
- package/src/commands/view.js +4 -1
- package/src/document-mirrors.js +42 -0
- package/src/document-store.js +4 -0
- package/src/domains/cast.js +19 -194
- package/src/domains/motion/motion-range-pin-rules.js +1 -1
- package/src/domains/motion/take-source.js +51 -0
- package/src/domains/motion.js +60 -1838
- package/src/domains/scenes.js +12 -55
- package/src/domains/shots.js +2 -2
- package/src/domains/stage.js +4 -2
- package/src/draft-ghost.js +46 -0
- package/src/draft-ghost.jsx +129 -0
- package/src/dualview.jsx +4 -3
- package/src/effects/EffectsLayer.jsx +112 -0
- package/src/effects/effect-meshes.js +232 -0
- package/src/effects/effect-record.js +103 -0
- package/src/effects/emitter.js +59 -0
- package/src/effects/simulate.js +261 -0
- package/src/effects/state.js +59 -0
- package/src/execution-telemetry.js +2 -3
- package/src/first-success-guide.jsx +5 -5
- package/src/ghost-set.js +257 -0
- package/src/held-object-edit.jsx +113 -0
- package/src/held-object-pose.js +175 -0
- package/src/hierarchy-model.js +1 -1
- package/src/hierarchy-panel.jsx +1 -1
- package/src/imported-mesh.jsx +103 -0
- package/src/kits/held.js +84 -0
- package/src/kits/index.js +70 -0
- package/src/kits/smoking.js +57 -0
- package/src/light-blockers.js +93 -0
- package/src/motion/beat-board-model.js +84 -0
- package/src/motion/beat-board.css +124 -0
- package/src/motion/beat-board.jsx +59 -0
- package/src/motion/center-of-mass.js +66 -0
- package/src/motion/fix-collisions.js +850 -0
- package/src/motion/physics-review.js +118 -0
- package/src/{ardy → motion}/physics-support.js +1 -76
- package/src/motion/rig-snapshot.js +22 -0
- package/src/motion/take-segments.jsx +140 -0
- package/src/{ardy → motion}/timeline-coordinates.js +0 -21
- package/src/{ardy → motion}/timeline.css +1 -2
- package/src/{ardy → motion}/timeline.jsx +48 -419
- package/src/motion/waypoints.js +76 -0
- package/src/motion3/beats.js +83 -0
- package/src/motion3/body.js +158 -0
- package/src/motion3/bones.js +47 -0
- package/src/motion3/carried.js +47 -0
- package/src/motion3/compile-job.js +75 -0
- package/src/motion3/compile-worker.js +10 -0
- package/src/motion3/compiler/anchors.js +105 -0
- package/src/motion3/compiler/arm-orient.js +128 -0
- package/src/motion3/compiler/channels.js +125 -0
- package/src/motion3/compiler/compile.js +205 -0
- package/src/motion3/compiler/gait-rhythm.js +97 -0
- package/src/motion3/compiler/grip.js +171 -0
- package/src/motion3/compiler/head-steady.js +48 -0
- package/src/motion3/compiler/hold.js +134 -0
- package/src/motion3/compiler/idle.js +113 -0
- package/src/motion3/compiler/limbs.js +170 -0
- package/src/motion3/compiler/math.js +72 -0
- package/src/motion3/compiler/pose.js +162 -0
- package/src/motion3/compiler/quat.js +49 -0
- package/src/motion3/compiler/skeleton.js +74 -0
- package/src/motion3/compiler/validate-common.js +32 -0
- package/src/motion3/compiler/validate-goals.js +118 -0
- package/src/motion3/compiler/validate-objects.js +143 -0
- package/src/motion3/compiler/validate-parts.js +116 -0
- package/src/motion3/compiler/validate.js +122 -0
- package/src/motion3/compiler/vocab.js +73 -0
- package/src/motion3/compiler/walk-pelvis.js +275 -0
- package/src/motion3/compiler/walk.js +207 -0
- package/src/motion3/compiler/wrist-clamp.js +32 -0
- package/src/motion3/delta.js +47 -0
- package/src/motion3/describe.js +174 -0
- package/src/motion3/docs.js +27 -0
- package/src/motion3/edit-carry.js +21 -0
- package/src/motion3/fix/ease.js +16 -0
- package/src/motion3/fix/ground.js +37 -0
- package/src/motion3/fix/index.js +52 -0
- package/src/motion3/fix/push.js +71 -0
- package/src/motion3/fix/reach.js +46 -0
- package/src/motion3/fix/retime.js +79 -0
- package/src/motion3/fix/self.js +211 -0
- package/src/motion3/fix/slide.js +70 -0
- package/src/motion3/fix/turn.js +51 -0
- package/src/motion3/follow.js +39 -0
- package/src/motion3/free-motion.js +173 -0
- package/src/motion3/grip-choice.js +130 -0
- package/src/motion3/hold-plan.js +157 -0
- package/src/motion3/json-patch.js +77 -0
- package/src/motion3/key-aim.js +105 -0
- package/src/motion3/key-edit.js +82 -0
- package/src/motion3/lenient.js +127 -0
- package/src/motion3/object-keys.js +236 -0
- package/src/motion3/object-pose.js +182 -0
- package/src/motion3/object-tracks.js +12 -0
- package/src/motion3/pipeline.js +102 -0
- package/src/motion3/playback.js +51 -0
- package/src/motion3/probes.js +91 -0
- package/src/motion3/qa/body-checks.js +34 -0
- package/src/motion3/qa/check-names.js +14 -0
- package/src/motion3/qa/checks.js +121 -0
- package/src/motion3/qa/contact-checks.js +51 -0
- package/src/motion3/qa/explain.js +80 -0
- package/src/motion3/qa/fmt.js +5 -0
- package/src/motion3/qa/foot-checks.js +72 -0
- package/src/motion3/qa/geometry.js +77 -0
- package/src/motion3/qa/goals.js +191 -0
- package/src/motion3/qa/ground.js +60 -0
- package/src/motion3/qa/hints-contact.js +179 -0
- package/src/motion3/qa/hints-goal.js +160 -0
- package/src/motion3/qa/hints-knee.js +24 -0
- package/src/motion3/qa/hints-motion.js +209 -0
- package/src/motion3/qa/hints-object.js +91 -0
- package/src/motion3/qa/index.js +42 -0
- package/src/motion3/qa/key-checks.js +82 -0
- package/src/motion3/qa/near.js +96 -0
- package/src/motion3/qa/object-checks.js +135 -0
- package/src/motion3/qa/patch.js +161 -0
- package/src/motion3/qa/severity.js +38 -0
- package/src/motion3/qa/spec-checks.js +65 -0
- package/src/motion3/qa/style.js +218 -0
- package/src/motion3/qa/wrist-checks.js +69 -0
- package/src/motion3/qa/wrist-obs.js +60 -0
- package/src/motion3/refs.js +120 -0
- package/src/motion3/repair-tune.js +121 -0
- package/src/motion3/repair.js +83 -0
- package/src/motion3/report.js +67 -0
- package/src/motion3/rigs/index.js +14 -0
- package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
- package/src/motion3/rigs/x-bot-tpose.json +1 -0
- package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
- package/src/motion3/rigs/y-bot-tpose.json +1 -0
- package/src/motion3/scene.js +60 -0
- package/src/motion3/schema/brief.js +89 -0
- package/src/motion3/schema/fields.js +44 -0
- package/src/motion3/schema/spec-examples.js +46 -0
- package/src/motion3/schema/topics.js +111 -0
- package/src/motion3/schema/types.js +147 -0
- package/src/motion3/search.js +117 -0
- package/src/motion3/second-hand.js +112 -0
- package/src/motion3/skills/basic.js +82 -0
- package/src/motion3/skills/book.js +76 -0
- package/src/motion3/skills/car.js +145 -0
- package/src/motion3/skills/frames-auto.js +29 -0
- package/src/motion3/skills/index.js +83 -0
- package/src/motion3/skills/info.js +65 -0
- package/src/motion3/skills/smoke-kit.js +109 -0
- package/src/motion3/skills/smoke.js +160 -0
- package/src/motion3/spec-store.js +59 -0
- package/src/motion3/take-edit.js +155 -0
- package/src/motion3/take.js +63 -0
- package/src/motion3/timeline.js +127 -0
- package/src/motion3/views.js +121 -0
- package/src/motion3/walk-plan.js +119 -0
- package/src/object-catalog.jsx +7 -1
- package/src/object-colors.js +98 -0
- package/src/object-gizmo-parts.js +115 -0
- package/src/object-gizmo.jsx +37 -122
- package/src/object-glow.js +139 -0
- package/src/object-hidden.js +33 -0
- package/src/object-look.js +196 -0
- package/src/object-size.js +10 -0
- package/src/object-travel.js +71 -6
- package/src/panels/CameraPanel.jsx +7 -7
- package/src/panels/HdrEnvironmentControls.jsx +59 -0
- package/src/panels/LightPanel.jsx +25 -4
- package/src/panels/ObjectLookPanel.jsx +88 -0
- package/src/panels/PoseImagePanel.jsx +1 -1
- package/src/panels/PosePanel.jsx +2 -17
- package/src/panels/RigControlPanel.jsx +5 -53
- package/src/panels/SubjectBox.jsx +4 -1
- package/src/panels/details.css +14 -0
- package/src/posestudio.jsx +4 -27
- package/src/project-browser.jsx +3 -4
- package/src/project-resources.js +18 -31
- package/src/project.js +13 -104
- package/src/props.jsx +25 -280
- package/src/rail-dot-drag.js +23 -0
- package/src/render-passes.js +10 -0
- package/src/resource-status.jsx +1 -0
- package/src/result-modal.jsx +4 -19
- package/src/room.jsx +20 -12
- package/src/scene-assets.js +8 -6
- package/src/scene-light-place.js +72 -0
- package/src/scene-lights.jsx +148 -0
- package/src/scene-objects.js +31 -139
- package/src/scenes.js +15 -105
- package/src/semantic-edit.js +2 -5
- package/src/set-pieces.jsx +183 -0
- package/src/settings-menu.jsx +3 -11
- package/src/shell/BottomDock.jsx +11 -53
- package/src/shell/CompositionGuideButton.jsx +20 -0
- package/src/shell/DetailsSlot.jsx +16 -200
- package/src/shell/GhostsMenuGroup.jsx +74 -0
- package/src/shell/LibrarySlot.jsx +1 -3
- package/src/shell/MenuBar.jsx +3 -3
- package/src/shell/PreferencesDialog.jsx +15 -264
- package/src/shell/PreferencesSlot.jsx +2 -8
- package/src/shell/ShotPreviewHeader.jsx +17 -0
- package/src/shell/TopBar.jsx +5 -83
- package/src/shell/ViewportToolbar.jsx +23 -93
- package/src/shell/agent-glass.css +19 -6
- package/src/shell/details-selection.js +42 -0
- package/src/shell/ghosts-menu.css +22 -0
- package/src/shell/glass-regions.css +29 -3
- package/src/shell/preferences.css +6 -1
- package/src/shell/viewport.css +12 -0
- package/src/shot-authoring.js +4 -7
- package/src/soft-shadows.js +37 -0
- package/src/stage-attach-frames.js +12 -12
- package/src/stage-canvas-rigs.jsx +3 -3
- package/src/stage-capture.jsx +42 -8
- package/src/stage-characters.jsx +22 -216
- package/src/stage-editor-gizmos.jsx +6 -6
- package/src/stage-environment.js +93 -0
- package/src/stage-hdr-builtins.js +107 -0
- package/src/stage-hdr-image.js +116 -0
- package/src/stage-hdr-library.js +70 -0
- package/src/stage-hdr-map.js +94 -0
- package/src/stage-hdr.js +130 -0
- package/src/stage-lighting.js +149 -0
- package/src/stage-occlusion.js +210 -0
- package/src/stage-sky.jsx +159 -0
- package/src/stage-startup-defaults.js +5 -9
- package/src/studio-actions.js +12 -14
- package/src/studio-agent-commands.js +46 -16
- package/src/studio-agent-motion.js +9 -9
- package/src/studio-agent-protocol.js +46 -73
- package/src/studio-app-binding.js +29 -45
- package/src/studio-asset-list.js +17 -0
- package/src/studio-contact-sheet.js +37 -5
- package/src/studio-elements.js +27 -7
- package/src/studio-entity-bounds.js +18 -0
- package/src/studio-error-codes.js +8 -0
- package/src/studio-export-framing.js +152 -0
- package/src/studio-lighting-check.js +103 -0
- package/src/studio-motion-visual.js +150 -0
- package/src/studio-schema-errors.js +80 -0
- package/src/studio-support-gap.js +74 -0
- package/src/styles.css +1 -19
- package/src/timeline-defaults.js +5 -0
- package/src/timeline-extent.js +8 -20
- package/src/tutorial-walk.js +17 -0
- package/src/ui-scrub.js +1 -1
- package/src/use-shot-camera-tracks.js +12 -0
- package/src/view-ghosts.js +97 -0
- package/src/view-ghosts.jsx +49 -0
- package/src/workflow/AgentPanel.jsx +47 -166
- package/src/workflow/AgentProgressCard.jsx +107 -0
- package/src/workflow/AgentReplyText.jsx +37 -0
- package/src/workflow/AgentTurnSteps.jsx +84 -0
- package/src/workflow/LoginPanel.jsx +140 -0
- package/src/workflow/WorkflowBuilder.jsx +7 -23
- package/src/workflow/agent-client.js +54 -51
- package/src/workflow/agent-panel.css +71 -1
- package/src/workflow/agent-progress-card.css +167 -0
- package/src/workflow/agent-progress-view.js +47 -0
- package/src/workflow/agent-turn-steps.css +113 -0
- package/src/workflow/agent-turn.js +191 -0
- package/src/workflow/login-client.js +34 -0
- package/src/workflow/motion-input.js +18 -31
- package/src/workflow/node-schema.js +1 -1
- package/src/workflow/reply-markdown.js +69 -0
- package/src/workflow/scene-asset-sync.js +8 -8
- package/tools/agent-session-stats.mjs +61 -0
- package/tools/dev-full.mjs +5 -56
- package/tools/eslint-baseline.json +12 -13
- package/tools/headless-studio.mjs +85 -0
- package/tools/knip-baseline.json +0 -179
- package/tools/loc-baseline.json +33 -83
- package/tools/motion3/extract-body.mjs +103 -0
- package/tools/motion3/extract-rig.mjs +85 -0
- package/tools/process-supervisor.mjs +0 -88
- package/tools/run-tests.mjs +9 -124
- package/bin/agent/motion-runtime.mjs +0 -76
- package/dist/ardy/cskel27-rest.json +0 -557
- package/dist/assets/analytics-B41FmPYI.js +0 -1
- package/dist/assets/app-Do-Og5Pu.css +0 -1
- package/dist/assets/app-DwP-tl2x.js +0 -4920
- package/dist/assets/config-Bx7pYsD9.js +0 -1
- package/dist/assets/config-DeoFTYzb.css +0 -1
- package/dist/assets/demo-Dt0qZfS7.js +0 -1
- package/dist/assets/scene-asset-sync-BCWDJB1d.js +0 -19
- package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
- package/dist/assets/ticket-jqMhqL88.js +0 -1
- package/dist/assets/workflow-Br-K7Srs.js +0 -179
- package/dist/demo/walk-then-stop.npz +0 -0
- package/mcp/ardy-prompts.mjs +0 -218
- package/src/ardy/auto-fix-panel.css +0 -108
- package/src/ardy/auto-physics.js +0 -1194
- package/src/ardy/client.js +0 -153
- package/src/ardy/convert.js +0 -313
- package/src/ardy/cskel27-neutral.js +0 -39
- package/src/ardy/cskel27.js +0 -77
- package/src/ardy/export.js +0 -165
- package/src/ardy/fix-collisions.js +0 -2257
- package/src/ardy/foot-lock.js +0 -230
- package/src/ardy/motion-calibration.js +0 -118
- package/src/ardy/motion-edit.js +0 -213
- package/src/ardy/motion-url.js +0 -55
- package/src/ardy/mp4-duration.js +0 -102
- package/src/ardy/npz.js +0 -595
- package/src/ardy/physics-panel.css +0 -21
- package/src/ardy/physics-panel.jsx +0 -89
- package/src/ardy/physics-refine.js +0 -111
- package/src/ardy/physics-review.js +0 -567
- package/src/ardy/physics-temporal.js +0 -54
- package/src/ardy/platform-fit-panel.css +0 -64
- package/src/ardy/platform-fit-panel.jsx +0 -41
- package/src/ardy/platform-fit.js +0 -326
- package/src/ardy/playback.js +0 -711
- package/src/ardy/pose-pin.js +0 -97
- package/src/ardy/prompt-clips.js +0 -30
- package/src/ardy/retime.js +0 -211
- package/src/ardy/root-drop.js +0 -369
- package/src/ardy/timeline-resize.js +0 -13
- package/src/ardy/to-cskel27.js +0 -225
- package/src/ardy/trim.js +0 -33
- package/src/ardy/waypoints.js +0 -369
- package/src/ardy-bridge-contract.js +0 -281
- package/src/domains/motion/motion-video-capture.js +0 -664
- package/src/i2v-motion-client.js +0 -77
- package/src/i2v-motion-studio.jsx +0 -180
- package/src/line-edit.js +0 -1348
- package/src/motion/generation.js +0 -105
- package/src/motion-readiness-ui.jsx +0 -67
- package/src/motion-readiness.js +0 -40
- package/src/motion-resources.js +0 -177
- package/src/motion-store.js +0 -65
- package/src/motion-trail.js +0 -601
- package/src/multimodel-ingest.js +0 -394
- package/src/panels/PromptBlocksPanel.jsx +0 -444
- package/src/panels/VideoCapturePanel.jsx +0 -181
- package/src/pose-extract/browser.js +0 -42
- package/src/pose-extract/detector.js +0 -100
- package/src/pose-extract/fit.js +0 -227
- package/src/pose-extract/image-frame.js +0 -51
- package/src/pose-extract/index.js +0 -58
- package/src/pose-extract/keyframes.js +0 -74
- package/src/pose-extract/landmarks.js +0 -162
- package/src/pose-extract/mirror.js +0 -153
- package/src/pose-extract/take.js +0 -131
- package/src/pose-extract/video-frames.js +0 -91
- package/src/take-recipe.js +0 -165
- package/src/trail-key-conflicts.js +0 -39
- package/src/trail-pick.js +0 -59
- package/src/use-i2v-capture-modal.js +0 -15
- package/tools/ardy/BRIDGE.md +0 -37
- package/tools/ardy/GVHMR-NPZ.md +0 -68
- package/tools/ardy/README.md +0 -124
- package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
- package/tools/ardy/artifacts.mjs +0 -34
- package/tools/ardy/bridge.mjs +0 -1732
- package/tools/ardy/bvh-cskel27.mjs +0 -1265
- package/tools/ardy/cclay_constrained_generate.py +0 -561
- package/tools/ardy/cclay_gvhmr_worker.py +0 -264
- package/tools/ardy/cclay_motion_edit.py +0 -510
- package/tools/ardy/cclay_sequence_generate.py +0 -705
- package/tools/ardy/cclay_worker.py +0 -304
- package/tools/ardy/dump-npz.py +0 -205
- package/tools/ardy/extract-rest.mjs +0 -299
- package/tools/ardy/extract.mjs +0 -507
- package/tools/ardy/footage.mjs +0 -467
- package/tools/ardy/gvhmr-floor.mjs +0 -102
- package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
- package/tools/ardy/gvhmr_fastpath.py +0 -168
- package/tools/ardy/gvhmr_trajectory.py +0 -240
- package/tools/ardy/merge-text-encoder.py +0 -160
- package/tools/ardy/mocap-metrics.mjs +0 -200
- package/tools/ardy/mocap-quality-gate.mjs +0 -110
- package/tools/ardy/motion-stabilize.mjs +0 -348
- package/tools/ardy/npz.mjs +0 -414
- package/tools/ardy/pose-to-npz.mjs +0 -106
- package/tools/ardy/prompt-limits.mjs +0 -5
- package/tools/ardy/run-edit-on-box.sh +0 -73
- package/tools/ardy/run-local.mjs +0 -233
- package/tools/ardy/run-on-box.sh +0 -593
- package/tools/ardy/run-sequence-on-box.sh +0 -177
- package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
- package/tools/ardy/runners/index.mjs +0 -18
- package/tools/ardy/runners/local.mjs +0 -455
- package/tools/ardy/runners/proc.mjs +0 -125
- package/tools/ardy/runners/remote.mjs +0 -252
- package/tools/ardy/setup-local.mjs +0 -189
- package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
- package/tools/ardy/setup-text-encoder.py +0 -306
- package/tools/ardy/smpl-cskel27.mjs +0 -178
- package/tools/ardy/visual-qa.mjs +0 -196
- package/tools/ardy/vq-car.mjs +0 -52
- package/tools/bench/EXP3.md +0 -61
- package/tools/bench/cclay_bench_extract_incam.py +0 -125
- package/tools/bench/cclay_bench_extract_obs.py +0 -204
- package/tools/bench/cclay_bench_runner.py +0 -42
- package/tools/bench/cube-contact.mjs +0 -162
- package/tools/bench/exp3.mjs +0 -152
- package/tools/bench/extract-bench-lib.mjs +0 -216
- package/tools/bench/extract-bench.mjs +0 -302
- package/tools/bench/fal-generate.mjs +0 -88
- package/tools/bench/fit/README.md +0 -189
- package/tools/bench/fit/camera.mjs +0 -59
- package/tools/bench/fit/contact.mjs +0 -419
- package/tools/bench/fit/footlock.mjs +0 -234
- package/tools/bench/fit/motion.mjs +0 -85
- package/tools/bench/fit/pin.mjs +0 -27
- package/tools/bench/fit/remote.mjs +0 -105
- package/tools/bench/fit-bench.mjs +0 -126
- package/tools/bench/fit-sanity.mjs +0 -45
- package/tools/bench/metrics.mjs +0 -313
- package/tools/bench/obs/depth.mjs +0 -258
- package/tools/bench/obs/extrinsics.mjs +0 -175
- package/tools/bench/obs/fit_mannequin_betas.py +0 -340
- package/tools/bench/obs/ground.mjs +0 -294
- package/tools/bench/obs/heading.mjs +0 -151
- package/tools/bench/obs/ladder.mjs +0 -555
- package/tools/bench/obs/mannequin-betas.json +0 -124
- package/tools/bench/obs/remote.mjs +0 -83
- package/tools/bench/obs/rest_joints.py +0 -52
- package/tools/bench/obs/ybot-targets.mjs +0 -49
- package/tools/bench/obs-bench.mjs +0 -520
- package/tools/bench/score.mjs +0 -343
- package/tools/bench/summarize.mjs +0 -86
- package/tools/demo-worker/README.md +0 -137
- package/tools/demo-worker/api-client.mjs +0 -233
- package/tools/demo-worker/generate.mjs +0 -301
- package/tools/demo-worker/index.mjs +0 -466
- package/tools/demo-worker/sign-core.mjs +0 -112
- package/tools/demo-worker/sign.mjs +0 -161
- package/tools/gt-render/browser.mjs +0 -159
- package/tools/gt-render/camera-math.mjs +0 -276
- package/tools/gt-render/page.mjs +0 -267
- package/tools/gt-render/render.mjs +0 -514
- package/tools/gt-render/scene-box.mjs +0 -31
- package/tools/gt-render/take-transform.mjs +0 -87
- package/tools/kimodo/compare-seam.mjs +0 -108
- package/tools/kimodo/constraints.mjs +0 -244
- package/tools/kimodo/edit.mjs +0 -259
- package/tools/kimodo/effector-constraints.mjs +0 -200
- package/tools/kimodo/generate.mjs +0 -646
- package/tools/kimodo/local-output.mjs +0 -265
- package/tools/kimodo/measure-pose.mjs +0 -65
- package/tools/kimodo/measure-preserve.mjs +0 -899
- package/tools/kimodo/measure-waypoints.mjs +0 -55
- package/tools/kimodo/mlx-generate.py +0 -111
- package/tools/kimodo/pose-constraints.mjs +0 -248
- package/tools/kimodo/preserve-mask.mjs +0 -543
- package/tools/kimodo/read-npz.mjs +0 -189
- package/tools/kimodo/run-edit-on-box.mjs +0 -155
- package/tools/kimodo/run-sequence-on-box.mjs +0 -178
- package/tools/kimodo/runner.mjs +0 -284
- package/tools/kimodo/seam-batch.mjs +0 -77
- package/tools/kimodo/setup-local.mjs +0 -30
- package/tools/kimodo/setup-on-box.sh +0 -339
- package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
- package/tools/morphgs/assets/gen_truth.py +0 -39
- package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
- package/tools/morphgs/assets/playback-check.mjs +0 -30
- package/tools/morphgs/demo-gate.sh +0 -26
- package/tools/morphgs/fbx2morphgs.mjs +0 -68
- package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
- package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
- package/tools/morphgs/setup-on-cluster.sh +0 -126
- package/tools/projflow/driver.py +0 -1069
- package/tools/projflow/generate.mjs +0 -805
- package/tools/projflow/hml22-to-cskel27.mjs +0 -735
- package/tools/projflow/line-edit-job.mjs +0 -547
- package/tools/projflow/replay.mjs +0 -452
- package/tools/projflow/runner.mjs +0 -269
- package/tools/projflow/service.mjs +0 -742
- package/tools/track/DESIGN.md +0 -513
- package/tools/track/backfill-provenance.mjs +0 -116
- package/tools/track/budget.mjs +0 -8
- package/tools/track/check-rig.mjs +0 -209
- package/tools/track/diagnostics.schema.json +0 -60
- package/tools/track/export-rig.mjs +0 -256
- package/tools/track/fallback.mjs +0 -7
- package/tools/track/fk-parity-fixture.mjs +0 -161
- package/tools/track/gate.mjs +0 -349
- package/tools/track/masks.mjs +0 -318
- package/tools/track/metrics.mjs +0 -201
- package/tools/track/publish-obs.mjs +0 -108
- package/tools/track/py/check_env.py +0 -61
- package/tools/track/py/eval_lr.py +0 -229
- package/tools/track/py/lr_viterbi.py +0 -294
- package/tools/track/py/masks.py +0 -405
- package/tools/track/py/objective.py +0 -382
- package/tools/track/py/rig.py +0 -508
- package/tools/track/py/scene.py +0 -326
- package/tools/track/py/test_joint_indices.py +0 -123
- package/tools/track/py/test_lr_viterbi.py +0 -195
- package/tools/track/py/test_masks.py +0 -229
- package/tools/track/py/test_rig.py +0 -288
- package/tools/track/py/test_scene.py +0 -354
- package/tools/track/py/test_track.py +0 -328
- package/tools/track/py/track.py +0 -411
- package/tools/track/remote.mjs +0 -140
- package/tools/track/rig-dump.mjs +0 -227
- package/tools/track/run-box-tests.mjs +0 -14
- package/tools/track/run-box.mjs +0 -168
- package/tools/track/setup-box.sh +0 -59
- package/tools/track/study-2d.mjs +0 -728
- /package/src/{ardy → motion}/collision-blockers.js +0 -0
- /package/src/{ardy → motion}/ground.js +0 -0
- /package/src/{ardy → motion}/ik-drag.js +0 -0
- /package/src/{ardy → motion}/ik-key-json.js +0 -0
- /package/src/{ardy → motion}/ik.js +0 -0
- /package/src/{ardy → motion}/physics-surface.js +0 -0
- /package/src/{ardy → motion}/playback-clock.js +0 -0
- /package/src/{ardy → motion}/range-pin.js +0 -0
package/src/domains/cast.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { copyPhysicsKeys } from "../
|
|
1
|
+
import { copyPhysicsKeys } from "../motion/physics-review.js";
|
|
2
2
|
import { useState, useMemo, useEffect, useSyncExternalStore, useContext } from "react";
|
|
3
3
|
import { AppContext } from '../app-context.js';
|
|
4
4
|
import { createDocumentStore } from "../document-store.js";
|
|
@@ -13,32 +13,25 @@ import {
|
|
|
13
13
|
saveCustomPoses,
|
|
14
14
|
} from "../poses.js";
|
|
15
15
|
import { createCharacterEntry, createCharacterLayer, isProxyFigure, PROXY_FIGURE_MODEL } from "../scenes.js";
|
|
16
|
-
import { kindRefusal } from "../character-kind.js";
|
|
17
16
|
import {
|
|
18
17
|
DEFAULT_SUBJECT,
|
|
19
18
|
DEFAULT_SUBJECT2,
|
|
20
19
|
nextCharacterId,
|
|
21
20
|
MAX_WAYPOINTS,
|
|
22
|
-
MULTIMODEL_REASONS,
|
|
23
|
-
ARDY_DURATION_MIN,
|
|
24
|
-
TIMELINE_FPS,
|
|
25
21
|
} from "../app-stage.jsx";
|
|
26
22
|
import { ko, isKo } from "../locale.js";
|
|
27
|
-
import { createIkState } from "../
|
|
28
|
-
import { judgeNextWaypoint } from "../
|
|
23
|
+
import { createIkState } from "../motion/ik.js";
|
|
24
|
+
import { judgeNextWaypoint } from "../motion/waypoints.js";
|
|
29
25
|
import { StudioProtocolError } from "../studio-agent-protocol.js";
|
|
30
26
|
import { studioActionRefusal } from "../studio-actions.js";
|
|
31
27
|
import { createStableItemId, removeStableItem } from "../stable-items.js";
|
|
32
28
|
import { track, trackFeature } from "../analytics.js";
|
|
33
|
-
import { requestBridgeExtract } from "../multimodel-ingest.js";
|
|
34
|
-
import { loadMotionFromUrl } from "../ardy/npz.js";
|
|
35
|
-
import { snapshotPlaybackBones, applyMotionFrame, restorePlaybackBones } from "../ardy/playback.js";
|
|
36
29
|
|
|
37
30
|
import { shotAtFrame } from "../cuts.js";
|
|
38
31
|
|
|
39
32
|
const sameCastValue = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
40
33
|
|
|
41
|
-
|
|
34
|
+
function createCastDomain(appContext, initial, customPoses = []) {
|
|
42
35
|
const normalize = value => ({ characters: (Array.isArray(value) ? value : value.characters).map(createCharacterEntry),
|
|
43
36
|
customPoses: Array.isArray(value) ? customPoses : value.customPoses ?? customPoses });
|
|
44
37
|
let native = createDocumentStore({ owned: { cast: normalize(initial) } });
|
|
@@ -329,7 +322,6 @@ export function useCast(appContext) {
|
|
|
329
322
|
// every playhead tick.
|
|
330
323
|
const ghostLayers = useMemo(() => characters.flatMap((entry, index) => entry.id === activeChar.id || entry.hidden ? [] : [{
|
|
331
324
|
owner: `S${index + 1}`,
|
|
332
|
-
promptClips: entry.layer?.promptClips ?? [],
|
|
333
325
|
waypointFrames: (entry.layer?.waypoints ?? []).map((waypoint) => waypoint.frame),
|
|
334
326
|
}]), [characters, activeChar.id]);
|
|
335
327
|
|
|
@@ -340,7 +332,7 @@ export function useCast(appContext) {
|
|
|
340
332
|
characters: appContext.live.characters.map((entry) => ({
|
|
341
333
|
...entry,
|
|
342
334
|
layer: entry.id === activeChar.id
|
|
343
|
-
? { waypoints: appContext.shared.bufferRef.current.waypoints
|
|
335
|
+
? { waypoints: appContext.shared.bufferRef.current.waypoints }
|
|
344
336
|
: entry.layer,
|
|
345
337
|
})),
|
|
346
338
|
bufferMotion: appContext.shared.bufferRef.current.motion,
|
|
@@ -365,11 +357,7 @@ export function useCast(appContext) {
|
|
|
365
357
|
|
|
366
358
|
const [hasCharSheet, setHasCharSheet] = useState(appContext.shared.startupStage.hasCharSheet);
|
|
367
359
|
|
|
368
|
-
|
|
369
|
-
// on screen — selecting or adding a block on the timeline.
|
|
370
|
-
const [promptBlocksReveal, setPromptBlocksReveal] = useState(0);
|
|
371
|
-
|
|
372
|
-
const revealPromptBlocks = () => setPromptBlocksReveal((n) => n + 1);
|
|
360
|
+
|
|
373
361
|
|
|
374
362
|
// Root waypoints {frame, x, z, heading: null}, kept sorted by frame —
|
|
375
363
|
// the fixed bridge contract rejects out-of-order or duplicate frames.
|
|
@@ -382,13 +370,6 @@ export function useCast(appContext) {
|
|
|
382
370
|
|
|
383
371
|
const [pendingWaypointFrame, setPendingWaypointFrame] = useState(null);
|
|
384
372
|
|
|
385
|
-
const promptClips = activeChar.layer.promptClips;
|
|
386
|
-
const setPromptClips = value => setLayerField('promptClips', value);
|
|
387
|
-
const editPromptClips = value => writeLayerField(domain.activeId, 'promptClips', value);
|
|
388
|
-
function writeLayerField(characterId, key, value) {
|
|
389
|
-
domain.write(rows => rows.map(entry => entry.id === characterId ? { ...entry, layer: { ...entry.layer,
|
|
390
|
-
[key]: typeof value === 'function' ? value(entry.layer[key]) : value } } : entry));
|
|
391
|
-
}
|
|
392
373
|
function setLayerField(key, value) {
|
|
393
374
|
const entry = domain.read().find(entry => entry.id === domain.activeId) ?? domain.read()[0];
|
|
394
375
|
const next = typeof value === 'function' ? value(entry.layer[key]) : value;
|
|
@@ -396,11 +377,7 @@ export function useCast(appContext) {
|
|
|
396
377
|
return domain.run('cast.setLayer', { characterId: entry.id, layer: { [key]: next } });
|
|
397
378
|
}
|
|
398
379
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
const [photoPoseState, setPhotoPoseState] = useState("idle");
|
|
402
|
-
|
|
403
|
-
const [photoPoseError, setPhotoPoseError] = useState("");
|
|
380
|
+
|
|
404
381
|
|
|
405
382
|
// The library is the user's own material: poses read from photographs and
|
|
406
383
|
// poses saved off the rig, accumulating across sessions and projects. No
|
|
@@ -625,7 +602,6 @@ export function useCast(appContext) {
|
|
|
625
602
|
const next = !waypointMode;
|
|
626
603
|
// Both modes want the viewport pointer; the last one switched on wins,
|
|
627
604
|
// the other stands down rather than fighting for pointerdown.
|
|
628
|
-
if (next && appContext.shared.lineEditMode) appContext.shared.exitLineEditMode();
|
|
629
605
|
setWaypointMode(next);
|
|
630
606
|
if (!next) {
|
|
631
607
|
setPendingWaypointFrame(null);
|
|
@@ -711,143 +687,13 @@ export function useCast(appContext) {
|
|
|
711
687
|
appContext.notify(ko("Pose saved", "포즈 저장됨"));
|
|
712
688
|
}
|
|
713
689
|
|
|
714
|
-
/**
|
|
715
|
-
* Read a body pose out of one photograph.
|
|
716
|
-
*
|
|
717
|
-
* A still is the degenerate footage case, so it walks the same proven path:
|
|
718
|
-
* landmarks -> one-frame take -> applyMotionFrame -> capturePose. Posing the
|
|
719
|
-
* rig and reading it back is what makes the result an ordinary editable pose
|
|
720
|
-
* rather than a motion layer — the IK handles keep working on it, and the
|
|
721
|
-
* playback bones are restored so nothing about the take survives the read.
|
|
722
|
-
*
|
|
723
|
-
* Depth in a single frame is inferred, not measured, so this is a starting
|
|
724
|
-
* pose to refine, which is why it lands in the studio instead of on the
|
|
725
|
-
* character directly.
|
|
726
|
-
*/
|
|
727
|
-
async function posePhotoFile(file) {
|
|
728
|
-
if (!file || photoPoseState === "running") return;
|
|
729
|
-
// Reachable from the Inspector as well as the studio panel, and posedRig()
|
|
730
|
-
// only answers while the studio is open — fall back to the character the
|
|
731
|
-
// hierarchy has selected, which is the one the pose will be applied to.
|
|
732
|
-
const rig = posedRig() ?? activeRig;
|
|
733
|
-
let objectUrl = "";
|
|
734
|
-
setPhotoPoseState("running");
|
|
735
|
-
setPhotoPoseError("");
|
|
736
|
-
try {
|
|
737
|
-
// A capsule figure has no bones for a photo to pose.
|
|
738
|
-
if (isProxyFigure(posingChar ?? activeChar)) throw new StudioProtocolError("TARGET_NOT_READY", kindRefusal("photoPose", isKo));
|
|
739
|
-
if (!rig) throw new Error("rig-not-loaded");
|
|
740
|
-
objectUrl = URL.createObjectURL(file);
|
|
741
|
-
let bones = null;
|
|
742
|
-
let rootY = 0;
|
|
743
|
-
let gpuError = null;
|
|
744
|
-
// GVHMR on the box measures the body over the whole clip,
|
|
745
|
-
// which is more reliable than a single-frame depth estimate.
|
|
746
|
-
// The bridge wraps the still into a second of video and runs the exact
|
|
747
|
-
// GVHMR footage pipeline. A missing bridge or another backend is an error.
|
|
748
|
-
try {
|
|
749
|
-
const health = await fetch("/ardy/health", { signal: AbortSignal.timeout(2000) }).catch(() => null);
|
|
750
|
-
if (!health?.ok) throw new Error("extract-bridge-required");
|
|
751
|
-
const healthPayload = await health.json().catch(() => null);
|
|
752
|
-
if (healthPayload?.extractionBackend !== "gvhmr") throw new Error("extract-backend-unsupported");
|
|
753
|
-
const done = await requestBridgeExtract(file, {});
|
|
754
|
-
const take = await loadMotionFromUrl(done.motionUrl);
|
|
755
|
-
// The middle frame: the wrap's smoothing passes have settled
|
|
756
|
-
// there, while frame 0 can still carry filter warm-up.
|
|
757
|
-
const frame = Math.floor((take.frames - 1) / 2);
|
|
758
|
-
const snapshot = snapshotPlaybackBones(rig);
|
|
759
|
-
try {
|
|
760
|
-
applyMotionFrame(rig, { ...take, anchorFrame: frame }, frame);
|
|
761
|
-
bones = capturePose(rig);
|
|
762
|
-
// GVHMR measured the hips' true height — a crouch is a crouch
|
|
763
|
-
// because the hips came DOWN, not just because the knees bent.
|
|
764
|
-
rootY = captureHipsOffset(rig);
|
|
765
|
-
} finally {
|
|
766
|
-
restorePlaybackBones(rig, snapshot);
|
|
767
|
-
}
|
|
768
|
-
} catch (error) {
|
|
769
|
-
gpuError = error;
|
|
770
|
-
console.warn("photo pose: GVHMR extract failed", error);
|
|
771
|
-
}
|
|
772
|
-
if (!bones) throw new Error(gpuError?.message || "extract-run-failed");
|
|
773
|
-
const pose = {
|
|
774
|
-
id: `photo_${Date.now()}`,
|
|
775
|
-
label: isKo ? `사진 포즈 ${customPoses.length + 1}` : `Photo Pose ${customPoses.length + 1}`,
|
|
776
|
-
prompt: "in the exact body pose shown in the reference photograph",
|
|
777
|
-
bones,
|
|
778
|
-
rootY,
|
|
779
|
-
custom: true,
|
|
780
|
-
};
|
|
781
|
-
setStudioPick(pose.id);
|
|
782
|
-
// The studio poses whichever character it was opened on; the Inspector
|
|
783
|
-
// poses the selected one. Write the pose to whichever that is.
|
|
784
|
-
const poseTargetIndex = posingIndex >= 0 ? posingIndex : activeCharIndex;
|
|
785
|
-
// A running take drives the same bones a pose writes, so the read would
|
|
786
|
-
// land invisibly underneath it. Applying from a photo follows the same
|
|
787
|
-
// rule the Apply button already states: the motion goes first.
|
|
788
|
-
const hadMotion = Boolean(appContext.shared.motion);
|
|
789
|
-
domain.run('cast.savePose', { pose, characterId: characters[poseTargetIndex].id, clearMotion: hadMotion });
|
|
790
|
-
setPhotoPoseState("done");
|
|
791
|
-
// The pose is already saved and written by this point. GVHMR either
|
|
792
|
-
// returns a measured pose or the named error above reaches the user.
|
|
793
|
-
appContext.notify(hadMotion
|
|
794
|
-
? ko("Cleared the motion and posed from the photo — refine it with the handles", "모션을 지우고 사진으로 자세를 잡았어요 — 핸들로 다듬어 보세요")
|
|
795
|
-
: ko("Pose read from the photo — refine it with the handles", "사진에서 자세를 읽었어요 — 핸들로 다듬어 보세요"));
|
|
796
|
-
} catch (error) {
|
|
797
|
-
const code = error?.message ?? String(error);
|
|
798
|
-
// fitLandmarksToPose refuses a sample whose torso is not visible; that is
|
|
799
|
-
// a photograph problem, not an engine problem, so it is named as one.
|
|
800
|
-
const named = code.startsWith("fitLandmarksToPose:") ? "pose-partly-occluded" : code;
|
|
801
|
-
setPhotoPoseState("error");
|
|
802
|
-
setPhotoPoseError(MULTIMODEL_REASONS[named]?.[isKo ? 1 : 0] ?? named);
|
|
803
|
-
} finally {
|
|
804
|
-
if (objectUrl) URL.revokeObjectURL(objectUrl);
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
|
|
808
690
|
function removePose(id) {
|
|
809
691
|
domain.run('cast.removePose', { id });
|
|
810
692
|
if (studioPick === id) setStudioPick(DEFAULT_POSE.id);
|
|
811
693
|
}
|
|
812
694
|
|
|
813
|
-
function addPromptClip(frame, surface = "timeline") {
|
|
814
|
-
const before = domain.read().find(entry => entry.id === domain.activeId).layer.promptClips;
|
|
815
|
-
const receipt = domain.run('character.addPromptBlock', { characterId: domain.activeId, frame });
|
|
816
|
-
const clip = domain.read().find(entry => entry.id === domain.activeId).layer.promptClips.find(clip => !before.some(row => row.id === clip.id));
|
|
817
|
-
setSelectedPromptId(clip.id);
|
|
818
|
-
appContext.shared.setArdyDuration(Math.max(ARDY_DURATION_MIN, clip.endFrame / TIMELINE_FPS));
|
|
819
|
-
trackFeature('prompt_block_add'); return receipt;
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
function changePromptClip(id, text) {
|
|
823
|
-
domain.beginGesture();
|
|
824
|
-
const receipt = domain.edit('character.changePromptBlock', { characterId: domain.activeId, id, text });
|
|
825
|
-
if (id === selectedPromptId) appContext.shared.setArdyPrompt(text);
|
|
826
|
-
return receipt;
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
// Quality policy: one prompt block never spans more than 5 s. Kimodo
|
|
830
|
-
// walk-to-run sweeps (seeds 7/21/99; seam stall ratio, 1.0 = no stall)
|
|
831
|
-
// scored 0.79 for 5 s blocks (best of the sweep), close to a seam-free
|
|
832
|
-
// single take at 0.85; 8 s blocks collapsed to 0.32. <2 s blocks lose
|
|
833
|
-
// about a third of their frames to the transition window, so 3-5 s is the recommended
|
|
834
|
-
// authoring range.
|
|
835
|
-
const PROMPT_BLOCK_MAX_FRAMES = 5 * TIMELINE_FPS;
|
|
836
|
-
|
|
837
|
-
function resizePromptClip(id, edge, frame) {
|
|
838
|
-
return domain.edit('character.resizePromptBlock', { characterId: domain.activeId, id, edge, frame });
|
|
839
|
-
}
|
|
840
|
-
function movePromptClip(id, frame) {
|
|
841
|
-
return domain.edit('character.movePromptBlock', { characterId: domain.activeId, id, frame });
|
|
842
|
-
}
|
|
843
|
-
function removePromptClip(id) {
|
|
844
|
-
const receipt = domain.run('character.removePromptBlock', { characterId: domain.activeId, id });
|
|
845
|
-
if (selectedPromptId === id) setSelectedPromptId(null);
|
|
846
|
-
return receipt;
|
|
847
|
-
}
|
|
848
695
|
function applyExternalCharacters(characters) {
|
|
849
696
|
appContext.storeDomain('cast').run('cast.replace', { characters });
|
|
850
|
-
appContext.shared.restoreMotionRefs(characters);
|
|
851
697
|
}
|
|
852
698
|
function publishStudioCharacters(next) {
|
|
853
699
|
if (typeof next === 'function') next = next(appContext.live.characters);
|
|
@@ -857,18 +703,15 @@ export function useCast(appContext) {
|
|
|
857
703
|
for (const entry of next) if (Object.hasOwn(entry, 'sessionMotion')) owner.publishMotion(entry.id, entry.sessionMotion);
|
|
858
704
|
}
|
|
859
705
|
/** The active character's layer lives in the editing buffer, and the read
|
|
860
|
-
* model folds that buffer back over the cast. A published or restored
|
|
861
|
-
*
|
|
862
|
-
* would revert it. */
|
|
706
|
+
* model folds that buffer back over the cast. A published or restored root
|
|
707
|
+
* path has to reach it in the same tick, or the next read would revert it. */
|
|
863
708
|
function syncStudioLayerBuffer(rows) {
|
|
864
709
|
if (appContext.storeDomain('cast')) return appContext.storeDomain('cast').syncLayer();
|
|
865
710
|
const layer = rows.find(entry => entry.id === appContext.shared.loadedLayerCharRef.current)?.layer;
|
|
866
711
|
const changed = key => Array.isArray(layer?.[key]) && JSON.stringify(layer[key]) !== JSON.stringify(appContext.shared.bufferRef.current[key]);
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
if (clips) setPromptClips(layer.promptClips);
|
|
871
|
-
if (path) setWaypoints(layer.waypoints);
|
|
712
|
+
if (!changed("waypoints")) return;
|
|
713
|
+
appContext.shared.bufferRef.current = { ...appContext.shared.bufferRef.current, waypoints: layer.waypoints };
|
|
714
|
+
setWaypoints(layer.waypoints);
|
|
872
715
|
}
|
|
873
716
|
function undoScene() {
|
|
874
717
|
const receipt = appContext.bus.run('edit.undo');
|
|
@@ -914,7 +757,7 @@ export function useCast(appContext) {
|
|
|
914
757
|
switchNativeMotionLayer(previous, entry);
|
|
915
758
|
appContext.shared.loadedLayerCharRef.current = entry.id;
|
|
916
759
|
domain.syncLayer();
|
|
917
|
-
|
|
760
|
+
setWaypointMode(false); setActiveWaypointId(null); setPendingWaypointFrame(null);
|
|
918
761
|
}
|
|
919
762
|
function createLegacyCastHandlers(finitePatch, characterForRef) {
|
|
920
763
|
function replaceCharacters(next) { return domain.run('cast.replace', { characters: next }); }
|
|
@@ -953,29 +796,14 @@ export function useCast(appContext) {
|
|
|
953
796
|
domain.run('character.remove', { characterId: character.id });
|
|
954
797
|
return { id: character.id };
|
|
955
798
|
}
|
|
956
|
-
|
|
957
|
-
if (!Array.isArray(args.blocks)) throw new Error("Invalid blocks");
|
|
958
|
-
const stamp = Date.now();
|
|
959
|
-
const clips = args.blocks.map((block, i) => {
|
|
960
|
-
const startFrame = Math.round(Number(block.startFrame));
|
|
961
|
-
const endFrame = Math.round(Number(block.endFrame));
|
|
962
|
-
if (!Number.isFinite(startFrame) || !Number.isFinite(endFrame) || endFrame <= startFrame) {
|
|
963
|
-
throw new Error(`Invalid frame range on block ${i + 1}`);
|
|
964
|
-
}
|
|
965
|
-
if (typeof block.text !== "string" || !block.text.trim()) throw new Error(`Block ${i + 1} needs text`);
|
|
966
|
-
return { id: `prompt-${stamp}-${i}`, startFrame, endFrame, text: block.text.trim() };
|
|
967
|
-
});
|
|
968
|
-
domain.run('character.setPromptBlocks', { characterId: domain.activeId, blocks: clips });
|
|
969
|
-
return { blocks: clips.length };
|
|
970
|
-
}
|
|
971
|
-
return { add_character: addLiveCharacter, update_character: updateLiveCharacter, remove_character: removeLiveCharacter, set_prompt_blocks: setLivePromptBlocks };
|
|
799
|
+
return { add_character: addLiveCharacter, update_character: updateLiveCharacter, remove_character: removeLiveCharacter };
|
|
972
800
|
}
|
|
973
801
|
function toggleCharacterHidden(charId) { return domain.run('character.update', { characterId: charId, patch: { hidden: castMemberOf(charId).hidden !== true } }); }
|
|
974
802
|
domain.snapshotMotion = snapshotNativeMotion;
|
|
975
803
|
domain.syncLayer = () => {
|
|
976
804
|
const entry = domain.read().find(entry => entry.id === appContext.shared.loadedLayerCharRef.current) ?? domain.read()[0];
|
|
977
805
|
appContext.shared.bufferRef.current = { ...appContext.shared.bufferRef.current, ...entry.layer };
|
|
978
|
-
|
|
806
|
+
|
|
979
807
|
setActiveWaypointId(id => entry.layer.waypoints.some(waypoint => waypoint.id === id) ? id : null);
|
|
980
808
|
};
|
|
981
809
|
domain.loadView = () => { appContext.shared.loadedLayerCharRef.current = domain.activeId; setActiveCharacterId(domain.activeId); };
|
|
@@ -989,8 +817,7 @@ export function useCast(appContext) {
|
|
|
989
817
|
const shots = appContext.storeDomain('shot');
|
|
990
818
|
if (!shots) return;
|
|
991
819
|
const current = domain.projection(), active = current.find(entry => entry.id === domain.activeId) ?? current[0];
|
|
992
|
-
const extent = timelineContentExtent(current, active.id, appContext.shared.bufferRef.current.motion,
|
|
993
|
-
active.layer.promptClips, appContext.shared.motionDomain.multiModelFootage?.frames);
|
|
820
|
+
const extent = timelineContentExtent(current, active.id, appContext.shared.bufferRef.current.motion, null);
|
|
994
821
|
domain.setTimeline(Math.max(24, timelineSpan(extent, shots.read(), shots.state().frameCount)));
|
|
995
822
|
};
|
|
996
823
|
domain.extendTimeline = domain.syncTimeline;
|
|
@@ -1011,14 +838,12 @@ export function useCast(appContext) {
|
|
|
1011
838
|
spawnCharacter, charKeyToHierarchyId, charIdFromHierarchyId, activeCharacterId, setActiveCharacterId,
|
|
1012
839
|
rowIdForCharIndex, activeChar, selectActiveCharacterInHierarchy, activeCharIndex, activeRig, waitForRig,
|
|
1013
840
|
ghostLayers, snapshotCast, changeInspectorCharacter, hasCharSheet,
|
|
1014
|
-
setHasCharSheet,
|
|
841
|
+
setHasCharSheet, waypointMode,
|
|
1015
842
|
setWaypointMode, waypoints, setWaypoints, activeWaypointId, setActiveWaypointId, pendingWaypointFrame,
|
|
1016
|
-
setPendingWaypointFrame,
|
|
1017
|
-
setSelectedPromptId, photoPoseState, photoPoseError, setPhotoPoseError, allPoses, selectablePoses,
|
|
843
|
+
setPendingWaypointFrame, allPoses, selectablePoses,
|
|
1018
844
|
posingIndex, posingChar, posedRig, setPosed, rootStart, queueRootWaypointFrame, castMemberOf,
|
|
1019
845
|
addCharacterWaypoint, moveCharacterWaypoint, removeCharacterWaypoint, clearCharacterWaypoints,
|
|
1020
846
|
addFloorWaypoint, moveWaypoint, removeWaypoint, toggleWaypointMode, openStudio, closeStudio,
|
|
1021
|
-
saveCurrentPose, savePose,
|
|
1022
|
-
PROMPT_BLOCK_MAX_FRAMES, resizePromptClip, movePromptClip, removePromptClip,
|
|
847
|
+
saveCurrentPose, savePose, removePose,
|
|
1023
848
|
};
|
|
1024
849
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// What a saved take v3 is: the motion spec, the character placement and the scene as the
|
|
2
|
+
// compiler saw it (motionScene boxes), never the baked Float32 arrays. Compiling is
|
|
3
|
+
// deterministic, so compiling the source again rebuilds the same bones: this follows the
|
|
4
|
+
// motion.compile install path step for step (pipeline compileSpec, then bakeTake). Searched
|
|
5
|
+
// open parameters are already resolved in the stored spec, so no search runs again.
|
|
6
|
+
import { compileSpec } from "../../motion3/pipeline.js";
|
|
7
|
+
import { bakeTake } from "../../motion3/take.js";
|
|
8
|
+
import { motionScene } from "../../motion3/scene.js";
|
|
9
|
+
import { skeletonFor } from "../../motion3/rigs/index.js";
|
|
10
|
+
import { isTakeV3 } from "../../motion3/playback.js";
|
|
11
|
+
import { normalizeTakeEdit } from "../../motion3/take-edit.js";
|
|
12
|
+
export { renderTakeEdit } from "../../motion3/take-edit.js";
|
|
13
|
+
|
|
14
|
+
const TAKE_SCHEMA = "cozyclay.take.v3";
|
|
15
|
+
const SPEC_SCHEMA = "cozyclay.motion-spec.v1";
|
|
16
|
+
const TIMELINE_FPS = 24;
|
|
17
|
+
const plain = value => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
18
|
+
const finite3 = value => Array.isArray(value) && value.length === 3 && value.every(Number.isFinite);
|
|
19
|
+
|
|
20
|
+
/** The JSON source of an installed take v3 (null for any other motion). Skills, anchors and
|
|
21
|
+
* hinges may read any scene object, so the whole compile scene is kept. */
|
|
22
|
+
export function takeSource(take, sceneObjects = []) {
|
|
23
|
+
if (!isTakeV3(take) || !plain(take.spec)) return null;
|
|
24
|
+
return structuredClone({ schema: TAKE_SCHEMA, rig: take.rig, spec: take.spec,
|
|
25
|
+
placement: { position: take.placement?.position ?? [0, 0, 0], yaw: take.placement?.yaw ?? 0 }, scene: motionScene(sceneObjects) });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** A saved source (with the Studio take id it carried), checked and owned by the caller; null when it is not one. */
|
|
29
|
+
export function normalizeTakeSource(value) {
|
|
30
|
+
if (!plain(value) || value.schema !== TAKE_SCHEMA || typeof value.rig !== "string") return null;
|
|
31
|
+
if (!plain(value.spec) || value.spec.schema !== SPEC_SCHEMA || !Number.isFinite(value.spec.frames)) return null;
|
|
32
|
+
if (!plain(value.placement) || !finite3(value.placement.position) || !Number.isFinite(value.placement.yaw)) return null;
|
|
33
|
+
const objects = plain(value.scene?.objects) ? value.scene.objects : {}, others = plain(value.scene?.others) ? { others: value.scene.others } : {};
|
|
34
|
+
return structuredClone({ schema: TAKE_SCHEMA, rig: value.rig, spec: value.spec,
|
|
35
|
+
placement: { position: value.placement.position, yaw: value.placement.yaw }, scene: { objects, ...others },
|
|
36
|
+
...(typeof value.takeId === "string" && value.takeId ? { takeId: value.takeId } : {}),
|
|
37
|
+
...(normalizeTakeEdit(value.edit, value.spec.frames) ? { edit: normalizeTakeEdit(value.edit, value.spec.frames) } : {}) });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** What a scene saves for a motion layer's take descriptor: its source, take id and timing edit (take-edit.js), or null. */
|
|
41
|
+
export const savedTakeSource = descriptor => descriptor?.source ? { ...descriptor.source, takeId: descriptor.studioTakeId, ...(descriptor.edit ? { edit: descriptor.edit } : {}) } : null;
|
|
42
|
+
|
|
43
|
+
/** Compile a source back into the installed take (with `frames`, as motion.compile installs it).
|
|
44
|
+
* Leniently: a field a later, stricter validator does not know never blocks loading a saved take. */
|
|
45
|
+
export function compileTakeSource(source) {
|
|
46
|
+
const sk = skeletonFor(source?.rig);
|
|
47
|
+
if (!sk || !plain(source.spec)) return null;
|
|
48
|
+
const { out } = compileSpec({ fps: TIMELINE_FPS, ...source.spec }, { sk, scene: source.scene ?? { objects: {} } }, { lenient: true });
|
|
49
|
+
const take = bakeTake(sk, out, source.placement, { spec: source.spec, prompt: source.spec.label ?? "" });
|
|
50
|
+
return { ...take, frames: take.frameCount };
|
|
51
|
+
}
|