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
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useEffect,
|
|
2
|
-
import { createPortal } from "react-dom";
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
3
2
|
import { useStudioShell } from "./studio-shell-context.js";
|
|
3
|
+
import ShotPreviewHeader from "./ShotPreviewHeader.jsx";
|
|
4
4
|
import { ko } from "../locale.js";
|
|
5
5
|
import { PRESETS, SHOT_ASPECT_PRESETS } from "../app-stage.jsx";
|
|
6
6
|
import { CAMERA_PRESETS } from "../camera-move.js";
|
|
@@ -10,6 +10,8 @@ import { CHARACTER_MODEL_IDS } from "../scenes.js";
|
|
|
10
10
|
import { elementByPath } from "../studio-elements.js";
|
|
11
11
|
import { saveAutoColor } from "../auto-color.js";
|
|
12
12
|
import { trackFeature } from "../analytics.js";
|
|
13
|
+
import { GUIDE_LABELS, nextGuideMode } from "../shot-guides.js";
|
|
14
|
+
import GhostsMenuGroup from "./GhostsMenuGroup.jsx";
|
|
13
15
|
import "./viewport.css";
|
|
14
16
|
|
|
15
17
|
// G1: the single mode+tool pill. Keys 1-5 and W/E/R are bound in App's
|
|
@@ -39,7 +41,6 @@ const ICON = {
|
|
|
39
41
|
rotate: "M13.25 8A5.25 5.25 0 1 1 11.7 4.3 M13.25 2.5v2.75H10.5",
|
|
40
42
|
scale: "M2.5 8.5v4a1 1 0 0 0 1 1h4 M8.5 2.5h5v5 M13.5 2.5 7.5 8.5",
|
|
41
43
|
ik: "M2.5 13.5 6.5 9l3 2.2 4-7.7 M6.5 9h.01 M9.5 11.2h.01",
|
|
42
|
-
trail: "M2 12.5c3 0 3-9 6-9s3 9 6 9",
|
|
43
44
|
pin: "M8 14.5v-4 M5 2h6 M6.2 2v3.6L4.5 10.5h7L9.8 5.6V2",
|
|
44
45
|
blocks: "M2 3.5h7.5v3.5H2z M6.5 9h7.5v3.5H6.5z",
|
|
45
46
|
refine: "M10.5 2.5l3 3L6 13H3v-3z",
|
|
@@ -62,12 +63,10 @@ function RailIcon({ name, size = 16 }) {
|
|
|
62
63
|
|
|
63
64
|
// The gizmo's snap increments (TRANSLATE_SNAP / ROTATE_SNAP in
|
|
64
65
|
// src/scene-objects.js). They are fixed, so the value group names them.
|
|
65
|
-
const SNAP_MOVE = "5cm";
|
|
66
|
-
const SNAP_TURN = "5°";
|
|
66
|
+
const SNAP_MOVE = "5cm", SNAP_TURN = "5°";
|
|
67
67
|
|
|
68
68
|
// Editor lens range: shotsDomain.changeLens and the FOV slider take 14-90°.
|
|
69
|
-
const FOV_MIN = 14;
|
|
70
|
-
const FOV_MAX = 90;
|
|
69
|
+
const FOV_MIN = 14, FOV_MAX = 90;
|
|
71
70
|
|
|
72
71
|
// "+ Add › Character" stands the new body one metre along X per existing
|
|
73
72
|
// character, inside the same stage clamp the Content drag applies.
|
|
@@ -113,35 +112,17 @@ function MenuItem({ checked, role = "menuitemradio", className = "", children, .
|
|
|
113
112
|
);
|
|
114
113
|
}
|
|
115
114
|
|
|
116
|
-
/** The inset card's header (violet dot, shot name, lens) lives in App's
|
|
117
|
-
* `.vp-shot-preview-tag`; this region only fills in the words it shows. */
|
|
118
|
-
function ShotPreviewHeader({ name, lens }) {
|
|
119
|
-
const [host, setHost] = useState(null);
|
|
120
|
-
useLayoutEffect(() => {
|
|
121
|
-
setHost(document.querySelector(".vp-shot-preview .vp-shot-preview-tag"));
|
|
122
|
-
}, []);
|
|
123
|
-
if (!host) return null;
|
|
124
|
-
return createPortal(
|
|
125
|
-
<span className="vp-shot-preview-meta" data-testid="shot-preview-header">
|
|
126
|
-
<span className="vp-shot-preview-name">{name}</span>
|
|
127
|
-
<span className="vp-shot-preview-lens">{lens}</span>
|
|
128
|
-
</span>,
|
|
129
|
-
host,
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
115
|
export default function ViewportToolbar() {
|
|
134
116
|
const {
|
|
135
117
|
workflowMode, selectWorkflowMode, poseRefusal, gizmoMode, setGizmoMode, snapEnabled,
|
|
136
|
-
setSnapEnabled, preset, applyPreset, cameraPresetId,
|
|
118
|
+
setSnapEnabled, preset, applyPreset, cameraPresetId,
|
|
137
119
|
runStudioAction, shotAspectKey, fovDeg, shotsDomain, shot, shots, activeShot,
|
|
138
120
|
setNonce, workspaceLayout, viewMenuTriggerRef, viewMenuOpen,
|
|
139
|
-
setViewMenuOpen, viewLooksActive, gridView, setGridView,
|
|
121
|
+
setViewMenuOpen, viewLooksActive, gridView, setGridView, guideMode,
|
|
140
122
|
autoColor, setAutoColor, isCharacterSelection, partColoursChoice, embedMode,
|
|
141
123
|
agentCollapsed, addSceneObject, spawnCharacter, characters, flySpeed,
|
|
142
|
-
ikEditTool, setIkEditTool,
|
|
143
|
-
|
|
144
|
-
refineDisabledReason, previsMode, sculptView, requestSculptView,
|
|
124
|
+
ikEditTool, setIkEditTool, motion, setRangePinPartPick,
|
|
125
|
+
previsMode, sculptView, requestSculptView,
|
|
145
126
|
} = useStudioShell();
|
|
146
127
|
const menu = useOverlayMenu();
|
|
147
128
|
|
|
@@ -152,7 +133,6 @@ export default function ViewportToolbar() {
|
|
|
152
133
|
setAutoColor(next);
|
|
153
134
|
};
|
|
154
135
|
|
|
155
|
-
const refineReason = lineEditMode ? null : refineDisabledReason();
|
|
156
136
|
const tools = {
|
|
157
137
|
scene: [
|
|
158
138
|
{ key: "W", id: "move", name: ko("Move", "이동"), active: gizmoMode === "move", pick: () => setGizmoMode("move") },
|
|
@@ -161,11 +141,7 @@ export default function ViewportToolbar() {
|
|
|
161
141
|
],
|
|
162
142
|
pose: [
|
|
163
143
|
{ key: "W", id: "ik", name: ko("Pose fix (IK parts)", "포즈 수정 (IK 파츠)"), active: ikEditTool === "ik", pick: () => setIkEditTool("ik") },
|
|
164
|
-
|
|
165
|
-
key: "E", id: "trail", name: ko("Path fix (motion trail)", "경로 수정 (궤적선)"), active: ikEditTool === "trail",
|
|
166
|
-
refused: showTrails ? null : ko("Turn Trails on in Show to edit the motion path", "경로를 수정하려면 표시에서 궤적선을 켜세요"),
|
|
167
|
-
pick: () => setIkEditTool("trail"),
|
|
168
|
-
},
|
|
144
|
+
|
|
169
145
|
{
|
|
170
146
|
key: "R", id: "pin", name: ko("Pin (range pin)", "고정 (범위 고정)"), active: ikEditTool === "pin",
|
|
171
147
|
refused: motion ? null : ko("Pinning needs a motion take", "고정하려면 모션 테이크가 필요해요"),
|
|
@@ -176,16 +152,8 @@ export default function ViewportToolbar() {
|
|
|
176
152
|
{ key: "W", id: "move", name: ko("Move camera", "카메라 이동"), active: gizmoMode === "move", pick: () => setGizmoMode("move") },
|
|
177
153
|
{ key: "E", id: "rotate", name: ko("Rotate camera", "카메라 회전"), active: gizmoMode === "rotate", pick: () => setGizmoMode("rotate") },
|
|
178
154
|
],
|
|
179
|
-
motion
|
|
180
|
-
|
|
181
|
-
key: "W", id: "blocks", name: ko("Blocks (select and move prompt blocks)", "블록 (프롬프트 블록 선택·이동)"), active: !lineEditMode,
|
|
182
|
-
pick: () => { if (lineEditMode) exitLineEditMode(); },
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
key: "E", id: "refine", name: ko("Refine (edit the path line)", "다듬기 (경로선 편집)"), active: lineEditMode,
|
|
186
|
-
refused: refineReason, pick: () => { if (!lineEditMode) enterRefineMode(); },
|
|
187
|
-
},
|
|
188
|
-
],
|
|
155
|
+
// Motion is compiled by the agent (motion.compile); the department has no tools of its own.
|
|
156
|
+
motion: [],
|
|
189
157
|
// Sculpt mode's W/E/R swing the turntable camera to a reference view.
|
|
190
158
|
sculpt: [
|
|
191
159
|
{ key: "W", id: "front", name: ko("Front view", "정면 보기"), active: sculptView?.view === "front", pick: () => requestSculptView("front") },
|
|
@@ -216,33 +184,6 @@ export default function ViewportToolbar() {
|
|
|
216
184
|
<span className="vp-value-part"><RailIcon name="grid" size={14} />{SNAP_MOVE}</span>
|
|
217
185
|
<span className="vp-value-part"><RailIcon name="angle" size={14} />{SNAP_TURN}</span>
|
|
218
186
|
</button>
|
|
219
|
-
) : workflowMode === "pose" ? (
|
|
220
|
-
<div className="vp-menu-wrap" data-vp-menu="influence">
|
|
221
|
-
<button
|
|
222
|
-
type="button"
|
|
223
|
-
className="vp-value"
|
|
224
|
-
aria-haspopup="dialog"
|
|
225
|
-
aria-expanded={menu.open === "influence"}
|
|
226
|
-
title={ko("Influence range — how far an edit blends into nearby frames", "영향 범위 — 수정이 주변 프레임에 섞이는 길이")}
|
|
227
|
-
onClick={() => menu.toggle("influence")}
|
|
228
|
-
>
|
|
229
|
-
{trimNumber(trailFalloffS)}s
|
|
230
|
-
</button>
|
|
231
|
-
{menu.open === "influence" && (
|
|
232
|
-
<div className="vp-menu vp-slider-popover" role="dialog" aria-label={ko("Influence range", "영향 범위")}>
|
|
233
|
-
<input
|
|
234
|
-
type="range"
|
|
235
|
-
min={0.1}
|
|
236
|
-
max={2}
|
|
237
|
-
step={0.1}
|
|
238
|
-
value={trailFalloffS}
|
|
239
|
-
aria-label={ko("Influence range", "영향 범위")}
|
|
240
|
-
onChange={(event) => setTrailFalloffS(Number(event.target.value))}
|
|
241
|
-
/>
|
|
242
|
-
<output>{trimNumber(trailFalloffS)}s</output>
|
|
243
|
-
</div>
|
|
244
|
-
)}
|
|
245
|
-
</div>
|
|
246
187
|
) : workflowMode === "camera" ? (
|
|
247
188
|
<>
|
|
248
189
|
<div className="vp-menu-wrap" data-vp-menu="lens">
|
|
@@ -264,7 +205,6 @@ export default function ViewportToolbar() {
|
|
|
264
205
|
key={mm}
|
|
265
206
|
data-lens={mm}
|
|
266
207
|
checked={shot.focalMm === mm}
|
|
267
|
-
disabled={i2vMotionCameraLocked}
|
|
268
208
|
onClick={() => { shotsDomain.changeLens(fov); menu.close(); }}
|
|
269
209
|
>
|
|
270
210
|
{mm}mm
|
|
@@ -278,7 +218,6 @@ export default function ViewportToolbar() {
|
|
|
278
218
|
max={FOV_MAX}
|
|
279
219
|
step="1"
|
|
280
220
|
value={fovDeg}
|
|
281
|
-
disabled={i2vMotionCameraLocked}
|
|
282
221
|
onChange={(event) => shotsDomain.changeLens(Number(event.target.value))}
|
|
283
222
|
/>
|
|
284
223
|
<output>{Math.round(fovDeg)}°</output>
|
|
@@ -476,7 +415,6 @@ export default function ViewportToolbar() {
|
|
|
476
415
|
<select
|
|
477
416
|
aria-label={ko("Camera preset", "카메라 프리셋")}
|
|
478
417
|
value={cameraPresetId ?? ""}
|
|
479
|
-
disabled={i2vMotionCameraLocked}
|
|
480
418
|
onChange={(event) => {
|
|
481
419
|
const id = event.target.value;
|
|
482
420
|
if (!id) { runStudioAction("stage.setFilmback", { cameraPresetId: null }); return; }
|
|
@@ -515,20 +453,13 @@ export default function ViewportToolbar() {
|
|
|
515
453
|
onClick={() => menu.toggle("shading")}
|
|
516
454
|
>
|
|
517
455
|
<RailIcon name="shading" />
|
|
518
|
-
<span className="vp-label">{
|
|
456
|
+
<span className="vp-label">{ko("Clay Lit", "클레이 조명")}</span>
|
|
519
457
|
</button>
|
|
520
458
|
{menu.open === "shading" && (
|
|
521
459
|
<div className="vp-menu" role="menu" aria-label={ko("Shading", "셰이딩")}>
|
|
522
460
|
<MenuItem checked={!autoColor} onClick={() => { setAutoColorOn(false); menu.close(); }}>
|
|
523
461
|
{ko("Clay Lit", "클레이 조명")}
|
|
524
462
|
</MenuItem>
|
|
525
|
-
<MenuItem
|
|
526
|
-
checked={autoColor}
|
|
527
|
-
title={ko("Flat, distinct colour per object — captures include them while on", "오브젝트별 평면 구분 색 — 켜둔 동안 캡처에도 포함됩니다")}
|
|
528
|
-
onClick={() => { setAutoColorOn(true); menu.close(); }}
|
|
529
|
-
>
|
|
530
|
-
{ko("Auto Color", "자동 색")}
|
|
531
|
-
</MenuItem>
|
|
532
463
|
</div>
|
|
533
464
|
)}
|
|
534
465
|
</div>
|
|
@@ -590,18 +521,17 @@ export default function ViewportToolbar() {
|
|
|
590
521
|
<button
|
|
591
522
|
type="button"
|
|
592
523
|
role="menuitemcheckbox"
|
|
593
|
-
className={"view-menu-item
|
|
594
|
-
aria-checked={
|
|
595
|
-
aria-pressed={
|
|
596
|
-
title={ko("
|
|
597
|
-
onClick={() => {
|
|
598
|
-
if (showTrails && ikEditTool === "trail") setIkEditTool("ik");
|
|
599
|
-
setShowTrails(!showTrails);
|
|
600
|
-
}}
|
|
524
|
+
className={"view-menu-item vp-guide-cycle" + (guideMode === "off" ? "" : " active")}
|
|
525
|
+
aria-checked={guideMode !== "off"}
|
|
526
|
+
aria-pressed={guideMode !== "off"}
|
|
527
|
+
title={ko(GUIDE_LABELS[guideMode].en, GUIDE_LABELS[guideMode].ko) + ko(" · click to cycle", " · 클릭으로 전환")}
|
|
528
|
+
onClick={() => runStudioAction("view.setGuideMode", { mode: nextGuideMode(guideMode) })}
|
|
601
529
|
>
|
|
602
|
-
<span className="view-menu-mark" aria-hidden="true">{
|
|
603
|
-
{ko("
|
|
530
|
+
<span className="view-menu-mark" aria-hidden="true">{guideMode !== "off" ? "✓" : ""}</span>
|
|
531
|
+
{ko("Composition guides", "구도 가이드")}
|
|
532
|
+
<small>{ko(GUIDE_LABELS[guideMode].en, GUIDE_LABELS[guideMode].ko)}</small>
|
|
604
533
|
</button>
|
|
534
|
+
<GhostsMenuGroup />
|
|
605
535
|
{/* Part colours repaint a BODY, so the section only exists
|
|
606
536
|
while a character is selected (R2). */}
|
|
607
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 {
|
|
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
|
-
|
|
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:
|
|
252
|
-
min-width:
|
|
253
|
-
max-width:
|
|
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 +
|
|
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)
|
|
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
|
-
|
|
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:
|
|
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);
|
package/src/shell/viewport.css
CHANGED
|
@@ -32,6 +32,18 @@
|
|
|
32
32
|
color: var(--text-1);
|
|
33
33
|
}
|
|
34
34
|
.app[data-embed-mode] .viewport-titlebar { display: none; }
|
|
35
|
+
.app[data-embed-mode] .vp-embed-guide {
|
|
36
|
+
position: absolute;
|
|
37
|
+
top: var(--sp-1);
|
|
38
|
+
right: var(--sp-1);
|
|
39
|
+
z-index: 6;
|
|
40
|
+
padding: var(--sp-1);
|
|
41
|
+
border-radius: var(--r-2);
|
|
42
|
+
background: var(--surface-panel);
|
|
43
|
+
color: var(--text-2);
|
|
44
|
+
}
|
|
45
|
+
.app[data-embed-mode] .vp-embed-guide:hover,
|
|
46
|
+
.app[data-embed-mode] .vp-embed-guide.on { color: var(--select); }
|
|
35
47
|
|
|
36
48
|
.viewport-titlebar button { font-family: inherit; }
|
|
37
49
|
.viewport-titlebar button:focus-visible {
|
package/src/shot-authoring.js
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
|
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
|
|
69
|
-
*
|
|
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;
|