@dailies-studio/shot-editor 0.1.0 → 0.2.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/dist/.vite/manifest.json +382 -0
- package/dist/assets/AgentPanel-CQejLbiX.js +2 -0
- package/dist/assets/AgentPanel-DJEphah0.css +1 -0
- package/dist/assets/AgentQuestionDialog-BqkD0kXF.js +1 -0
- package/dist/assets/CodeStudio-Dv4ihHpz.js +23 -0
- package/dist/assets/CommentsPanel-B4yhhT1T.js +1 -0
- package/dist/assets/ComponentLibraryRail-Ch_dsAru.js +1 -0
- package/dist/assets/ComponentStage-BRhRotyH.js +1 -0
- package/dist/assets/CurvePane-BjFVabKX.css +1 -0
- package/dist/assets/CurvePane-R22WzllJ.js +1 -0
- package/dist/assets/ExportDialog-CWLQWTmG.js +2 -0
- package/dist/assets/FontPicker-DWKaYL7F.js +1 -0
- package/dist/assets/FontPicker-v0IOIArM.css +1 -0
- package/dist/assets/GenerateDrawer-Bh3SqDKt.js +2 -0
- package/dist/assets/InsertDrawer-Ce1fod1L.js +1 -0
- package/dist/assets/LibraryBrowser-D9sEGz5w.js +2 -0
- package/dist/assets/MakeItYoursSection-CMO4319_.js +2 -0
- package/dist/assets/MaterialGraphCanvas-BFzl4wWR.js +23 -0
- package/dist/assets/MaterialGraphCanvas-BIUD59ik.css +1 -0
- package/dist/assets/MaterialWorkspace-CqTWqaRA.js +14 -0
- package/dist/assets/PreferencesDialog-CBf9_OoD.js +1 -0
- package/dist/assets/PresetsSection-CUEaoCVU.js +1 -0
- package/dist/assets/SoundHistory-BeS8EW1h.js +1 -0
- package/dist/assets/SoundMode-BmcZru3i.js +3 -0
- package/dist/assets/StockSounds-DdAUGRYK.js +1 -0
- package/dist/assets/TemplateFieldSection-CaeXpLFo.js +1 -0
- package/dist/assets/VersionHistoryPanel-CxG6XhNP.js +1 -0
- package/dist/assets/board-B88EPuLO.css +1 -0
- package/dist/assets/board-CL-he7SL.js +3 -0
- package/dist/assets/components-0oOSPN0l.js +1 -0
- package/dist/assets/googleFontRanges-gp32wJMo.js +1 -0
- package/dist/assets/googleFonts-BNon6M7X.js +1 -0
- package/dist/assets/iconsAndAliases-DL7gXP5j.js +1863 -0
- package/dist/assets/index-4F5NQmI8.css +1 -0
- package/dist/assets/index-BGHQGV5z.js +117 -0
- package/dist/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/assets/libraryModel-CpIwfFha.js +1 -0
- package/dist/assets/lucide-6iK64tTB.js +9319 -0
- package/dist/assets/motionStamp-CH-Hew4E.js +1 -0
- package/dist/assets/takeMeasure-Tdg0TxEi.js +1 -0
- package/dist/assets/webmcp-BsB9gxWC.js +2 -0
- package/dist/index.html +34 -3
- package/package.json +12 -9
- package/src/addFamilies.ts +66 -0
- package/src/api.ts +1631 -55
- package/src/app/App.tsx +977 -198
- package/src/app/lazyPanel.tsx +137 -0
- package/src/app/lazySurfaces.tsx +203 -0
- package/src/audio/index.tsx +41 -10
- package/src/audio/meter.ts +485 -0
- package/src/audio/meterMath.ts +273 -0
- package/src/audio/meterStore.ts +155 -0
- package/src/audio/offlineMix.ts +289 -0
- package/src/audio/preview.ts +928 -118
- package/src/bridge.ts +15 -5
- package/src/bridgeTypes.ts +1611 -36
- package/src/channels.ts +17 -32
- package/src/fonts/googleFonts.ts +4 -0
- package/src/hostApi.ts +174 -0
- package/src/icons.tsx +770 -0
- package/src/layerWords.ts +61 -0
- package/src/main.tsx +56 -4
- package/src/panels/ResizeHandle.tsx +33 -43
- package/src/panels/agent/AgentDots.tsx +36 -0
- package/src/panels/agent/AgentPanel.tsx +119 -43
- package/src/panels/agent/AgentQuestionDialog.tsx +202 -0
- package/src/panels/agent/agent.css +113 -97
- package/src/panels/agent/agentGate.ts +35 -0
- package/src/panels/code/CodeDefaultsPanel.tsx +345 -0
- package/src/panels/code/CodeStudio.tsx +373 -0
- package/src/panels/code/FileTree.tsx +265 -0
- package/src/panels/code/codeBufferGuard.ts +52 -0
- package/src/panels/code/codeParts.tsx +321 -0
- package/src/panels/comments/CommentComposer.tsx +239 -0
- package/src/panels/comments/CommentThread.tsx +346 -0
- package/src/panels/comments/CommentsPanel.tsx +336 -0
- package/src/panels/comments/InboxButton.tsx +131 -0
- package/src/panels/comments/MentionMenu.tsx +98 -0
- package/src/panels/comments/parts.tsx +171 -0
- package/src/panels/export/ExportDialog.tsx +919 -96
- package/src/panels/export/ExportScrim.tsx +57 -0
- package/src/panels/files/AssetsTab.tsx +656 -0
- package/src/panels/files/FilePanel.tsx +1466 -216
- package/src/panels/files/LayerMarks.tsx +40 -0
- package/src/panels/files/LeftColumn.tsx +37 -0
- package/src/panels/files/McpSection.tsx +690 -47
- package/src/panels/files/MissingAssetsNotice.tsx +60 -0
- package/src/panels/files/assetDrag.ts +79 -0
- package/src/panels/files/resourceParts.tsx +255 -0
- package/src/panels/fonts/FontPicker.tsx +762 -0
- package/src/panels/fonts/faceCache.ts +207 -0
- package/src/panels/fonts/fontPicker.css +271 -0
- package/src/panels/fonts/pickerModel.ts +265 -0
- package/src/panels/fonts/pickerRequest.ts +46 -0
- package/src/panels/header/AccountAvatar.tsx +76 -0
- package/src/panels/header/AgentChip.tsx +77 -0
- package/src/panels/header/AppMenu.tsx +213 -0
- package/src/panels/header/Header.tsx +564 -84
- package/src/panels/header/HistoryControls.tsx +31 -5
- package/src/panels/header/PresenceStack.tsx +329 -0
- package/src/panels/header/ProjectTitle.tsx +232 -0
- package/src/panels/header/ShareButton.tsx +59 -0
- package/src/panels/header/StatusBadges.tsx +358 -27
- package/src/panels/header/SyncDeletedDialog.tsx +88 -0
- package/src/panels/header/ZoomControls.tsx +46 -15
- package/src/panels/header/agentHandoff.ts +52 -0
- package/src/panels/header/leave.ts +26 -0
- package/src/panels/help/HelpSection.tsx +189 -163
- package/src/panels/insert/InsertDrawer.tsx +723 -0
- package/src/panels/insert/iconSet.ts +109 -0
- package/src/panels/inspector/ExposeDot.tsx +117 -0
- package/src/panels/inspector/FramingRows.tsx +314 -44
- package/src/panels/inspector/InspectorFooter.tsx +91 -0
- package/src/panels/inspector/InspectorHead.tsx +425 -0
- package/src/panels/inspector/InspectorPanel.tsx +408 -124
- package/src/panels/inspector/KeyframeDot.tsx +373 -0
- package/src/panels/inspector/KeyframeSection.tsx +257 -0
- package/src/panels/inspector/MarkerSection.tsx +55 -11
- package/src/panels/inspector/ParamRow.tsx +84 -53
- package/src/panels/inspector/RightColumn.tsx +152 -0
- package/src/panels/inspector/TimeSection.tsx +866 -0
- package/src/panels/inspector/animate/EaseControl.tsx +244 -0
- package/src/panels/inspector/animate/PresetsSection.tsx +135 -0
- package/src/panels/inspector/animate/ShotSection.tsx +562 -48
- package/src/panels/inspector/design/AlignRow.tsx +95 -31
- package/src/panels/inspector/design/AppearanceSection.tsx +118 -9
- package/src/panels/inspector/design/ClonerSection.tsx +323 -62
- package/src/panels/inspector/design/ComponentSection.tsx +50 -43
- package/src/panels/inspector/design/CornerSection.tsx +45 -14
- package/src/panels/inspector/design/DefinitionProps.tsx +315 -0
- package/src/panels/inspector/design/DefinitionSection.tsx +136 -0
- package/src/panels/inspector/design/DeviceSection.tsx +210 -0
- package/src/panels/inspector/design/FillSection.tsx +83 -51
- package/src/panels/inspector/design/FontField.tsx +196 -0
- package/src/panels/inspector/design/HtmlSection.tsx +23 -12
- package/src/panels/inspector/design/InstanceSection.tsx +373 -154
- package/src/panels/inspector/design/MaskSection.tsx +84 -0
- package/src/panels/inspector/design/MaterialSection.tsx +177 -0
- package/src/panels/inspector/design/MediaSection.tsx +273 -120
- package/src/panels/inspector/design/MeshSection.tsx +910 -82
- package/src/panels/inspector/design/PaintRows.tsx +550 -0
- package/src/panels/inspector/design/PlateStyleSection.tsx +177 -0
- package/src/panels/inspector/design/ShadowSection.tsx +221 -48
- package/src/panels/inspector/design/SplineFollowSection.tsx +235 -0
- package/src/panels/inspector/design/StrokeSection.tsx +228 -43
- package/src/panels/inspector/design/TemplateFieldSection.tsx +57 -0
- package/src/panels/inspector/design/TransformSection.tsx +244 -50
- package/src/panels/inspector/design/TypographySection.tsx +679 -110
- package/src/panels/inspector/layout.ts +295 -0
- package/src/panels/inspector/propValue.ts +199 -0
- package/src/panels/inspector/scene/CameraSection.tsx +232 -22
- package/src/panels/inspector/scene/EffectsSection.tsx +722 -71
- package/src/panels/inspector/scene/MakeItYoursSection.tsx +180 -0
- package/src/panels/inspector/scene/SceneDocSection.tsx +191 -0
- package/src/panels/inspector/scene/SceneSection.tsx +219 -44
- package/src/panels/inspector/scene/TransitionSection.tsx +523 -72
- package/src/panels/inspector/storyboard/StoryboardReferenceSection.tsx +593 -0
- package/src/panels/inspector/storyboard/VideoStill.tsx +120 -0
- package/src/panels/inspector/timeModel.ts +190 -0
- package/src/panels/inspector/useDocWrite.ts +438 -146
- package/src/panels/library/LibraryBrowser.tsx +435 -0
- package/src/panels/library/LibraryGrid.tsx +190 -0
- package/src/panels/library/LibraryPreviewPanel.tsx +349 -0
- package/src/panels/library/LibraryRail.tsx +84 -0
- package/src/panels/library/LibrarySoundPanel.tsx +293 -0
- package/src/panels/library/SoundHistory.tsx +245 -0
- package/src/panels/library/StockSounds.tsx +390 -0
- package/src/panels/library/libraryModel.ts +147 -0
- package/src/panels/library/stockSearch.ts +77 -0
- package/src/panels/maskMarks.tsx +117 -0
- package/src/panels/material/MaterialCommentNode.tsx +54 -0
- package/src/panels/material/MaterialGraphCanvas.tsx +861 -0
- package/src/panels/material/MaterialGraphMenu.tsx +45 -0
- package/src/panels/material/MaterialGroupNode.tsx +56 -0
- package/src/panels/material/MaterialLibrary.tsx +253 -0
- package/src/panels/material/MaterialNode.tsx +453 -0
- package/src/panels/material/MaterialNodePalette.tsx +349 -0
- package/src/panels/material/MaterialParameterControls.tsx +525 -0
- package/src/panels/material/MaterialRerouteNode.tsx +42 -0
- package/src/panels/material/MaterialWorkspace.tsx +501 -0
- package/src/panels/material/NodePreview.tsx +70 -0
- package/src/panels/material/flowModel.ts +441 -0
- package/src/panels/material/parameterValues.ts +231 -0
- package/src/panels/material/previewScheduler.ts +235 -0
- package/src/panels/material/reactFlow.css +6 -0
- package/src/panels/material/socketGlyph.ts +85 -0
- package/src/panels/material/viewportMemory.ts +58 -0
- package/src/panels/preferences/PreferencesDialog.tsx +215 -0
- package/src/panels/share/ShareComponentDialog.tsx +247 -0
- package/src/panels/stage/StageMenu.tsx +35 -5
- package/src/panels/stage/StagePanel.tsx +338 -23
- package/src/panels/stage/cellSlots.tsx +70 -0
- package/src/panels/storyboard/BoardCanvas.tsx +739 -0
- package/src/panels/storyboard/BoardCursors.tsx +158 -0
- package/src/panels/storyboard/BoardDropDialog.tsx +161 -0
- package/src/panels/storyboard/BoardPlan.tsx +42 -0
- package/src/panels/storyboard/ComponentSheet.tsx +187 -0
- package/src/panels/storyboard/ComponentStage.tsx +235 -0
- package/src/panels/storyboard/MiniSketch.tsx +173 -0
- package/src/panels/storyboard/PartPicker.tsx +64 -0
- package/src/panels/storyboard/PlanPanel.tsx +617 -0
- package/src/panels/storyboard/ReferencePreview.tsx +217 -0
- package/src/panels/storyboard/ShotBrief.tsx +360 -0
- package/src/panels/storyboard/ShotCard.tsx +251 -0
- package/src/panels/storyboard/StagePreview.tsx +348 -0
- package/src/panels/storyboard/StillThumbs.tsx +162 -0
- package/src/panels/storyboard/StoryboardView.tsx +79 -0
- package/src/panels/storyboard/board.css +1065 -0
- package/src/panels/storyboard/board.ts +12 -0
- package/src/panels/storyboard/boardClipboard.ts +111 -0
- package/src/panels/storyboard/boardOrder.ts +68 -0
- package/src/panels/storyboard/boardRows.tsx +425 -0
- package/src/panels/storyboard/liveCap.ts +90 -0
- package/src/panels/storyboard/plan.css +295 -0
- package/src/panels/storyboard/posterCache.ts +133 -0
- package/src/panels/storyboard/shotboard/ComponentPicker.tsx +373 -0
- package/src/panels/storyboard/shotboard/ImagePicker.tsx +145 -0
- package/src/panels/storyboard/shotboard/ShotBoard.tsx +292 -0
- package/src/panels/storyboard/shotboard/SketchCanvas.tsx +443 -0
- package/src/panels/storyboard/shotboard/SketchInspector.tsx +471 -0
- package/src/panels/storyboard/shotboard/SketchItem.tsx +240 -0
- package/src/panels/storyboard/shotboard/SketchLayers.tsx +130 -0
- package/src/panels/storyboard/shotboard/SketchPlay.tsx +108 -0
- package/src/panels/storyboard/shotboard/SketchStrip.tsx +178 -0
- package/src/panels/storyboard/shotboard/SketchToolFooter.tsx +99 -0
- package/src/panels/storyboard/shotboard/sketch.css +1392 -0
- package/src/panels/storyboard/shotboard/sketchModel.ts +219 -0
- package/src/panels/storyboard/storyboardDrop.ts +164 -0
- package/src/panels/studio/ComponentLibraryRail.tsx +346 -0
- package/src/panels/studio/ComponentSidePanel.tsx +355 -0
- package/src/panels/studio/ComponentStudio.tsx +243 -0
- package/src/panels/studio/ComponentsHome.tsx +318 -0
- package/src/panels/studio/ComponentsPreview.tsx +179 -0
- package/src/panels/studio/EveryUse.tsx +244 -0
- package/src/panels/studio/ThisUsePanel.tsx +679 -0
- package/src/panels/studio/componentParts.tsx +341 -0
- package/src/panels/studio/components.ts +6 -0
- package/src/panels/studio/newCodeComponent.ts +66 -0
- package/src/panels/timeline/AudioFxButton.tsx +290 -0
- package/src/panels/timeline/AudioLane.tsx +674 -85
- package/src/panels/timeline/BlockRow.tsx +154 -85
- package/src/panels/timeline/ChannelRow.tsx +378 -129
- package/src/panels/timeline/CurvePane.tsx +508 -0
- package/src/panels/timeline/Filmstrip.tsx +361 -0
- package/src/panels/timeline/GenerateDrawer.tsx +407 -0
- package/src/panels/timeline/KeyStretch.tsx +115 -0
- package/src/panels/timeline/LifespanRow.tsx +730 -47
- package/src/panels/timeline/MarkerLane.tsx +46 -8
- package/src/panels/timeline/PlayButton.tsx +91 -0
- package/src/panels/timeline/PropertyPicker.tsx +254 -0
- package/src/panels/timeline/ShotRow.tsx +400 -0
- package/src/panels/timeline/SoundMode.tsx +1406 -0
- package/src/panels/timeline/TimelineDock.tsx +2338 -272
- package/src/panels/timeline/TransportVolume.tsx +163 -0
- package/src/panels/timeline/beatRuler.ts +74 -0
- package/src/panels/timeline/curveModel.ts +500 -0
- package/src/panels/timeline/duckUnderVoice.ts +68 -0
- package/src/panels/timeline/keyframeMenu.ts +138 -0
- package/src/panels/timeline/labelWidth.ts +49 -0
- package/src/panels/timeline/marquee.ts +155 -0
- package/src/panels/timeline/model.ts +1860 -199
- package/src/panels/timeline/snap.ts +125 -43
- package/src/panels/timeline/staggerPreview.tsx +92 -0
- package/src/panels/timeline/takeMeasure.ts +72 -0
- package/src/panels/timeline/useLive.ts +48 -0
- package/src/panels/timeline/viewport.ts +234 -0
- package/src/panels/toolbar/BackChip.tsx +116 -0
- package/src/panels/toolbar/CameraViewBar.tsx +118 -49
- package/src/panels/toolbar/CanvasBar.tsx +117 -0
- package/src/panels/toolbar/InsertButton.tsx +38 -0
- package/src/panels/toolbar/IsolationTrail.tsx +156 -0
- package/src/panels/toolbar/PanelToggles.tsx +86 -0
- package/src/panels/toolbar/ShadingBar.tsx +119 -26
- package/src/panels/toolbar/ToolDockBar.tsx +329 -80
- package/src/panels/toolbar/ToolFooter.tsx +102 -0
- package/src/panels/toolbar/ViewModeBar.tsx +247 -38
- package/src/panels/toolbar/WorkPlaneBar.tsx +94 -0
- package/src/panels/toolbar/useAddRows.tsx +326 -0
- package/src/panels/toolbar/useDismiss.ts +122 -0
- package/src/panels/versions/VersionHistoryPanel.tsx +274 -0
- package/src/panels/versions/versionModel.ts +103 -0
- package/src/panels/virtualWindow.ts +271 -0
- package/src/shotTokens.css +151 -60
- package/src/stage/FrustumGizmo.tsx +504 -84
- package/src/stage/GridPlane.tsx +225 -16
- package/src/stage/NodePreviews.tsx +628 -0
- package/src/stage/PerfHud.tsx +437 -47
- package/src/stage/SplitRenderer.tsx +816 -169
- package/src/stage/StageApp.tsx +4274 -486
- package/src/stage/StageRootBoundary.tsx +114 -0
- package/src/stage/StageTools.tsx +651 -151
- package/src/stage/TransformGizmo.tsx +696 -0
- package/src/stage/adaptivePresentation.ts +145 -0
- package/src/stage/bridgeClient.ts +2522 -41
- package/src/stage/exportWorker.ts +9 -0
- package/src/stage/feed.ts +305 -14
- package/src/stage/fontPreview.ts +176 -0
- package/src/stage/frustumGeometry.ts +319 -1
- package/src/stage/furnitureTokens.ts +33 -0
- package/src/stage/gizmoMath.ts +508 -16
- package/src/stage/gpuTimer.ts +276 -0
- package/src/stage/instanceModules.ts +194 -33
- package/src/stage/interactions/move.ts +24 -5
- package/src/stage/isolation.ts +291 -33
- package/src/stage/jsSelfProfiler.ts +325 -0
- package/src/stage/main.tsx +116 -16
- package/src/stage/modalState.ts +222 -23
- package/src/stage/moduleEpoch.ts +60 -0
- package/src/stage/motionPathStage.ts +279 -0
- package/src/stage/motionPreview.ts +74 -0
- package/src/stage/overlays/Overlays.tsx +1112 -159
- package/src/stage/overlays/Rulers.tsx +495 -0
- package/src/stage/panes.ts +159 -10
- package/src/stage/project.ts +68 -3
- package/src/stage/renderScaleController.ts +730 -0
- package/src/stage/rulers.ts +129 -0
- package/src/stage/sceneExtent.ts +75 -0
- package/src/stage/shading.ts +20 -0
- package/src/stage/splineStage.ts +632 -0
- package/src/stage/stagePerformanceTelemetry.ts +717 -0
- package/src/stage/stageTheme.ts +36 -0
- package/src/stage/stageWarmup.ts +11 -0
- package/src/stage/textAutoSize.ts +124 -0
- package/src/stage/tier1Export.ts +641 -0
- package/src/stage/tokenColor.ts +14 -9
- package/src/stage/view.ts +56 -9
- package/src/stage/workingView.ts +277 -33
- package/src/state/accountPrefs.ts +261 -0
- package/src/state/agentActions.ts +173 -15
- package/src/state/agentActivity.ts +198 -0
- package/src/state/agentQuestion.ts +239 -0
- package/src/state/bootOpen.ts +42 -0
- package/src/state/cameraVerbs.ts +139 -0
- package/src/state/clientId.ts +6 -1
- package/src/state/comments.ts +1099 -0
- package/src/state/context.tsx +19 -1
- package/src/state/editorPrefs.ts +220 -0
- package/src/state/errorReports.ts +121 -0
- package/src/state/fieldWrite.ts +161 -0
- package/src/state/fontRecents.ts +70 -0
- package/src/state/fonts.ts +656 -0
- package/src/state/graphClipboard.ts +414 -0
- package/src/state/imageThumbs.ts +216 -0
- package/src/state/insert.ts +444 -67
- package/src/state/isolationTrail.ts +92 -0
- package/src/state/keyMoves.ts +134 -0
- package/src/state/keyframeClipboard.ts +177 -0
- package/src/state/keymap.ts +1153 -117
- package/src/state/layoutPrefs.ts +272 -0
- package/src/state/layouts.ts +205 -0
- package/src/state/measureMedia.ts +167 -0
- package/src/state/menu.ts +2341 -28
- package/src/state/motionStamp.ts +7 -0
- package/src/state/panelSize.ts +375 -5
- package/src/state/pendingChanges.ts +119 -0
- package/src/state/playHold.ts +78 -0
- package/src/state/playbackPreparation.ts +562 -0
- package/src/state/posterCapture.ts +242 -0
- package/src/state/presence.ts +254 -0
- package/src/state/projectComponents.ts +160 -0
- package/src/state/renderEvents.ts +298 -18
- package/src/state/runtimeErrors.ts +46 -0
- package/src/state/selection.ts +12 -0
- package/src/state/shortcuts.ts +1606 -0
- package/src/state/sketchGuide.ts +51 -0
- package/src/state/splineRefs.ts +87 -0
- package/src/state/stageHealth.ts +259 -0
- package/src/state/stageWatchdog.ts +47 -0
- package/src/state/stillStage.ts +330 -0
- package/src/state/stillThumbs.ts +474 -0
- package/src/state/store.ts +23591 -2982
- package/src/state/storyboardModel.ts +528 -0
- package/src/state/sync.ts +1257 -0
- package/src/state/syncCache.ts +159 -0
- package/src/state/triangles.ts +13 -0
- package/src/state/types.ts +1698 -55
- package/src/state/unsavedGuard.ts +49 -0
- package/src/state/viewMode.ts +200 -0
- package/src/state/webmcp.ts +1128 -0
- package/src/state/workspace.ts +1147 -0
- package/src/styles/assets-tab.css +304 -0
- package/src/styles/canvas.css +545 -0
- package/src/styles/comments.css +1435 -0
- package/src/styles/controls.css +162 -0
- package/src/styles/dialogs.css +390 -0
- package/src/styles/insert-drawer.css +586 -0
- package/src/styles/inspector-board.css +207 -0
- package/src/styles/inspector-object.css +486 -0
- package/src/styles/inspector-shot.css +252 -0
- package/src/styles/inspector.css +360 -0
- package/src/styles/left-column.css +1628 -0
- package/src/styles/library-preview.css +575 -0
- package/src/styles/library.css +512 -0
- package/src/styles/modes/code.css +569 -0
- package/src/styles/modes/component.css +1561 -0
- package/src/styles/modes/material.css +1201 -0
- package/src/styles/modes/storyboard.css +518 -0
- package/src/styles/share-component.css +49 -0
- package/src/styles/shell.css +653 -0
- package/src/styles/shot-brief.css +360 -0
- package/src/styles/states.css +76 -0
- package/src/styles/sync.css +380 -0
- package/src/styles/timeline-graph.css +384 -0
- package/src/styles/timeline-meters.css +89 -0
- package/src/styles/timeline-rows.css +1959 -0
- package/src/styles/timeline-sound.css +1003 -0
- package/src/styles/timeline.css +754 -0
- package/src/styles/tool-footer.css +525 -0
- package/src/styles/topbar.css +886 -0
- package/src/styles/versions.css +262 -0
- package/src/styles.css +72 -2921
- package/src/tools.ts +108 -23
- package/dist/assets/index-B7notge7.css +0 -1
- package/dist/assets/index-BBE6Ta9L.js +0 -52
- package/src/panels/files/icons.tsx +0 -118
- package/src/panels/header/DocSwitcher.tsx +0 -85
- package/src/panels/header/TransportBar.tsx +0 -86
- package/src/panels/inspector/animate/BlockTiming.tsx +0 -341
- package/src/panels/inspector/animate/DuringBlocks.tsx +0 -85
- package/src/panels/inspector/animate/InOutPresets.tsx +0 -57
- package/src/panels/inspector/animate/ResolvedChannels.tsx +0 -150
- package/src/panels/inspector/animate/useBlocks.ts +0 -43
- package/src/panels/material/MaterialPicker.tsx +0 -172
- package/src/panels/timeline/SceneStrip.tsx +0 -145
- package/src/panels/toolbar/AddMenu.tsx +0 -230
- package/src/stage/MoveGizmo.tsx +0 -411
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
// WHICH SECTIONS A SUBJECT GETS, AND IN WHAT ORDER. DECLARED, NOT DERIVED.
|
|
2
|
+
//
|
|
3
|
+
// ── THE PANEL MOUNTED EVERYTHING AND LET EACH SECTION REFUSE ────────────
|
|
4
|
+
//
|
|
5
|
+
// `InspectorPanel` used to render every design section for every selection and
|
|
6
|
+
// each one gated itself: `layers.some((l) => l.kind === "cloner")` in one file,
|
|
7
|
+
// `every(isMedia)` in a second, `layers.length === 1` in three more. So the
|
|
8
|
+
// answer to "what does a text layer's inspector look like" was the ORDER OF THE
|
|
9
|
+
// JSX plus a kind predicate buried inside whichever of the sections happened to
|
|
10
|
+
// carry one, a file each. Nothing asserted it, two sections could disagree about
|
|
11
|
+
// the same selection, and a new layer kind got whatever happened to fall out.
|
|
12
|
+
//
|
|
13
|
+
// This file IS that answer, and `test/inspectorLayout.test.tsx` pins it per
|
|
14
|
+
// kind. `LAYER_LAYOUT` is a `Record` over the schema's own union — the rule
|
|
15
|
+
// `KIND_WORDS` (layerWords.ts) already follows — so a sixteenth layer kind
|
|
16
|
+
// is a COMPILE ERROR here rather than a rail that silently offers it nothing
|
|
17
|
+
// but Transform.
|
|
18
|
+
//
|
|
19
|
+
// ── KIND GATES MOVED HERE; THE REST STAYED, AND MOST OF THAT IS A CHOICE ─
|
|
20
|
+
//
|
|
21
|
+
// "Is this layer a cloner" is a question about the kind, and the table answers
|
|
22
|
+
// it once. The gates that stayed behind split in two, and only one half is
|
|
23
|
+
// out of reach.
|
|
24
|
+
//
|
|
25
|
+
// "Does this mesh wear a node graph", "is this instance's definition still
|
|
26
|
+
// there" are questions about the DOCUMENT. Nothing handed to this module can
|
|
27
|
+
// answer them, so they could not move even in principle.
|
|
28
|
+
//
|
|
29
|
+
// "Is exactly one layer selected", "is every one of them media", "which layer
|
|
30
|
+
// leads" could: `sectionsFor` is given `layers.map((l) => l.kind)`, the kinds
|
|
31
|
+
// IN SELECTION ORDER, so the count, the leader and the whole multiset are
|
|
32
|
+
// already in its argument. They stay in their sections anyway, because
|
|
33
|
+
// re-deriving them here would be a SECOND SPELLING of each section's own rule
|
|
34
|
+
// and two spellings are what drift — the sections keep the one copy and this
|
|
35
|
+
// table stays the ceiling. Every one of them is named on `sectionsFor` below,
|
|
36
|
+
// because a gate nobody wrote down is the gate the next author debugs twice.
|
|
37
|
+
import type { Layer3DKind } from "@dailies-studio/shot/doc";
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Every design section, in the order a MIXED selection renders them.
|
|
41
|
+
*
|
|
42
|
+
* The order is the order the picture is described in: where the layer is
|
|
43
|
+
* (transform, appearance), WHEN it is (time), what it IS (the per-kind block,
|
|
44
|
+
* a mesh's geometry, a device's slab, a component's definition, a cloner's
|
|
45
|
+
* arrangement, a media layer's source), what is PAINTED onto it, what its
|
|
46
|
+
* content is (type, markup), and last what it DOES over time.
|
|
47
|
+
*
|
|
48
|
+
* "Time" is the layer's LIFETIME and, for a video, the footage under it: the
|
|
49
|
+
* window, the source edges, the speed and what happens past the recording's
|
|
50
|
+
* end. It sits with transform and appearance because it is a fact about the
|
|
51
|
+
* layer, and every kind has one.
|
|
52
|
+
*
|
|
53
|
+
* "Mask" leads (gap 7, Paper page 25): a mask paints nothing of its own, so
|
|
54
|
+
* what it does to the layers in front of it is the first fact about it.
|
|
55
|
+
*
|
|
56
|
+
* "Template field" (schema v50) follows the content: whether a person who
|
|
57
|
+
* starts from this Project swaps the layer for their own is a fact about what
|
|
58
|
+
* the layer shows, so it sits after the sections that say what that is.
|
|
59
|
+
*/
|
|
60
|
+
export const SECTION_ORDER = [
|
|
61
|
+
"mask",
|
|
62
|
+
"transform",
|
|
63
|
+
"appearance",
|
|
64
|
+
"time",
|
|
65
|
+
"presets",
|
|
66
|
+
"mesh",
|
|
67
|
+
"material",
|
|
68
|
+
"device",
|
|
69
|
+
"instance",
|
|
70
|
+
"component",
|
|
71
|
+
"cloner",
|
|
72
|
+
"media",
|
|
73
|
+
"plateStyle",
|
|
74
|
+
"textFill",
|
|
75
|
+
"fill",
|
|
76
|
+
"stroke",
|
|
77
|
+
"corner",
|
|
78
|
+
"shadow",
|
|
79
|
+
"typography",
|
|
80
|
+
"html",
|
|
81
|
+
"templateField",
|
|
82
|
+
"splineFollow",
|
|
83
|
+
] as const;
|
|
84
|
+
|
|
85
|
+
export type SectionId = (typeof SECTION_ORDER)[number];
|
|
86
|
+
|
|
87
|
+
/** Where the layer is, how it reads, when it exists and how it comes and goes.
|
|
88
|
+
* Every kind has all of them: a lifetime is not optional, so neither is the
|
|
89
|
+
* section that edits it, and every kind has an opacity a Fade can stamp
|
|
90
|
+
* ("presets", the Motion section: a preset writes ordinary keys).
|
|
91
|
+
* Any kind can be a mask too, so every kind lists "mask"; the section itself
|
|
92
|
+
* is a document gate (see `sectionsFor`). */
|
|
93
|
+
const BASE = ["mask", "transform", "appearance", "time", "presets"] as const satisfies readonly SectionId[];
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The four sections that write `paint`. A kind lists only the ones its draw
|
|
97
|
+
* reads (F30): ellipse and path have no corner, line and arrow have no fill or
|
|
98
|
+
* corner, and media has no fill (see `LAYER_LAYOUT`).
|
|
99
|
+
*
|
|
100
|
+
* The six kinds that do NOT list these are refused for two overlapping reasons.
|
|
101
|
+
* `mesh`, `device` and `instance` DRAW but never take a rasterizer call — a
|
|
102
|
+
* mesh's look is its material, a device's slab colour comes from its preset
|
|
103
|
+
* (device.tsx reads `deviceSlab`, never `paint`), and an instance paints
|
|
104
|
+
* itself. `group`, `cloner` and `component` do not draw at all; they are
|
|
105
|
+
* transform, derivation and definition parents. For every one of the six a
|
|
106
|
+
* fill, a stroke, a corner radius and a shadow are document fields that move no
|
|
107
|
+
* pixel: the author edits one, sees nothing, and concludes the renderer is
|
|
108
|
+
* broken.
|
|
109
|
+
*/
|
|
110
|
+
const PAINT = ["fill", "stroke", "corner", "shadow"] as const satisfies readonly SectionId[];
|
|
111
|
+
|
|
112
|
+
/** What the layer does over time beyond its keyframes. The keyframes are the
|
|
113
|
+
* timeline dock's channel rows and the inspector's diamonds, not a section. */
|
|
114
|
+
const MOTION = ["splineFollow"] as const satisfies readonly SectionId[];
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The predefined control panel for each layer kind.
|
|
118
|
+
*
|
|
119
|
+
* MEDIA HAS NO `fill`, which is the one entry that is not simply "what the kind
|
|
120
|
+
* carries": `drawLayer` paints `paint.fill` only in the arm that is neither
|
|
121
|
+
* "mask" nor "plate" (raster.ts) and `MediaPlane` asks for exactly those two, so
|
|
122
|
+
* a photo's fill swatch writes a field and moves nothing. Stroke, corner and
|
|
123
|
+
* shadow ride the plate and the mask, so those three stay.
|
|
124
|
+
*
|
|
125
|
+
* TEXT'S "Fill" IS THE GLYPH COLOUR (`textFill`, F20), the Figma meaning. Its
|
|
126
|
+
* `paint.fill` is the plate behind the words, so that section reads
|
|
127
|
+
* "Background" over text (FillSection).
|
|
128
|
+
*
|
|
129
|
+
* ONLY TEXT, IMAGE AND VIDEO LIST `templateField`: they are `SWAP_KINDS`, the
|
|
130
|
+
* kinds `setLayerSwap` lets a template field sit on.
|
|
131
|
+
*/
|
|
132
|
+
export const LAYER_LAYOUT: Record<Layer3DKind, readonly SectionId[]> = {
|
|
133
|
+
text: [...BASE, "textFill", ...PAINT, "typography", "templateField", ...MOTION],
|
|
134
|
+
image: [...BASE, "media", "plateStyle", "stroke", "corner", "shadow", "templateField", ...MOTION],
|
|
135
|
+
video: [...BASE, "media", "plateStyle", "stroke", "corner", "shadow", "templateField", ...MOTION],
|
|
136
|
+
rect: [...BASE, ...PAINT, ...MOTION],
|
|
137
|
+
ellipse: [...BASE, "fill", "stroke", "shadow", ...MOTION],
|
|
138
|
+
line: [...BASE, "stroke", "shadow", ...MOTION],
|
|
139
|
+
arrow: [...BASE, "stroke", "shadow", ...MOTION],
|
|
140
|
+
path: [...BASE, "fill", "stroke", "shadow", ...MOTION],
|
|
141
|
+
html: [...BASE, ...PAINT, "html", ...MOTION],
|
|
142
|
+
group: [...BASE, ...MOTION],
|
|
143
|
+
device: [...BASE, "device", ...MOTION],
|
|
144
|
+
mesh: [...BASE, "mesh", "material", ...MOTION],
|
|
145
|
+
cloner: [...BASE, "cloner", ...MOTION],
|
|
146
|
+
instance: [...BASE, "instance", ...MOTION],
|
|
147
|
+
component: [...BASE, "component", ...MOTION],
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The sections a selection of these kinds renders, in `SECTION_ORDER`.
|
|
152
|
+
*
|
|
153
|
+
* THE UNION, NEVER THE INTERSECTION. A rect selected with a mesh keeps the
|
|
154
|
+
* paint block, because the rect in it still paints and `useSelectionWrite`
|
|
155
|
+
* already skips the layers a write cannot reach — a false cut hides a real
|
|
156
|
+
* control, which is strictly worse than a control that only reaches half the
|
|
157
|
+
* selection. That is also what the old self-gating stack produced (every kind
|
|
158
|
+
* gate in it was `some`, never `every`), and `inspectorPanel.test.tsx` pins it.
|
|
159
|
+
*
|
|
160
|
+
* DECLARED IS THE CEILING, NOT THE MOUNT. Nothing outside this list mounts.
|
|
161
|
+
* Something inside it can still withhold itself, on a question about the SHAPE
|
|
162
|
+
* OF THE SELECTION or about the DOCUMENT. The document ones are outside this
|
|
163
|
+
* module's reach. The shape ones are NOT — the argument is the kinds in
|
|
164
|
+
* selection order — and they are left in their sections deliberately, so each
|
|
165
|
+
* rule has exactly one spelling. Every withholding, and its exact condition:
|
|
166
|
+
*
|
|
167
|
+
* `component` ONE layer only. Each panel's rows are one
|
|
168
|
+
* `instance`, `material` definition's or one graph's own key list, so a
|
|
169
|
+
* fan-out would write keys the other subject has
|
|
170
|
+
* never heard of.
|
|
171
|
+
* `templateField` ONE layer only. A field's name says what THAT
|
|
172
|
+
* layer asks for ("Screenshot", "Headline"), so two
|
|
173
|
+
* layers under one name would be one question
|
|
174
|
+
* asked twice.
|
|
175
|
+
* `time` ONE layer only, and on its own reason rather than
|
|
176
|
+
* theirs: nothing about it is a key list. A lifetime
|
|
177
|
+
* belongs to one layer and every clip op takes one
|
|
178
|
+
* `layerId`, so fanning the edges out would need
|
|
179
|
+
* `moveLayers`' all-or-nothing posture, and "source
|
|
180
|
+
* in" has no fan-out meaning at all because the next
|
|
181
|
+
* layer's footage starts somewhere else entirely.
|
|
182
|
+
* `TimeSection`'s own header states this rule and
|
|
183
|
+
* names this list as the company it keeps, so the
|
|
184
|
+
* two are written to be read together.
|
|
185
|
+
* `plateStyle` `every(isMedia)`. A plate chip writes stroke,
|
|
186
|
+
* radius and shadows over the WHOLE selection, so a
|
|
187
|
+
* rect in it would be restyled from a shelf that
|
|
188
|
+
* never named it.
|
|
189
|
+
* `cloner`, `html` the FIRST selected layer's. A selection led in
|
|
190
|
+
* document order by anything else has no arrangement
|
|
191
|
+
* and no markup to show. (They arrive there by
|
|
192
|
+
* different routes: `html` reads through
|
|
193
|
+
* `useSelectionValue`, while `ClonerSection` takes
|
|
194
|
+
* the lead layer directly and asks about mixedness
|
|
195
|
+
* per field — an object read through that hook makes
|
|
196
|
+
* every multi-selection "Mixed" by identity.)
|
|
197
|
+
* `material` and, ON TOP of the one-layer rule, the document
|
|
198
|
+
* has to hold what it describes: a mesh with no
|
|
199
|
+
* node graph renders nothing at all.
|
|
200
|
+
* `mask` a document gate: it renders only when a selected
|
|
201
|
+
* layer is a mask or a group that holds one
|
|
202
|
+
* (`maskTargetOf`).
|
|
203
|
+
* `splineFollow` a document gate too: it renders only when the
|
|
204
|
+
* layer already follows a spline, the home holds a
|
|
205
|
+
* spline it could follow, or a cloner's spline
|
|
206
|
+
* distribution owns the path.
|
|
207
|
+
*
|
|
208
|
+
* The material gate is why "a single layer renders exactly its row of the
|
|
209
|
+
* table" is true of fourteen of the fifteen kinds and not of `mesh`: its
|
|
210
|
+
* material needs a graph behind it, which is why the fixture in
|
|
211
|
+
* `inspectorLayout.test.tsx` mints one before asserting the row.
|
|
212
|
+
* Every withholding above is pinned in that file too, so this list is asserted
|
|
213
|
+
* rather than merely written down.
|
|
214
|
+
*/
|
|
215
|
+
export function sectionsFor(kinds: Iterable<Layer3DKind>): readonly SectionId[] {
|
|
216
|
+
const wanted = new Set<SectionId>();
|
|
217
|
+
for (const kind of kinds) for (const id of LAYER_LAYOUT[kind]) wanted.add(id);
|
|
218
|
+
return SECTION_ORDER.filter((id) => wanted.has(id));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** What the rail is looking at when NOTHING is selected. The three are decided
|
|
222
|
+
* by the context bits alone: an open definition, then the entered shot, then
|
|
223
|
+
* the project the panel is a view of. */
|
|
224
|
+
export type ContainerSubject = "project" | "shot" | "definition" | "storyboard";
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Every container section, by id.
|
|
228
|
+
*
|
|
229
|
+
* `shotTransition` is the PROJECT context's shot: the shot's own rows and the
|
|
230
|
+
* seam after it, under one head. `shot` is the same shot rows alone, for the
|
|
231
|
+
* inside of a shot, where the seam is off screen. `blur` and `postprocessing`
|
|
232
|
+
* are the two halves of one `Scene3D.effects` stack, split by what the pass
|
|
233
|
+
* does to the picture (see `EffectsSection`).
|
|
234
|
+
*/
|
|
235
|
+
export type ContainerSectionId =
|
|
236
|
+
| "project"
|
|
237
|
+
| "makeItYours"
|
|
238
|
+
| "shot"
|
|
239
|
+
| "shotTransition"
|
|
240
|
+
| "camera"
|
|
241
|
+
| "blur"
|
|
242
|
+
| "postprocessing"
|
|
243
|
+
| "definition"
|
|
244
|
+
| "storyboardReference"
|
|
245
|
+
| "storyboardCut";
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* The predefined control panel for each container subject.
|
|
249
|
+
*
|
|
250
|
+
* EACH CONTEXT LEADS WITH ITSELF (Paper 27, "8 · Empty inspector"). With
|
|
251
|
+
* nothing selected the first read is the context the author is in: the
|
|
252
|
+
* Project's name, size and rate above the shots, the Shot's background and
|
|
253
|
+
* duration inside one. The camera follows in both, because it is what the
|
|
254
|
+
* stage IS (the presented shot camera above, the framed picture inside), and
|
|
255
|
+
* the other context's section after it. Blur and Postprocessing close the
|
|
256
|
+
* list, blur first because a defocus is a lens decision and a grade is not;
|
|
257
|
+
* each opens collapsed to one "None" line while it holds no pass
|
|
258
|
+
* (EffectsSection).
|
|
259
|
+
*
|
|
260
|
+
* This replaced one shared order (Camera, Project, Shot, ...) for both
|
|
261
|
+
* contexts. That order put the camera's numbers first in a panel whose
|
|
262
|
+
* subject was the Project or the Shot, so the empty inspector never said
|
|
263
|
+
* where the author was.
|
|
264
|
+
*
|
|
265
|
+
* Camera, Blur and Postprocessing used to sit out the project context on the
|
|
266
|
+
* claim that nobody could judge them there. That stopped being true: the stage
|
|
267
|
+
* there is the presented shot camera, `writeCamera` and `writeScene` both
|
|
268
|
+
* resolve the shot from the playhead, and a camera drag on the stage was
|
|
269
|
+
* already allowed. So the rail now offers what the stage already did.
|
|
270
|
+
*
|
|
271
|
+
* WHERE THE TWO DIFFER IS THE SEAM. PROJECT holds `shotTransition`, because a
|
|
272
|
+
* transition is a property of the join between two shots and that join is
|
|
273
|
+
* drawn there: the shot row puts a diamond on every cut. SHOT holds plain
|
|
274
|
+
* `shot`, because inside one shot the strip is gone and the shot after it is
|
|
275
|
+
* off screen, so the one thing an author cannot see is the join a transition
|
|
276
|
+
* describes. DEFINITION is the open component's own panel; the scene sections
|
|
277
|
+
* there would describe a scene the stage is not rendering.
|
|
278
|
+
*
|
|
279
|
+
* MAKE IT YOURS comes second in both Studio contexts, right after the context
|
|
280
|
+
* itself: in a Project started from a template, swapping its fields for one's
|
|
281
|
+
* own is the first work there is. It is a DATA gate, in the spirit of the
|
|
282
|
+
* layer withholdings: it renders only while `swapFieldsOf` lists a field.
|
|
283
|
+
*/
|
|
284
|
+
export const CONTAINER_LAYOUT: Record<ContainerSubject, readonly ContainerSectionId[]> = {
|
|
285
|
+
project: ["project", "makeItYours", "shotTransition", "camera", "blur", "postprocessing"],
|
|
286
|
+
shot: ["shot", "makeItYours", "camera", "project", "blur", "postprocessing"],
|
|
287
|
+
definition: ["definition"],
|
|
288
|
+
// STORYBOARD is the board's own panel. Each section gates on WHAT the
|
|
289
|
+
// board's selection points at (one card, one cut), a data question
|
|
290
|
+
// in the spirit of the layer withholdings above, so exactly one of them
|
|
291
|
+
// renders at a time. With nothing of that kind selected the right column
|
|
292
|
+
// holds no inspector (`boardRightPanel`), so there is no Doc or Part section
|
|
293
|
+
// any more.
|
|
294
|
+
storyboard: ["storyboardReference", "storyboardCut"],
|
|
295
|
+
};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// THE ONE CONVERSION between what a prop row's control hands back and what the
|
|
2
|
+
// document may hold, for every ControlSpec row in the chrome: a placed code
|
|
3
|
+
// component's props, a Studio-made component's overrides and published props,
|
|
4
|
+
// a code component's defaults, and one use of either.
|
|
5
|
+
//
|
|
6
|
+
// ── WHY THE CONTRACT'S `coerceValue` AND NOT A CHECK OF ITS OWN ─────────
|
|
7
|
+
//
|
|
8
|
+
// Each surface used to run its own `asValue`, which took any string, any
|
|
9
|
+
// boolean and any short number list and refused every object. So the curve and
|
|
10
|
+
// gradient editors, which hand back the decoded VALUE OBJECT, ended every edit
|
|
11
|
+
// in an error and their props could not be changed at all, while a colour box
|
|
12
|
+
// stored "banana" and an enum stored an option the contract no longer has.
|
|
13
|
+
// `coerceValue` is the contract's own answer: it encodes a composite to its
|
|
14
|
+
// canonical JSON, checks enum membership and tuple shapes, and ends at the
|
|
15
|
+
// engine's value-shape gate (finite numbers, `#rrggbb[aa]` colours, unit
|
|
16
|
+
// quaternions), the gate the save itself runs.
|
|
17
|
+
//
|
|
18
|
+
// ── NULL IS "NO ASSET", NOT "NOT A VALUE" ───────────────────────────────
|
|
19
|
+
//
|
|
20
|
+
// An asset control's "None" (and an emptied id field) hands back null, which no
|
|
21
|
+
// document field can hold: an asset prop with no asset is a prop that stores
|
|
22
|
+
// nothing and falls back to its default. So "None" CLEARS the row when that
|
|
23
|
+
// fallback is itself no asset, and is refused with the reason when the default
|
|
24
|
+
// names one, rather than storing a value that would read back as the default's
|
|
25
|
+
// asset and look like the press had been ignored.
|
|
26
|
+
import { clampedStoredValue, coerceStoredValue, controlLabel, rangeWordsOf } from "@dailies-studio/contract";
|
|
27
|
+
import type { Contract, ControlSpec } from "@dailies-studio/contract";
|
|
28
|
+
import type { Value } from "@dailies-studio/engine";
|
|
29
|
+
import { exposedSpecOf, toTrackHex } from "@dailies-studio/shot/doc";
|
|
30
|
+
import { mimeForPath } from "@dailies-studio/shot/mime";
|
|
31
|
+
import type { ComponentDef3D, Doc3D, ExposedProp3D, ShotAssetKind } from "@dailies-studio/shot/doc";
|
|
32
|
+
import type { PropControlAsset } from "@dailies-studio/ui";
|
|
33
|
+
import { fileNameOf } from "../files/resourceParts.js";
|
|
34
|
+
|
|
35
|
+
/** The engine Value a control's value is stored as, or null when it cannot be
|
|
36
|
+
* one (the document would refuse it). */
|
|
37
|
+
export function coercePropValue(spec: ControlSpec, raw: unknown): Value | null {
|
|
38
|
+
const out = coerceStoredValue(spec, raw);
|
|
39
|
+
return out.ok ? out.value : null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** What a prop row does with a value its control handed back. */
|
|
43
|
+
export type PropEdit =
|
|
44
|
+
| { kind: "set"; value: Value }
|
|
45
|
+
/** Store nothing: the row falls back to its default (an asset's "None"
|
|
46
|
+
* over a default that names no asset). */
|
|
47
|
+
| { kind: "clear" }
|
|
48
|
+
| { kind: "refused"; reason: string };
|
|
49
|
+
|
|
50
|
+
/** No asset: what an asset control's "None" and an emptied id field commit. */
|
|
51
|
+
function isNoAsset(value: unknown): boolean {
|
|
52
|
+
return value === null || value === undefined || value === "";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** The row's words for a refusal, read defensively: a hand-built spec may
|
|
56
|
+
* carry no key at all. */
|
|
57
|
+
function wordsOf(spec: ControlSpec): string {
|
|
58
|
+
const key = typeof spec.key === "string" ? spec.key : "";
|
|
59
|
+
return controlLabel(typeof spec.label === "string" ? { key, label: spec.label } : { key }) || "This prop";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The edit a row makes for `raw`. `fallback` is what the row shows when it
|
|
64
|
+
* stores nothing (the contract default, the master's value), which decides
|
|
65
|
+
* whether an asset's "None" can be kept by clearing.
|
|
66
|
+
*/
|
|
67
|
+
export function propEditOf(spec: ControlSpec, raw: unknown, fallback: unknown): PropEdit {
|
|
68
|
+
const label = wordsOf(spec);
|
|
69
|
+
if (spec.kind === "asset" && isNoAsset(raw)) {
|
|
70
|
+
return isNoAsset(fallback)
|
|
71
|
+
? { kind: "clear" }
|
|
72
|
+
: { kind: "refused", reason: `${label} cannot be set to no asset here: its default names one. Pick another asset instead.` };
|
|
73
|
+
}
|
|
74
|
+
const out = coerceStoredValue(spec, raw);
|
|
75
|
+
return out.ok ? { kind: "set", value: out.value } : { kind: "refused", reason: `${label} cannot hold that value (${out.error}).` };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* A stored number or vector outside its spec's range, which its field cannot
|
|
80
|
+
* show truthfully (the slider sits at the end, the box shows a number the
|
|
81
|
+
* field would never commit): a component narrowed the range after the value
|
|
82
|
+
* was set, or a hand edit put it there. The row's warning, and the nearest
|
|
83
|
+
* value inside (`clampedStoredValue`) its "Bring inside" stores. Null when
|
|
84
|
+
* the value is inside, or the spec has no range.
|
|
85
|
+
*/
|
|
86
|
+
export function outsideRangeOf(
|
|
87
|
+
spec: ControlSpec,
|
|
88
|
+
value: Value | undefined,
|
|
89
|
+
): { words: string; title: string; inside: Value } | null {
|
|
90
|
+
if (value === undefined || (spec.kind !== "number" && spec.kind !== "vec2" && spec.kind !== "vec3")) return null;
|
|
91
|
+
const inside = clampedStoredValue(spec, value);
|
|
92
|
+
const range = rangeWordsOf(spec);
|
|
93
|
+
if (inside === value || range === null) return null;
|
|
94
|
+
const shown = (v: Value): string => (Array.isArray(v) ? v.join(", ") : String(v));
|
|
95
|
+
const label = wordsOf(spec);
|
|
96
|
+
return {
|
|
97
|
+
words: `${label} is ${shown(value)}, outside its range of ${range}.`,
|
|
98
|
+
title: `Set ${label} to ${shown(inside)}, the nearest value inside its range`,
|
|
99
|
+
inside,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The value as the row's control should be handed it. A colour is read in any
|
|
105
|
+
* spelling a layer holds (a paint's `rgba(30,215,96,0.18)`, a short `#fff`) and
|
|
106
|
+
* shown as the hex the colour field reads and writes, the respelling the
|
|
107
|
+
* keyframe seam makes (`toTrackHex`); one it cannot read is shown as it is.
|
|
108
|
+
*/
|
|
109
|
+
export function shownPropValue(spec: ControlSpec, value: unknown): unknown {
|
|
110
|
+
if (spec.kind === "color" && typeof value === "string") return toTrackHex(value) ?? value;
|
|
111
|
+
return value;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* What a prop row shows while it follows its master (it stores and tries
|
|
116
|
+
* nothing of its own): the MASTER'S VALUE, what an un-overridden placement
|
|
117
|
+
* draws (`masterValueOf`, `exposedMasterValue`), whenever the row's control
|
|
118
|
+
* can hold it. Else the spec's default, a valid typed value: a published
|
|
119
|
+
* prop's master falls back to its stored `default` where the definition draws
|
|
120
|
+
* nothing, and that can be the blank an old `expose_prop` minted.
|
|
121
|
+
*
|
|
122
|
+
* Not the spec's default first: `exposedSpecOf` takes the published `default`
|
|
123
|
+
* as its own, and that one drifts from the layer once the published field is
|
|
124
|
+
* edited anywhere but the props panel, so every row showed a value nothing on
|
|
125
|
+
* screen had.
|
|
126
|
+
*/
|
|
127
|
+
export function masterRowValue(spec: ControlSpec, master: unknown): unknown {
|
|
128
|
+
const typed = "default" in spec ? spec.default : undefined;
|
|
129
|
+
if (master === undefined) return typed;
|
|
130
|
+
return coercePropValue(spec, shownPropValue(spec, master)) !== null ? master : (typed ?? master);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** A spec PropControl draws as one box per part (a vec2, a vec3, a
|
|
134
|
+
* quaternion's Euler X, Y and Z), whatever value it holds. A verb on the
|
|
135
|
+
* whole track (the expose pin) sits once in such a row's label column, where
|
|
136
|
+
* a box's accessory would repeat in every part and crowd the first. */
|
|
137
|
+
export function isVectorSpec(spec: ControlSpec): boolean {
|
|
138
|
+
return spec.kind === "vec2" || spec.kind === "vec3" || spec.kind === "quaternion";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** An exposed prop's row: its control, and whether anything in reach could
|
|
142
|
+
* describe one. */
|
|
143
|
+
export interface ExposedRow {
|
|
144
|
+
spec: ControlSpec;
|
|
145
|
+
/** The target takes `#rrggbb` only, so the colour field offers no alpha. */
|
|
146
|
+
opaqueColor: boolean;
|
|
147
|
+
/** Nothing describes the control (a kind this editor does not know, an enum
|
|
148
|
+
* or an asset the record cannot carry the options or kind of): the row is
|
|
149
|
+
* read-only, its control saying what it can ("Unknown kind: …", "No
|
|
150
|
+
* options"), where it used to be a bare badge. */
|
|
151
|
+
undescribed: boolean;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* The row for one exposed prop of a definition, from what the prop drives
|
|
156
|
+
* (`exposedSpecOf`: its target's table row, contract spec or graph parameter),
|
|
157
|
+
* so the definition's own panel, an instance's override rows and one use's
|
|
158
|
+
* panel draw the same bounded, typed control for it.
|
|
159
|
+
*/
|
|
160
|
+
export function exposedRowOf(
|
|
161
|
+
prop: ExposedProp3D,
|
|
162
|
+
def: ComponentDef3D,
|
|
163
|
+
materials: Doc3D["materials"] | undefined,
|
|
164
|
+
contracts: Readonly<Record<string, Contract>>,
|
|
165
|
+
): ExposedRow {
|
|
166
|
+
const control = exposedSpecOf(prop, def, { materials, contracts });
|
|
167
|
+
if (control !== null) return { spec: control.spec, opaqueColor: control.opaqueColor, undescribed: false };
|
|
168
|
+
const spec = { key: prop.key, propName: prop.key, label: prop.label, kind: prop.kind, animatable: false };
|
|
169
|
+
return { spec: spec as unknown as ControlSpec, opaqueColor: false, undescribed: true };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** A Project asset's kind in the contract's words (`AssetSpec.assetKind`). A
|
|
173
|
+
* model is a "glb" there; a video has no asset kind a contract can ask for. */
|
|
174
|
+
function contractAssetKind(kind: ShotAssetKind): string {
|
|
175
|
+
return kind === "model" ? "glb" : kind;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* The Project's assets as an asset prop's picker offers them: by id, named by
|
|
180
|
+
* their file, in the contract's kinds, each with its file `name` and its MIME
|
|
181
|
+
* type, which the picker reads against the spec's `accept` list
|
|
182
|
+
* (`assetAccepted`): an extension entry (".png") against the name, a MIME
|
|
183
|
+
* entry ("image/svg+xml", "image/*") against the type.
|
|
184
|
+
*
|
|
185
|
+
* A Project asset records no MIME type (`ShotAsset`: a path, a hash, a kind
|
|
186
|
+
* and a probe), so the type is the one the studio serves its stored file as,
|
|
187
|
+
* from the one extension-to-MIME table (`mimeForPath`,
|
|
188
|
+
* `@dailies-studio/shot/mime`). A file whose extension the table does not know
|
|
189
|
+
* carries no type, and the picker offers it rather than hide it.
|
|
190
|
+
*/
|
|
191
|
+
export function projectAssetsOf(assets: Doc3D["assets"] | undefined): PropControlAsset[] {
|
|
192
|
+
return Object.values(assets ?? {})
|
|
193
|
+
.map((asset) => {
|
|
194
|
+
const name = fileNameOf(asset);
|
|
195
|
+
const mime = mimeForPath(asset.path);
|
|
196
|
+
return { id: asset.id, label: name, kind: contractAssetKind(asset.kind), name, ...(mime === undefined ? {} : { mime }) };
|
|
197
|
+
})
|
|
198
|
+
.sort((a, b) => a.label.localeCompare(b.label));
|
|
199
|
+
}
|