@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,453 @@
|
|
|
1
|
+
// One compute card: its sockets, its inline widgets, and its thumbnail.
|
|
2
|
+
//
|
|
3
|
+
// ── THE WIDGETS ARE DERIVED, NOT DECLARED ───────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// A card's fields come from `spec.fields`, which the registry already keeps
|
|
6
|
+
// because both signatures are computed from it. Nothing here adds a "widget"
|
|
7
|
+
// entry to the spec, and that is deliberate: a second list would be a second
|
|
8
|
+
// place for "does this kind carry a wrap?" to be answered, and the two would
|
|
9
|
+
// drift the first time a kind grew a field. The registry says WHAT a node
|
|
10
|
+
// carries; this file says how one of those is typed into.
|
|
11
|
+
//
|
|
12
|
+
// ── AND THEY COMMIT THROUGH THE STORE, NEVER THE DOCUMENT ───────────────
|
|
13
|
+
//
|
|
14
|
+
// `MaterialParameterControls.tsx`'s pattern, one level in. A typed value goes
|
|
15
|
+
// through `setMaterialNodeValue` — the validated door, one undo entry. A DRAG
|
|
16
|
+
// goes through `useScrub` over the exported pure `writeMaterialNodeValue`, so
|
|
17
|
+
// sixty pointer moves are one history entry and one save rather than sixty.
|
|
18
|
+
// Wiring only the commit half gives a field whose number moves and whose
|
|
19
|
+
// document never changes.
|
|
20
|
+
//
|
|
21
|
+
// Every widget root carries `nodrag nowheel`, which are React Flow's own
|
|
22
|
+
// opt-outs: without `nodrag` a pointer-down inside a field drags the CARD and
|
|
23
|
+
// the field never sees the gesture, and without `nowheel` a scroll over a
|
|
24
|
+
// number pans the canvas.
|
|
25
|
+
import { createContext, memo, useContext } from "react";
|
|
26
|
+
import type { ReactNode } from "react";
|
|
27
|
+
import { Handle, Position, useConnection } from "@xyflow/react";
|
|
28
|
+
import type { NodeProps } from "@xyflow/react";
|
|
29
|
+
import { ColorPicker, Combobox, NumberField, TextField, Toggle } from "@dailies-studio/ui";
|
|
30
|
+
import { MATERIAL_GRAPH_GENERATORS, MATERIAL_GRAPH_TEXTURE_WRAPS } from "@dailies-studio/shot/doc";
|
|
31
|
+
import type {
|
|
32
|
+
Doc3D,
|
|
33
|
+
MaterialGraphEndpoint,
|
|
34
|
+
MaterialGraphNode,
|
|
35
|
+
MaterialGraphSocketSpec,
|
|
36
|
+
MaterialGraphValue,
|
|
37
|
+
} from "@dailies-studio/shot/doc";
|
|
38
|
+
import { useStore } from "../../state/context.js";
|
|
39
|
+
import { writeMaterialNodeValue } from "../../state/store.js";
|
|
40
|
+
import { useScrub } from "../inspector/useDocWrite.js";
|
|
41
|
+
import { socketGlyphClass, socketTitle } from "./socketGlyph.js";
|
|
42
|
+
import type { MaterialSocketDrop } from "./socketGlyph.js";
|
|
43
|
+
import { NodePreview } from "./NodePreview.js";
|
|
44
|
+
import type { MaterialFlowData, MaterialFlowNode } from "./flowModel.js";
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* "May a wire from here land there?", as the canvas's memoised type index
|
|
48
|
+
* answers it.
|
|
49
|
+
*
|
|
50
|
+
* A CONTEXT rather than a prop, because the answer depends on the GRAPH and the
|
|
51
|
+
* question is asked by every handle: threading it through `data` would put a
|
|
52
|
+
* function into the memo key and re-render every card whenever the graph
|
|
53
|
+
* changed, which is exactly what `flowModel.ts` exists to stop. The value here
|
|
54
|
+
* changes on the same beat — once per graph — and only handles read it.
|
|
55
|
+
*/
|
|
56
|
+
const CanConnectContext = createContext<(source: MaterialGraphEndpoint, target: MaterialGraphEndpoint) => boolean>(
|
|
57
|
+
() => false,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
export function MaterialConnectProvider({
|
|
61
|
+
canConnect,
|
|
62
|
+
children,
|
|
63
|
+
}: {
|
|
64
|
+
canConnect: (source: MaterialGraphEndpoint, target: MaterialGraphEndpoint) => boolean;
|
|
65
|
+
children: ReactNode;
|
|
66
|
+
}) {
|
|
67
|
+
return <CanConnectContext.Provider value={canConnect}>{children}</CanConnectContext.Provider>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* What a live drag says about ONE handle.
|
|
72
|
+
*
|
|
73
|
+
* `useConnection` is React Flow 12's own subscription to the in-flight
|
|
74
|
+
* connection, so a drag re-renders the handles and nothing else — the canvas
|
|
75
|
+
* itself never re-renders for a pointer move. The three answers are the three
|
|
76
|
+
* the design system allows: ringed in accent, dimmed, or exactly as it was.
|
|
77
|
+
*/
|
|
78
|
+
export function useSocketDrop(nodeId: string, socket: string, side: "source" | "target"): MaterialSocketDrop {
|
|
79
|
+
const canConnect = useContext(CanConnectContext);
|
|
80
|
+
const from = useConnection((connection) => (connection.inProgress ? connection.fromHandle : null));
|
|
81
|
+
// React Flow types a handle's id as optional, because a node may declare one
|
|
82
|
+
// unnamed handle. This lane never does — every socket is a named registry id
|
|
83
|
+
// — so an absent one is a handle this canvas did not draw.
|
|
84
|
+
const held = from === null || from.id == null ? null : { nodeId: from.nodeId, socket: from.id };
|
|
85
|
+
if (from === null || held === null) return "idle";
|
|
86
|
+
// A handle on the same side as the one in hand is not a candidate at all, and
|
|
87
|
+
// neither is anything on the node the drag started from. Dimming those would
|
|
88
|
+
// grey out most of the canvas for a gesture that was never aimed at them.
|
|
89
|
+
if (from.nodeId === nodeId) return "idle";
|
|
90
|
+
if (from.type === side) return "idle";
|
|
91
|
+
const wire =
|
|
92
|
+
side === "target"
|
|
93
|
+
? { source: held, target: { nodeId, socket } }
|
|
94
|
+
: { source: { nodeId, socket }, target: held };
|
|
95
|
+
return canConnect(wire.source, wire.target) ? "ok" : "blocked";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function MaterialSocketHandle({
|
|
99
|
+
nodeId,
|
|
100
|
+
socket,
|
|
101
|
+
side,
|
|
102
|
+
connected,
|
|
103
|
+
}: {
|
|
104
|
+
nodeId: string;
|
|
105
|
+
socket: MaterialGraphSocketSpec;
|
|
106
|
+
side: "source" | "target";
|
|
107
|
+
connected: boolean;
|
|
108
|
+
}) {
|
|
109
|
+
const drop = useSocketDrop(nodeId, socket.id, side);
|
|
110
|
+
return (
|
|
111
|
+
<Handle
|
|
112
|
+
type={side}
|
|
113
|
+
position={side === "target" ? Position.Left : Position.Right}
|
|
114
|
+
id={socket.id}
|
|
115
|
+
className={socketGlyphClass(socket.type, { connected, drop })}
|
|
116
|
+
title={socketTitle(socket.label, socket.type)}
|
|
117
|
+
/>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** The card. `memo` is the second half of `flowModel.ts`'s bargain: the props
|
|
122
|
+
* come back identical for an untouched node, and this is what turns that into
|
|
123
|
+
* a skipped render. */
|
|
124
|
+
export const MaterialNodeCard = memo(function MaterialNodeCard({ data }: NodeProps<MaterialFlowNode>) {
|
|
125
|
+
const { node, spec, inputs, outputs, connected, problem } = data;
|
|
126
|
+
return (
|
|
127
|
+
<article
|
|
128
|
+
className={`material-node material-node-${spec.category}${problem === null ? "" : " is-problem"}`}
|
|
129
|
+
aria-label={`${spec.label} shader node`}
|
|
130
|
+
data-node-kind={node.kind}
|
|
131
|
+
data-testid={`material-node-${node.id}`}
|
|
132
|
+
>
|
|
133
|
+
<header className="material-node-title">
|
|
134
|
+
<span>{spec.label}</span>
|
|
135
|
+
{data.outputType === null ? null : <small>{data.outputType}</small>}
|
|
136
|
+
</header>
|
|
137
|
+
{problem === null ? null : (
|
|
138
|
+
<p className="material-node-problem" role="status">
|
|
139
|
+
{problem}
|
|
140
|
+
</p>
|
|
141
|
+
)}
|
|
142
|
+
<MaterialNodeFields data={data} />
|
|
143
|
+
{node.preview === true ? <NodePreview nodeId={node.id} /> : null}
|
|
144
|
+
<div className="material-node-sockets">
|
|
145
|
+
<div className="material-node-inputs">
|
|
146
|
+
{inputs.map((socket) => (
|
|
147
|
+
<div className="material-socket-row is-input" key={socket.id}>
|
|
148
|
+
<MaterialSocketHandle
|
|
149
|
+
nodeId={node.id}
|
|
150
|
+
socket={socket}
|
|
151
|
+
side="target"
|
|
152
|
+
connected={connected.has(`in:${socket.id}`)}
|
|
153
|
+
/>
|
|
154
|
+
<span>{socket.label}</span>
|
|
155
|
+
</div>
|
|
156
|
+
))}
|
|
157
|
+
</div>
|
|
158
|
+
<div className="material-node-outputs">
|
|
159
|
+
{outputs.map((socket) => (
|
|
160
|
+
<div className="material-socket-row is-output" key={socket.id}>
|
|
161
|
+
<span>{socket.label}</span>
|
|
162
|
+
<MaterialSocketHandle
|
|
163
|
+
nodeId={node.id}
|
|
164
|
+
socket={socket}
|
|
165
|
+
side="source"
|
|
166
|
+
connected={connected.has(`out:${socket.id}`)}
|
|
167
|
+
/>
|
|
168
|
+
</div>
|
|
169
|
+
))}
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
</article>
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
/** Which literal kinds carry an editable `value`, and how wide it is. The four
|
|
177
|
+
* vector widths are the only place a component count is spelled. */
|
|
178
|
+
const VECTOR_WIDTH: Readonly<Record<string, 2 | 3 | 4>> = { vec2: 2, vec3: 3, vec4: 4 };
|
|
179
|
+
const AXES = ["X", "Y", "Z", "W"] as const;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* The inline fields of one card, derived from `spec.fields`.
|
|
183
|
+
*
|
|
184
|
+
* Exported on its own because it is the half worth testing: it needs the store
|
|
185
|
+
* and nothing else, where the card around it needs a mounted React Flow.
|
|
186
|
+
*/
|
|
187
|
+
export function MaterialNodeFields({ data }: { data: MaterialFlowData }) {
|
|
188
|
+
const { spec, node } = data;
|
|
189
|
+
const rows: ReactNode[] = [];
|
|
190
|
+
for (const field of spec.fields) {
|
|
191
|
+
if (field === "value") rows.push(<ValueField key="value" data={data} />);
|
|
192
|
+
else if (field === "mask") rows.push(<MaskField key="mask" data={data} />);
|
|
193
|
+
else if (field === "wrap") rows.push(<WrapField key="wrap" data={data} />);
|
|
194
|
+
else if (field === "index") rows.push(<IndexField key="index" data={data} />);
|
|
195
|
+
else if (field === "assetId") rows.push(<AssetField key="assetId" data={data} />);
|
|
196
|
+
else if (field === "parameterId") rows.push(<ParameterField key="parameterId" data={data} />);
|
|
197
|
+
else if (field === "generator") rows.push(<GeneratorField key="generator" data={data} />);
|
|
198
|
+
// `functionId` and `socket` are deliberately absent: both are written by
|
|
199
|
+
// Collapse and Expand, which move a whole region at once, and a dropdown
|
|
200
|
+
// that re-pointed one call site at another function would leave its wires
|
|
201
|
+
// naming sockets that signature does not have.
|
|
202
|
+
//
|
|
203
|
+
// `generator` shares that shape and gets a widget anyway, because the two
|
|
204
|
+
// are not the same problem. A function boundary is authored elsewhere and
|
|
205
|
+
// this card merely calls it; a generator is not authored anywhere — picking
|
|
206
|
+
// one IS the node — and `setMaterialNodeValue` drops the wires the new
|
|
207
|
+
// parameter list no longer has a socket for as part of the same swap.
|
|
208
|
+
}
|
|
209
|
+
if (rows.length === 0) return null;
|
|
210
|
+
return (
|
|
211
|
+
<div className="material-node-fields nodrag nowheel" data-testid={`material-fields-${node.id}`}>
|
|
212
|
+
{rows}
|
|
213
|
+
</div>
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** The one commit seam every widget below uses. */
|
|
218
|
+
function useCommit(data: MaterialFlowData) {
|
|
219
|
+
const store = useStore();
|
|
220
|
+
return (patch: Parameters<typeof store.setMaterialNodeValue>[3]): void =>
|
|
221
|
+
store.setMaterialNodeValue(data.materialId, data.path, data.node.id, patch);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** …and the one DRAG seam. Narrow on purpose (see `writeMaterialNodeValue`'s
|
|
225
|
+
* header): a scrub may change a literal and may never change the graph's
|
|
226
|
+
* shape. */
|
|
227
|
+
function useValueScrub(data: MaterialFlowData, build: (node: MaterialGraphNode, raw: unknown) => MaterialGraphValue | null) {
|
|
228
|
+
return useScrub((doc: Doc3D, raw: unknown) => {
|
|
229
|
+
const node = doc.materials?.[data.materialId]?.nodesById[data.node.id];
|
|
230
|
+
if (node === undefined) return doc;
|
|
231
|
+
const next = build(node, raw);
|
|
232
|
+
if (next === null) return doc;
|
|
233
|
+
return writeMaterialNodeValue(doc, data.materialId, data.path, data.node.id, next);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function ValueField({ data }: { data: MaterialFlowData }) {
|
|
238
|
+
const store = useStore();
|
|
239
|
+
const commit = useCommit(data);
|
|
240
|
+
const { node, spec } = data;
|
|
241
|
+
const width = VECTOR_WIDTH[node.kind];
|
|
242
|
+
const label = spec.label;
|
|
243
|
+
|
|
244
|
+
const scalarScrub = useValueScrub(data, (_node, raw) => (typeof raw === "number" ? raw : null));
|
|
245
|
+
const colorScrub = useValueScrub(data, (_node, raw) => (typeof raw === "string" ? raw : null));
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* One component of a vector, dragged.
|
|
249
|
+
*
|
|
250
|
+
* Built here rather than through `useScrub` because it is needed PER
|
|
251
|
+
* COMPONENT and a hook cannot be called from a loop. It is the same three
|
|
252
|
+
* store calls that hook returns, with the other components re-read from the
|
|
253
|
+
* base document at capture time so a drag on Y cannot flatten X.
|
|
254
|
+
*/
|
|
255
|
+
const vectorScrub = (index: number, components: 2 | 3 | 4) => ({
|
|
256
|
+
start: (): void => store.beginScrub(),
|
|
257
|
+
move: (raw: unknown): void => {
|
|
258
|
+
if (typeof raw !== "number") return;
|
|
259
|
+
store.scrubCapture((doc: Doc3D) => {
|
|
260
|
+
const found = doc.materials?.[data.materialId]?.nodesById[node.id];
|
|
261
|
+
if (found === undefined) return doc;
|
|
262
|
+
return writeMaterialNodeValue(
|
|
263
|
+
doc,
|
|
264
|
+
data.materialId,
|
|
265
|
+
data.path,
|
|
266
|
+
node.id,
|
|
267
|
+
componentsOf(found.value, components, index, raw),
|
|
268
|
+
);
|
|
269
|
+
});
|
|
270
|
+
},
|
|
271
|
+
end: (ok: boolean): void => store.endScrub(ok),
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
if (node.kind === "color") {
|
|
275
|
+
return (
|
|
276
|
+
<div className="material-node-field is-color">
|
|
277
|
+
<ColorPicker
|
|
278
|
+
value={typeof node.value === "string" ? node.value : "#ffffff"}
|
|
279
|
+
ariaLabel={`${label} value`}
|
|
280
|
+
commit={(hex) => commit({ value: hex })}
|
|
281
|
+
scrub={colorScrub}
|
|
282
|
+
/>
|
|
283
|
+
</div>
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
if (node.kind === "bool") {
|
|
287
|
+
return (
|
|
288
|
+
<div className="material-node-field">
|
|
289
|
+
<Toggle
|
|
290
|
+
checked={node.value === true}
|
|
291
|
+
ariaLabel={`${label} value`}
|
|
292
|
+
onChange={(checked) => commit({ value: checked })}
|
|
293
|
+
/>
|
|
294
|
+
</div>
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
if (width !== undefined) {
|
|
298
|
+
const vector = Array.isArray(node.value) ? node.value : [];
|
|
299
|
+
return (
|
|
300
|
+
<div className="material-node-field is-vector">
|
|
301
|
+
{Array.from({ length: width }, (_unused, index) => {
|
|
302
|
+
const scrub = vectorScrub(index, width);
|
|
303
|
+
return (
|
|
304
|
+
<NumberField
|
|
305
|
+
key={index}
|
|
306
|
+
value={typeof vector[index] === "number" ? vector[index]! : 0}
|
|
307
|
+
ariaLabel={`${label} ${AXES[index]}`}
|
|
308
|
+
label={AXES[index]}
|
|
309
|
+
step={0.01}
|
|
310
|
+
onCommit={(next) => commit({ value: componentsOf(node.value, width, index, next) })}
|
|
311
|
+
onScrubStart={scrub.start}
|
|
312
|
+
onScrub={scrub.move}
|
|
313
|
+
onScrubEnd={scrub.end}
|
|
314
|
+
/>
|
|
315
|
+
);
|
|
316
|
+
})}
|
|
317
|
+
</div>
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
// float and int. An integer's quantum is 1, which is also what makes the
|
|
321
|
+
// field print it without a decimal point.
|
|
322
|
+
const step = node.kind === "int" ? 1 : 0.01;
|
|
323
|
+
return (
|
|
324
|
+
<div className="material-node-field">
|
|
325
|
+
<NumberField
|
|
326
|
+
value={typeof node.value === "number" ? node.value : 0}
|
|
327
|
+
ariaLabel={`${label} value`}
|
|
328
|
+
step={step}
|
|
329
|
+
onCommit={(next) => commit({ value: node.kind === "int" ? Math.round(next) : next })}
|
|
330
|
+
onScrubStart={scalarScrub.start}
|
|
331
|
+
onScrub={scalarScrub.move}
|
|
332
|
+
onScrubEnd={scalarScrub.end}
|
|
333
|
+
/>
|
|
334
|
+
</div>
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/** A vector with one component replaced, padded to width. */
|
|
339
|
+
function componentsOf(
|
|
340
|
+
value: MaterialGraphValue | undefined,
|
|
341
|
+
width: 2 | 3 | 4,
|
|
342
|
+
index: number,
|
|
343
|
+
next: number,
|
|
344
|
+
): MaterialGraphValue {
|
|
345
|
+
const current = Array.isArray(value) ? value : [];
|
|
346
|
+
const out = Array.from({ length: width }, (_unused, at) =>
|
|
347
|
+
at === index ? next : typeof current[at] === "number" ? current[at]! : 0,
|
|
348
|
+
);
|
|
349
|
+
return out as unknown as MaterialGraphValue;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function MaskField({ data }: { data: MaterialFlowData }) {
|
|
353
|
+
const commit = useCommit(data);
|
|
354
|
+
return (
|
|
355
|
+
<div className="material-node-field">
|
|
356
|
+
<TextField
|
|
357
|
+
value={data.node.mask ?? "xyz"}
|
|
358
|
+
ariaLabel="Swizzle mask"
|
|
359
|
+
// REFUSED SILENTLY rather than written and reported. A mask is four
|
|
360
|
+
// characters and the field shows what it has; typing "q" and watching
|
|
361
|
+
// it snap back says more than a sentence in the overlay strip would,
|
|
362
|
+
// and the validator's refusal for a bad mask is about a document that
|
|
363
|
+
// should never have been written.
|
|
364
|
+
onCommit={(text) => {
|
|
365
|
+
const mask = text.trim().toLowerCase();
|
|
366
|
+
if (/^[xyzw]{1,4}$/.test(mask)) commit({ mask });
|
|
367
|
+
}}
|
|
368
|
+
/>
|
|
369
|
+
</div>
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function WrapField({ data }: { data: MaterialFlowData }) {
|
|
374
|
+
const commit = useCommit(data);
|
|
375
|
+
return (
|
|
376
|
+
<div className="material-node-field">
|
|
377
|
+
<Combobox
|
|
378
|
+
value={data.node.wrap ?? "clamp"}
|
|
379
|
+
ariaLabel="Texture wrap"
|
|
380
|
+
options={MATERIAL_GRAPH_TEXTURE_WRAPS.map((wrap) => ({ value: wrap, label: wrap }))}
|
|
381
|
+
onChange={(wrap) => commit({ wrap: wrap as (typeof MATERIAL_GRAPH_TEXTURE_WRAPS)[number] })}
|
|
382
|
+
/>
|
|
383
|
+
</div>
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function IndexField({ data }: { data: MaterialFlowData }) {
|
|
388
|
+
const commit = useCommit(data);
|
|
389
|
+
return (
|
|
390
|
+
<div className="material-node-field">
|
|
391
|
+
<NumberField
|
|
392
|
+
value={data.node.index ?? 0}
|
|
393
|
+
ariaLabel="Set index"
|
|
394
|
+
min={0}
|
|
395
|
+
max={3}
|
|
396
|
+
step={1}
|
|
397
|
+
onCommit={(next) => commit({ index: Math.round(next) })}
|
|
398
|
+
/>
|
|
399
|
+
</div>
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function AssetField({ data }: { data: MaterialFlowData }) {
|
|
404
|
+
const commit = useCommit(data);
|
|
405
|
+
return (
|
|
406
|
+
<div className="material-node-field">
|
|
407
|
+
<Combobox
|
|
408
|
+
value={data.node.assetId ?? ""}
|
|
409
|
+
ariaLabel="Texture image"
|
|
410
|
+
placeholder="Choose image"
|
|
411
|
+
options={[...data.choices.images]}
|
|
412
|
+
onChange={(assetId) => commit({ assetId })}
|
|
413
|
+
/>
|
|
414
|
+
</div>
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/** Every material in the library, by the name an author reads. Module-level and
|
|
419
|
+
* sorted once: the table ships with the build and cannot change at runtime, so
|
|
420
|
+
* rebuilding it per card would be forty allocations for a constant. */
|
|
421
|
+
const GENERATOR_OPTIONS = Object.entries(MATERIAL_GRAPH_GENERATORS)
|
|
422
|
+
.map(([value, entry]) => ({ value, label: entry.label }))
|
|
423
|
+
.sort((a, b) => a.label.localeCompare(b.label));
|
|
424
|
+
|
|
425
|
+
function GeneratorField({ data }: { data: MaterialFlowData }) {
|
|
426
|
+
const commit = useCommit(data);
|
|
427
|
+
return (
|
|
428
|
+
<div className="material-node-field">
|
|
429
|
+
<Combobox
|
|
430
|
+
value={data.node.generator ?? ""}
|
|
431
|
+
ariaLabel="Procedural material"
|
|
432
|
+
placeholder="Choose material"
|
|
433
|
+
options={GENERATOR_OPTIONS}
|
|
434
|
+
onChange={(generator) => commit({ generator })}
|
|
435
|
+
/>
|
|
436
|
+
</div>
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function ParameterField({ data }: { data: MaterialFlowData }) {
|
|
441
|
+
const commit = useCommit(data);
|
|
442
|
+
return (
|
|
443
|
+
<div className="material-node-field">
|
|
444
|
+
<Combobox
|
|
445
|
+
value={data.node.parameterId ?? ""}
|
|
446
|
+
ariaLabel="Exposed control"
|
|
447
|
+
placeholder="Choose control"
|
|
448
|
+
options={[...data.choices.parameters]}
|
|
449
|
+
onChange={(parameterId) => commit({ parameterId })}
|
|
450
|
+
/>
|
|
451
|
+
</div>
|
|
452
|
+
);
|
|
453
|
+
}
|