@cueframe/kernel 0.2.1 → 0.2.3
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/_members/animate/index.d.ts +8 -2
- package/dist/_members/animate/layout/FlexLayout.d.ts +69 -0
- package/dist/_members/animate/layout/fit.d.ts +44 -0
- package/dist/_members/animate/layout/index.d.ts +3 -0
- package/dist/_members/animate/layout/solveFlex.d.ts +70 -0
- package/dist/_members/animate/media/MediaTileScene.d.ts +65 -0
- package/dist/_members/animate/media/recipes.d.ts +61 -0
- package/dist/_members/animate/scene/FocusPass.d.ts +76 -0
- package/dist/_members/animate/scene/UnlitPlane.d.ts +45 -0
- package/dist/_members/animate/scene/__oracle__/cssProjection.d.ts +24 -0
- package/dist/_members/animate/scene/assets.d.ts +21 -0
- package/dist/_members/animate/scene/backdrop.d.ts +7 -0
- package/dist/_members/animate/scene/coordinates.d.ts +58 -0
- package/dist/_members/animate/scene/deviceOpacity.d.ts +18 -0
- package/dist/_members/animate/scene/errors.d.ts +14 -0
- package/dist/_members/animate/scene/finishing.d.ts +69 -0
- package/dist/_members/animate/scene/finishingMath.d.ts +60 -0
- package/dist/_members/animate/scene/finishingPass.d.ts +35 -0
- package/dist/_members/animate/scene/focusBlur.d.ts +56 -0
- package/dist/_members/animate/scene/focusResources.d.ts +190 -0
- package/dist/_members/animate/scene/focusShaders.d.ts +68 -0
- package/dist/_members/animate/scene/fontReadiness.d.ts +27 -0
- package/dist/_members/animate/scene/grainNoise.d.ts +118 -0
- package/dist/_members/animate/scene/index.d.ts +19 -0
- package/dist/_members/animate/scene/internal.d.ts +29 -0
- package/dist/_members/animate/scene/planeFit.d.ts +46 -0
- package/dist/_members/animate/scene/preparedWorldText.d.ts +25 -0
- package/dist/_members/animate/scene/rasterCache.d.ts +30 -0
- package/dist/_members/animate/scene/rasterReadiness.d.ts +33 -0
- package/dist/_members/animate/scene/readiness.d.ts +69 -0
- package/dist/_members/animate/scene/redraw.d.ts +10 -0
- package/dist/_members/animate/scene/render.d.ts +9 -0
- package/dist/_members/animate/scene/scaling.d.ts +13 -0
- package/dist/_members/animate/scene/text.d.ts +40 -0
- package/dist/_members/animate/scene/textLayout.d.ts +78 -0
- package/dist/_members/animate/scene/textureImageSize.d.ts +4 -0
- package/dist/_members/animate/scene/useSceneImageTexture.d.ts +21 -0
- package/dist/_members/animate/scene/useWorldTextTexture.d.ts +21 -0
- package/dist/_members/animate/scene/v2/MeasuredPlaneGeometry.d.ts +7 -0
- package/dist/_members/animate/scene/v2/PhotographicStudioRig.d.ts +11 -0
- package/dist/_members/animate/scene/v2/PreparedSceneShotV1.d.ts +12 -0
- package/dist/_members/animate/scene/v2/SceneShotV2.d.ts +59 -0
- package/dist/_members/animate/scene/v2/builders.d.ts +170 -0
- package/dist/_members/animate/scene/v2/finishes.d.ts +152 -0
- package/dist/_members/animate/scene/v2/lighting.d.ts +119 -0
- package/dist/_members/animate/scene/v2/observePmremTargets.d.ts +4 -0
- package/dist/_members/animate/scene/v2/preparationFacts.d.ts +32 -0
- package/dist/_members/animate/scene/v2/preparedSurface.d.ts +17 -0
- package/dist/_members/animate/scene/v2/projectedResolution.d.ts +2 -0
- package/dist/_members/animate/scene/v2/renderTargetObserver.d.ts +5 -0
- package/dist/_members/animate/scene/v2/runtimeAllocations.d.ts +55 -0
- package/dist/_members/animate/scene/v2/shadow.d.ts +23 -0
- package/dist/_members/animate/scene/v2/slabGeometry.d.ts +134 -0
- package/dist/_members/animate/scene/v2/slots.d.ts +73 -0
- package/dist/_members/animate/scene/v2/videoBinding.d.ts +39 -0
- package/dist/_members/animate/scene/worldBounds.d.ts +19 -0
- package/dist/_members/animate/scene/worldTextRaster.d.ts +87 -0
- package/dist/_members/animate/scene/worldTextTexture.d.ts +32 -0
- package/dist/_members/animate/stage/PerspectiveStage.d.ts +73 -0
- package/dist/_members/animate/stage/camera.d.ts +143 -0
- package/dist/_members/animate/stage/dof.d.ts +9 -0
- package/dist/_members/animate/stage/index.d.ts +6 -0
- package/dist/_members/animate/stage/presets.d.ts +17 -0
- package/dist/_members/animate/three/DeviceMesh.d.ts +256 -0
- package/dist/_members/animate/three/SceneCameraRig.d.ts +12 -0
- package/dist/_members/animate/three/StageCameraRig.d.ts +7 -0
- package/dist/_members/animate/three/StudioRig.d.ts +228 -0
- package/dist/_members/animate/three/ThreeCanvas.d.ts +22 -0
- package/dist/_members/animate/three/defaultScreen.d.ts +23 -0
- package/dist/_members/animate/three/index.d.ts +7 -1
- package/dist/_members/animate/three/textureLifecycle.d.ts +29 -0
- package/dist/_members/animate/three/toneMapping.d.ts +113 -0
- package/dist/_members/animate/three/useImageTexture.d.ts +17 -0
- package/dist/_members/authoring/index.d.ts +2 -0
- package/dist/_members/authoring/scene/index.d.ts +6 -0
- package/dist/_members/authoring/scene/materialize.d.ts +47 -0
- package/dist/_members/authoring/scene/validate.d.ts +80 -0
- package/dist/_members/authoring/scene/wrapper.d.ts +41 -0
- package/dist/_members/component-runtime/allowedImports.d.ts +3 -0
- package/dist/_members/component-runtime/allowedImports.d.ts.map +1 -0
- package/dist/_members/component-runtime/bake.d.ts +8 -0
- package/dist/_members/component-runtime/bake.d.ts.map +1 -1
- package/dist/_members/component-runtime/browserFirewall.d.ts +7 -1
- package/dist/_members/component-runtime/browserFirewall.d.ts.map +1 -1
- package/dist/_members/component-runtime/browserOptions.d.ts +59 -3
- package/dist/_members/component-runtime/browserOptions.d.ts.map +1 -1
- package/dist/_members/component-runtime/canonicalIdentity.d.ts +14 -0
- package/dist/_members/component-runtime/canonicalIdentity.d.ts.map +1 -1
- package/dist/_members/component-runtime/contracts.d.ts +341 -1
- package/dist/_members/component-runtime/contracts.d.ts.map +1 -1
- package/dist/_members/component-runtime/fixtures/imageTileDriftWall.d.ts +5 -0
- package/dist/_members/component-runtime/fixtures/imageTileDriftWall.d.ts.map +1 -0
- package/dist/_members/component-runtime/fixtures/mediaTileMixed.d.ts +5 -0
- package/dist/_members/component-runtime/fixtures/mediaTileMixed.d.ts.map +1 -0
- package/dist/_members/component-runtime/fixtures/mediaTileVideo.d.ts +8 -0
- package/dist/_members/component-runtime/fixtures/mediaTileVideo.d.ts.map +1 -0
- package/dist/_members/component-runtime/importPolicy.d.ts +3 -2
- package/dist/_members/component-runtime/importPolicy.d.ts.map +1 -1
- package/dist/_members/component-runtime/index.d.ts +3 -0
- package/dist/_members/component-runtime/index.d.ts.map +1 -1
- package/dist/_members/component-runtime/livePreviewProxy.d.ts +7 -0
- package/dist/_members/component-runtime/livePreviewProxy.d.ts.map +1 -0
- package/dist/_members/component-runtime/localRoot.d.ts +37 -0
- package/dist/_members/component-runtime/localRoot.d.ts.map +1 -0
- package/dist/_members/component-runtime/mediaResolution.d.ts +25 -0
- package/dist/_members/component-runtime/mediaResolution.d.ts.map +1 -0
- package/dist/_members/component-runtime/render.d.ts +151 -13
- package/dist/_members/component-runtime/render.d.ts.map +1 -1
- package/dist/_members/component-runtime/renderDiagnostics.d.ts +14 -0
- package/dist/_members/component-runtime/renderDiagnostics.d.ts.map +1 -0
- package/dist/_members/component-runtime/sceneAdmission.d.ts +47 -0
- package/dist/_members/component-runtime/sceneAdmission.d.ts.map +1 -0
- package/dist/_members/component-runtime/sourceWorkspace.d.ts +8 -0
- package/dist/_members/component-runtime/sourceWorkspace.d.ts.map +1 -1
- package/dist/_members/component-runtime/webglProbe.d.ts +191 -0
- package/dist/_members/component-runtime/webglProbe.d.ts.map +1 -0
- package/dist/_members/composition/fonts/bundledFaces.d.ts +150 -0
- package/dist/_members/composition/fonts/captionFaces.d.ts +268 -0
- package/dist/_members/composition/fonts.d.ts +11 -4
- package/dist/_members/composition/graphics-plan/schemas.d.ts +4 -4
- package/dist/_members/composition/ops/types.d.ts +1 -1
- package/dist/_members/composition/primitive-catalog/types.d.ts +1 -0
- package/dist/_members/composition/projection/behind-readiness.d.ts +3 -0
- package/dist/_members/composition/projection/brandKit.d.ts +6 -0
- package/dist/_members/composition/projection/composition-floor.d.ts +2 -1
- package/dist/_members/composition/scene/animation.d.ts +25 -0
- package/dist/_members/composition/scene/budget.d.ts +29 -0
- package/dist/_members/composition/scene/budgetPolicy.d.mts +13 -0
- package/dist/_members/composition/scene/clipRules.d.ts +119 -0
- package/dist/_members/composition/scene/constraints.d.ts +61 -0
- package/dist/_members/composition/scene/device.d.ts +21 -0
- package/dist/_members/composition/scene/examples.d.ts +11 -0
- package/dist/_members/composition/scene/index.d.ts +11 -0
- package/dist/_members/composition/scene/photographicRig.d.ts +242 -0
- package/dist/_members/composition/scene/preparedRender.d.ts +239 -0
- package/dist/_members/composition/scene/resolution.d.ts +178 -0
- package/dist/_members/composition/scene/schema.d.ts +351 -0
- package/dist/_members/composition/scene/videoSchedule.d.ts +43 -0
- package/dist/_members/composition/validators/brandKit.d.ts +1 -0
- package/dist/_members/composition/validators/render.d.ts +2 -0
- package/dist/_members/composition-ops/index.d.ts +45 -0
- package/dist/_members/composition-ops/opRecorder.d.ts +1 -1
- package/dist/_members/core/render/compositionRender.d.ts +41 -9
- package/dist/_members/core/render/index.d.ts +9 -2
- package/dist/_members/core/render/sceneCaptureIdentity.d.ts +14 -0
- package/dist/_members/core/render/sceneShotPlan.d.ts +142 -0
- package/dist/_members/core/render/sceneShotPreparation.d.ts +57 -0
- package/dist/_members/core/render/slabDescriptor.d.ts +21 -0
- package/dist/_members/core/render/trackProjection.d.ts +33 -0
- package/dist/_members/core/render/types.d.ts +142 -0
- package/dist/_members/errors/registry.d.ts +6 -0
- package/dist/_members/mcp/adapter.d.ts +5 -0
- package/dist/_members/mcp/generated/sceneContract.d.ts +155 -0
- package/dist/_members/mcp/sceneShot.d.ts +38 -0
- package/dist/_members/mcp/sceneShotExample.d.ts +22 -0
- package/dist/_members/media-model/api.d.ts +1 -0
- package/dist/_members/media-model/media-kind.d.ts +1 -1
- package/dist/_members/media-model/testing/mediaStoreContract.d.ts +1 -1
- package/dist/_members/primitives/effects/index.d.ts +1 -0
- package/dist/_members/primitives/effects/stage-camera/config.d.ts +50 -0
- package/dist/_members/primitives/effects/stage-camera/index.d.ts +31 -0
- package/dist/_members/primitives/layouts/flex-layout/config.d.ts +73 -0
- package/dist/_members/primitives/layouts/flex-layout/index.d.ts +4 -0
- package/dist/_members/primitives/layouts/index.d.ts +1 -0
- package/dist/_members/primitives/layouts/picture-in-picture/config.d.ts +1 -1
- package/dist/_members/primitives/lib/frameScale.d.ts +4 -0
- package/dist/_members/primitives/lib/index.d.ts +1 -0
- package/dist/_members/primitives/lib/palette.d.ts +30 -30
- package/dist/_members/primitives/lib/text/contrast.d.ts +2 -1
- package/dist/_members/primitives/lib/text/spec.d.ts +0 -8
- package/dist/_members/primitives/lib/types.d.ts +2 -0
- package/dist/_members/primitives/scenes/device-showcase/config.d.ts +41 -0
- package/dist/_members/primitives/scenes/device-showcase/index.d.ts +36 -0
- package/dist/_members/primitives/scenes/hero-device-assemble/config.d.ts +1 -0
- package/dist/_members/primitives/scenes/hero-device-assemble/index.d.ts +2 -1
- package/dist/_members/primitives/scenes/index.d.ts +1 -0
- package/dist/_members/primitives/ui-blocks/badge-pop/config.d.ts +1 -1
- package/dist/_members/primitives/ui-blocks/device-mockup-zoom/config.d.ts +1 -0
- package/dist/_members/primitives/ui-blocks/device-mockup-zoom/index.d.ts +2 -1
- package/dist/_members/primitives/ui-blocks/terminal-simulator/config.d.ts +1 -1
- package/dist/_members/primitives/ui-blocks/toast-notification/config.d.ts +1 -1
- package/dist/_members/render-harness/cardAssetAdmission.d.ts.map +1 -1
- package/dist/_members/render-harness/cardRender.d.ts.map +1 -1
- package/dist/_members/render-harness/css-tree-subpaths.d.ts +11 -0
- package/dist/_members/render-harness/extractSegments.d.ts +1 -0
- package/dist/_members/render-harness/extractSegments.d.ts.map +1 -1
- package/dist/_members/render-harness/imageHeader.d.ts +14 -0
- package/dist/_members/render-harness/imageHeader.d.ts.map +1 -0
- package/dist/_members/render-harness/index.d.ts +6 -0
- package/dist/_members/render-harness/index.d.ts.map +1 -1
- package/dist/_members/render-harness/materializeSources.d.ts +46 -2
- package/dist/_members/render-harness/materializeSources.d.ts.map +1 -1
- package/dist/_members/render-harness/nodeScenePreparation.d.ts +97 -0
- package/dist/_members/render-harness/nodeScenePreparation.d.ts.map +1 -0
- package/dist/_members/render-harness/remotion-runtime.d.ts +16 -2
- package/dist/_members/render-harness/renderInputAssets.d.ts +1 -1
- package/dist/_members/render-harness/renderInputAssets.d.ts.map +1 -1
- package/dist/_members/render-harness/resolveAssets.d.ts +2 -2
- package/dist/_members/render-harness/resolveAssets.d.ts.map +1 -1
- package/dist/_members/render-harness/sceneShotAssets.d.ts +17 -0
- package/dist/_members/render-harness/sceneShotAssets.d.ts.map +1 -0
- package/dist/animate/preparation-facts.d.ts +1 -0
- package/dist/animate/preparation-facts.js +22 -0
- package/dist/animate.js +336 -1005
- package/dist/authoring/build-tools.js +7 -6
- package/dist/authoring/context.js +5 -4
- package/dist/authoring/prompts.js +1 -1
- package/dist/authoring/scene.d.ts +1 -0
- package/dist/authoring/scene.js +50 -0
- package/dist/authoring/tools.js +6 -5
- package/dist/authoring.js +49 -29
- package/dist/chunk-2L7PYYJK.js +23 -0
- package/dist/{chunk-ZN6P3KOJ.js → chunk-32TH76H3.js} +2 -2
- package/dist/chunk-5DJ3IEJR.js +4424 -0
- package/dist/chunk-6BVVCRRD.js +26488 -0
- package/dist/{chunk-DQKSCHFC.js → chunk-6EWRIAZA.js} +187 -66
- package/dist/{chunk-YQ7FFW3G.js → chunk-6VWICHOZ.js} +26 -5
- package/dist/{chunk-2PGLNTB7.js → chunk-A74FZCPY.js} +45 -5
- package/dist/{chunk-C5SEPOWD.js → chunk-AS5EXBNS.js} +1792 -707
- package/dist/{chunk-BKHGL4MB.js → chunk-B3GSTQLR.js} +341 -274
- package/dist/chunk-BVA3537Z.js +63 -0
- package/dist/{chunk-DHKQ47Q6.js → chunk-DAARYRNT.js} +6 -1
- package/dist/chunk-DQLYWNLC.js +2063 -0
- package/dist/chunk-E6WHXIDF.js +3619 -0
- package/dist/{chunk-NOEBAV2G.js → chunk-E7GIZEPS.js} +1 -1
- package/dist/{chunk-M2TLRXEO.js → chunk-EXY4JJPH.js} +1 -1
- package/dist/{chunk-GEGRJKKO.js → chunk-F2DJL7P7.js} +1 -1
- package/dist/{chunk-AWT3P5ZN.js → chunk-FVDFPJHT.js} +1 -1
- package/dist/{chunk-EMGFZ3PR.js → chunk-FWSJLHSV.js} +5 -1
- package/dist/{chunk-TMIBBD5E.js → chunk-I5QWBM3M.js} +280 -113
- package/dist/{chunk-IBMJ33EL.js → chunk-I5RX2QZT.js} +1 -1
- package/dist/{chunk-4FOOBSEE.js → chunk-J3DIUG24.js} +1 -0
- package/dist/{chunk-AD5HWBCE.js → chunk-JX53CVJV.js} +14 -5
- package/dist/{chunk-LNBVTDFR.js → chunk-L2AHS3AW.js} +1 -1
- package/dist/{chunk-BDMTUEEZ.js → chunk-LT4PWSR2.js} +2 -2
- package/dist/chunk-MH3UPKWR.js +3415 -0
- package/dist/{chunk-RFXR7ATW.js → chunk-NUKDEOK6.js} +13 -1
- package/dist/{chunk-IJ7PVJTK.js → chunk-ODUWCQI3.js} +3 -2
- package/dist/chunk-QAGGJHAF.js +16 -0
- package/dist/chunk-QS36DMFG.js +332 -0
- package/dist/{chunk-G5BFI32U.js → chunk-RAXHCRVV.js} +1 -1
- package/dist/{chunk-BIBYZJL3.js → chunk-RL5SO653.js} +3 -3
- package/dist/{chunk-ZSZABOE5.js → chunk-S5H6GH6M.js} +1 -1
- package/dist/{chunk-EEXCDFY5.js → chunk-SD25VQDE.js} +1 -1
- package/dist/{chunk-Y3QGYASW.js → chunk-SX523NDS.js} +14 -14
- package/dist/chunk-TARKDVP6.js +430 -0
- package/dist/{chunk-IHFREGFA.js → chunk-TCHPRGC5.js} +18 -2
- package/dist/{chunk-ZCAQHNPI.js → chunk-UKGNHZS4.js} +1 -1
- package/dist/{chunk-KU376ELE.js → chunk-UY77TMKD.js} +31 -44
- package/dist/chunk-VKATKWWR.js +1462 -0
- package/dist/{chunk-CX2IIQ4R.js → chunk-W2245F6G.js} +29 -29
- package/dist/{chunk-XHUYWVYK.js → chunk-WBNFSG6T.js} +1 -1
- package/dist/chunk-WIHXXF3X.js +221 -0
- package/dist/{chunk-XVBOSPZI.js → chunk-X74EEFXV.js} +6 -6
- package/dist/{chunk-7KEUL3FI.js → chunk-XF2QMKRG.js} +9 -1
- package/dist/{chunk-HFC3MKXA.js → chunk-Y4HPN4BC.js} +1 -0
- package/dist/{chunk-6XI57FZZ.js → chunk-YFSBFCXO.js} +1022 -46
- package/dist/{chunk-6ID2J64H.js → chunk-YHC3RXS7.js} +162 -25
- package/dist/{chunk-KKEY5MIW.js → chunk-ZS3A3QUM.js} +16 -16
- package/dist/{chunk-LQUWKBST.js → chunk-ZVG446DJ.js} +139 -10
- package/dist/component-runtime/browserOptions.js +14 -3
- package/dist/component-runtime/contracts.js +35 -3
- package/dist/component-runtime/identity/browser.js +1 -1
- package/dist/component-runtime/identity.js +2 -2
- package/dist/component-runtime/importPolicy.js +2 -2
- package/dist/component-runtime/mediaResolution.d.ts +1 -0
- package/dist/component-runtime/mediaResolution.js +11 -0
- package/dist/component-runtime/render.js +38 -5
- package/dist/component-runtime.js +118 -14
- package/dist/compose.js +27 -21
- package/dist/composition/fonts.js +64 -67
- package/dist/composition/graphics-plan.js +3 -2
- package/dist/composition/ops.js +4 -3
- package/dist/composition/primitive-catalog.js +1 -1
- package/dist/composition/projection.js +10 -3
- package/dist/composition/scene/budget-policy.d.ts +1 -0
- package/dist/composition/scene/budget-policy.js +17 -0
- package/dist/composition/scene/schema.json +2757 -0
- package/dist/composition/scene.d.ts +1 -0
- package/dist/composition/scene.js +275 -0
- package/dist/composition/validators.js +3 -2
- package/dist/composition-ops.js +103 -13
- package/dist/composition.js +12 -5
- package/dist/{context-4GSDBFT3.js → context-IUPQ54V4.js} +5 -4
- package/dist/core/render.js +54 -3
- package/dist/core/select.js +2 -2
- package/dist/core.js +6 -3
- package/dist/director/ai-sdk.js +3 -3
- package/dist/director/domain.js +2 -2
- package/dist/director.js +3 -3
- package/dist/errors.js +1 -1
- package/dist/mcp/adapter.js +4 -4
- package/dist/mcp/core.js +1 -1
- package/dist/mcp/curation.js +1 -1
- package/dist/mcp/server.js +4 -4
- package/dist/mcp.js +4 -4
- package/dist/media-model/media-kind.js +2 -0
- package/dist/media-model/testing.js +16 -11
- package/dist/media-model.js +1 -1
- package/dist/nle-export.js +27 -21
- package/dist/primitives/backgrounds.js +2 -2
- package/dist/primitives/captions.js +21 -11
- package/dist/primitives/effects.js +14 -4
- package/dist/primitives/graphics.json +3 -0
- package/dist/primitives/hero-text.js +4 -3
- package/dist/primitives/layouts.js +9 -2
- package/dist/primitives/lib/frameScale.d.ts +1 -0
- package/dist/primitives/lib/frameScale.js +11 -0
- package/dist/primitives/lib/index.js +18 -10
- package/dist/primitives/lib/palette.js +1 -1
- package/dist/primitives/lib/text/contrast.js +2 -1
- package/dist/primitives/lib/text/typeface.js +1 -1
- package/dist/primitives/lib.js +18 -10
- package/dist/primitives/params-required.json +3 -0
- package/dist/primitives/scenes.js +12 -3
- package/dist/primitives/text.js +5 -5
- package/dist/primitives/transitions.js +2 -2
- package/dist/primitives/ui-blocks.js +7 -6
- package/dist/primitives/version-map.json +5 -2
- package/dist/primitives.js +27 -20
- package/dist/render-harness/cardAssetAdmission.js +2 -2
- package/dist/render-harness/renderInputAssets.js +2 -2
- package/dist/render-harness.js +876 -126
- package/package.json +51 -17
- package/dist/_members/animate/three/drei.d.ts +0 -6
- package/dist/_members/component-runtime/fixtures/webgpuTiledRefraction.d.ts +0 -9
- package/dist/_members/component-runtime/fixtures/webgpuTiledRefraction.d.ts.map +0 -1
- package/dist/chunk-4JRUGT2Y.js +0 -544
- package/dist/chunk-5OTQ7M43.js +0 -718
- package/dist/chunk-CGHTMZNC.js +0 -6
- package/dist/chunk-QBKDEO7J.js +0 -9521
- /package/dist/{chunk-H5LMJKZU.js → chunk-JVDUSOYG.js} +0 -0
|
@@ -0,0 +1,4424 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEVICE_GLASS_OPACITY_LINEAR,
|
|
3
|
+
DeviceMesh,
|
|
4
|
+
MeasuredPlaneGeometry,
|
|
5
|
+
PhotographicStudioRig,
|
|
6
|
+
SLAB_DEFAULTS,
|
|
7
|
+
SceneRuntimeAllocationBoundaryV1,
|
|
8
|
+
StudioRig,
|
|
9
|
+
UNLIT_COLOUR_MANAGED,
|
|
10
|
+
admitLightingProfile,
|
|
11
|
+
admitSceneRigV2,
|
|
12
|
+
assertNoObjectLightField,
|
|
13
|
+
deviceDimensions,
|
|
14
|
+
laptopLayout,
|
|
15
|
+
lidRotationX,
|
|
16
|
+
registerActualSceneResourcesV1,
|
|
17
|
+
slabBodyGeometry,
|
|
18
|
+
slabFinishMaterial,
|
|
19
|
+
slabTriangleCount,
|
|
20
|
+
takeSceneEnvironment,
|
|
21
|
+
useSceneActualResourceRegistrarV1
|
|
22
|
+
} from "./chunk-VKATKWWR.js";
|
|
23
|
+
import {
|
|
24
|
+
resolveCaptionFaces
|
|
25
|
+
} from "./chunk-TARKDVP6.js";
|
|
26
|
+
import {
|
|
27
|
+
PHOTOGRAPHIC_STUDIO_RIG_ID,
|
|
28
|
+
SCENE_SLAB_CONTENT_OFFSET,
|
|
29
|
+
STUDIO_SHADOW_MAP_BUDGET,
|
|
30
|
+
evaluateScene,
|
|
31
|
+
sceneCameraPlanesV2,
|
|
32
|
+
sceneFocusPreparationAllocationsV1,
|
|
33
|
+
sceneFullMipLevels,
|
|
34
|
+
sceneTextureBytes,
|
|
35
|
+
sceneVideoMidpointAddressV1,
|
|
36
|
+
selectSceneBakeScale
|
|
37
|
+
} from "./chunk-MH3UPKWR.js";
|
|
38
|
+
|
|
39
|
+
// ../execution/animate/src/easing/smooth.ts
|
|
40
|
+
var sigmoid = (x) => 1 / (1 + Math.exp(-x));
|
|
41
|
+
function smooth(t, inflection = 10) {
|
|
42
|
+
const error = sigmoid(-inflection / 2);
|
|
43
|
+
return (sigmoid(inflection * (t - 0.5)) - error) / (1 - 2 * error);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ../execution/animate/src/easing/smootherstep.ts
|
|
47
|
+
function smootherstep(t) {
|
|
48
|
+
return 6 * t ** 5 - 15 * t ** 4 + 10 * t ** 3;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ../execution/animate/src/easing/rush.ts
|
|
52
|
+
function rushInto(t, inflection = 10) {
|
|
53
|
+
return 2 * smooth(t / 2, inflection);
|
|
54
|
+
}
|
|
55
|
+
function rushFrom(t, inflection = 10) {
|
|
56
|
+
return 2 * smooth(t / 2 + 0.5, inflection) - 1;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ../execution/animate/src/animations/Create.tsx
|
|
60
|
+
import React2 from "react";
|
|
61
|
+
import { useCurrentFrame, interpolate } from "remotion";
|
|
62
|
+
import { evolvePath } from "@remotion/paths";
|
|
63
|
+
var Create = ({
|
|
64
|
+
path,
|
|
65
|
+
stroke = "currentColor",
|
|
66
|
+
strokeWidth = 2,
|
|
67
|
+
fill = "none",
|
|
68
|
+
fillAfter = false,
|
|
69
|
+
width = "100%",
|
|
70
|
+
height = "100%",
|
|
71
|
+
viewBox = "0 0 1920 1080",
|
|
72
|
+
durationInFrames = 30,
|
|
73
|
+
delay = 0,
|
|
74
|
+
easing = smooth,
|
|
75
|
+
style
|
|
76
|
+
}) => {
|
|
77
|
+
const frame = useCurrentFrame();
|
|
78
|
+
const t = Math.min(1, Math.max(0, frame - delay) / Math.max(1, durationInFrames));
|
|
79
|
+
const progress2 = easing(t);
|
|
80
|
+
const evolved = evolvePath(progress2, path);
|
|
81
|
+
const fillOpacity = fillAfter && fill !== "none" ? interpolate(progress2, [0.8, 1], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }) : fill !== "none" ? 1 : 0;
|
|
82
|
+
return /* @__PURE__ */ React2.createElement("svg", { width, height, viewBox, style }, /* @__PURE__ */ React2.createElement(
|
|
83
|
+
"path",
|
|
84
|
+
{
|
|
85
|
+
d: path,
|
|
86
|
+
stroke,
|
|
87
|
+
strokeWidth,
|
|
88
|
+
fill,
|
|
89
|
+
fillOpacity,
|
|
90
|
+
strokeDasharray: evolved.strokeDasharray,
|
|
91
|
+
strokeDashoffset: evolved.strokeDashoffset,
|
|
92
|
+
strokeLinecap: "round",
|
|
93
|
+
strokeLinejoin: "round"
|
|
94
|
+
}
|
|
95
|
+
));
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// ../execution/animate/src/animations/GrowFromCenter.tsx
|
|
99
|
+
import React3 from "react";
|
|
100
|
+
import { useCurrentFrame as useCurrentFrame2, useVideoConfig, spring } from "remotion";
|
|
101
|
+
var GrowFromCenter = ({
|
|
102
|
+
children,
|
|
103
|
+
delay = 0,
|
|
104
|
+
springConfig = { damping: 12, stiffness: 200, mass: 0.8 },
|
|
105
|
+
style
|
|
106
|
+
}) => {
|
|
107
|
+
const frame = useCurrentFrame2();
|
|
108
|
+
const { fps } = useVideoConfig();
|
|
109
|
+
const adjustedFrame = Math.max(0, frame - delay);
|
|
110
|
+
const scale = spring({
|
|
111
|
+
frame: adjustedFrame,
|
|
112
|
+
fps,
|
|
113
|
+
config: springConfig
|
|
114
|
+
});
|
|
115
|
+
return /* @__PURE__ */ React3.createElement(
|
|
116
|
+
"div",
|
|
117
|
+
{
|
|
118
|
+
style: {
|
|
119
|
+
transform: `scale(${scale})`,
|
|
120
|
+
transformOrigin: "center center",
|
|
121
|
+
...style
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
children
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// ../execution/animate/src/animations/FadeIn.tsx
|
|
129
|
+
import React4 from "react";
|
|
130
|
+
import { useCurrentFrame as useCurrentFrame3, useVideoConfig as useVideoConfig2, spring as spring2 } from "remotion";
|
|
131
|
+
var DIRECTION_TRANSFORM = {
|
|
132
|
+
up: (o) => `translateY(${o}px)`,
|
|
133
|
+
down: (o) => `translateY(${-o}px)`,
|
|
134
|
+
left: (o) => `translateX(${o}px)`,
|
|
135
|
+
right: (o) => `translateX(${-o}px)`,
|
|
136
|
+
none: () => ""
|
|
137
|
+
};
|
|
138
|
+
var FadeIn = ({
|
|
139
|
+
children,
|
|
140
|
+
direction = "up",
|
|
141
|
+
distance = 30,
|
|
142
|
+
durationInFrames = 20,
|
|
143
|
+
delay = 0,
|
|
144
|
+
easing = smooth,
|
|
145
|
+
useSpring: useSpringPhysics = false,
|
|
146
|
+
springConfig = { damping: 15, stiffness: 200, mass: 0.5 },
|
|
147
|
+
style
|
|
148
|
+
}) => {
|
|
149
|
+
const frame = useCurrentFrame3();
|
|
150
|
+
const { fps } = useVideoConfig2();
|
|
151
|
+
const adjustedFrame = Math.max(0, frame - delay);
|
|
152
|
+
let progress2;
|
|
153
|
+
if (useSpringPhysics) {
|
|
154
|
+
progress2 = spring2({ frame: adjustedFrame, fps, config: springConfig });
|
|
155
|
+
} else {
|
|
156
|
+
const t = Math.min(1, adjustedFrame / Math.max(1, durationInFrames));
|
|
157
|
+
progress2 = easing(t);
|
|
158
|
+
}
|
|
159
|
+
const offset = (1 - progress2) * distance;
|
|
160
|
+
return /* @__PURE__ */ React4.createElement(
|
|
161
|
+
"div",
|
|
162
|
+
{
|
|
163
|
+
style: {
|
|
164
|
+
opacity: Math.min(1, progress2),
|
|
165
|
+
transform: DIRECTION_TRANSFORM[direction](offset),
|
|
166
|
+
...style
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
children
|
|
170
|
+
);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// ../execution/animate/src/animations/Write.tsx
|
|
174
|
+
import React5 from "react";
|
|
175
|
+
import { useCurrentFrame as useCurrentFrame4 } from "remotion";
|
|
176
|
+
var Write = ({
|
|
177
|
+
text,
|
|
178
|
+
durationInFrames = 60,
|
|
179
|
+
delay = 0,
|
|
180
|
+
easing = smooth,
|
|
181
|
+
color = "currentColor",
|
|
182
|
+
fontFamily,
|
|
183
|
+
fontSize,
|
|
184
|
+
fontWeight,
|
|
185
|
+
letterSpacing,
|
|
186
|
+
style
|
|
187
|
+
}) => {
|
|
188
|
+
const frame = useCurrentFrame4();
|
|
189
|
+
const chars = text.split("");
|
|
190
|
+
const count = chars.length;
|
|
191
|
+
if (count === 0) return null;
|
|
192
|
+
const charAnimDuration = Math.max(4, durationInFrames * 0.4);
|
|
193
|
+
const stagger = count > 1 ? (durationInFrames - charAnimDuration) / (count - 1) : 0;
|
|
194
|
+
return /* @__PURE__ */ React5.createElement(
|
|
195
|
+
"span",
|
|
196
|
+
{
|
|
197
|
+
style: {
|
|
198
|
+
display: "inline-block",
|
|
199
|
+
color,
|
|
200
|
+
fontFamily,
|
|
201
|
+
fontSize,
|
|
202
|
+
fontWeight,
|
|
203
|
+
letterSpacing,
|
|
204
|
+
whiteSpace: "pre-wrap",
|
|
205
|
+
...style
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
chars.map((char, i) => {
|
|
209
|
+
const charStart = delay + i * stagger;
|
|
210
|
+
const localFrame = frame - charStart;
|
|
211
|
+
const t = Math.min(1, Math.max(0, localFrame / charAnimDuration));
|
|
212
|
+
const progress2 = easing(t);
|
|
213
|
+
const yOffset = (1 - progress2) * 8;
|
|
214
|
+
return /* @__PURE__ */ React5.createElement(
|
|
215
|
+
"span",
|
|
216
|
+
{
|
|
217
|
+
key: i,
|
|
218
|
+
style: {
|
|
219
|
+
display: "inline-block",
|
|
220
|
+
opacity: progress2,
|
|
221
|
+
transform: `translateY(${yOffset}px)`,
|
|
222
|
+
minWidth: char === " " ? "0.25em" : void 0
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
char
|
|
226
|
+
);
|
|
227
|
+
})
|
|
228
|
+
);
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// ../execution/animate/src/animations/Indicate.tsx
|
|
232
|
+
import React6 from "react";
|
|
233
|
+
import { useCurrentFrame as useCurrentFrame5 } from "remotion";
|
|
234
|
+
var Indicate = ({
|
|
235
|
+
children,
|
|
236
|
+
color = "#FBBF24",
|
|
237
|
+
scaleFactor = 1.15,
|
|
238
|
+
durationInFrames = 30,
|
|
239
|
+
delay = 0,
|
|
240
|
+
pulses = 1,
|
|
241
|
+
style
|
|
242
|
+
}) => {
|
|
243
|
+
const frame = useCurrentFrame5();
|
|
244
|
+
const localFrame = Math.max(0, frame - delay);
|
|
245
|
+
const pulseDuration = durationInFrames / pulses;
|
|
246
|
+
const pulseFrame = localFrame % pulseDuration;
|
|
247
|
+
const t = Math.min(1, pulseFrame / Math.max(1, pulseDuration));
|
|
248
|
+
const isActive = localFrame < durationInFrames;
|
|
249
|
+
const bellT = isActive ? Math.sin(t * Math.PI) : 0;
|
|
250
|
+
const easedBell = smooth(bellT);
|
|
251
|
+
const scale = 1 + (scaleFactor - 1) * easedBell;
|
|
252
|
+
const glowOpacity = easedBell * 0.6;
|
|
253
|
+
return /* @__PURE__ */ React6.createElement(
|
|
254
|
+
"div",
|
|
255
|
+
{
|
|
256
|
+
style: {
|
|
257
|
+
display: "inline-block",
|
|
258
|
+
transform: `scale(${scale})`,
|
|
259
|
+
transformOrigin: "center center",
|
|
260
|
+
filter: glowOpacity > 0.01 ? `drop-shadow(0 0 ${8 * glowOpacity}px ${color})` : void 0,
|
|
261
|
+
...style
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
children
|
|
265
|
+
);
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// ../execution/animate/src/animations/Wiggle.tsx
|
|
269
|
+
import React7 from "react";
|
|
270
|
+
import { useCurrentFrame as useCurrentFrame6 } from "remotion";
|
|
271
|
+
var Wiggle = ({
|
|
272
|
+
children,
|
|
273
|
+
angle = 8,
|
|
274
|
+
xAmplitude = 4,
|
|
275
|
+
yAmplitude = 2,
|
|
276
|
+
durationInFrames = 30,
|
|
277
|
+
delay = 0,
|
|
278
|
+
cycles = 3,
|
|
279
|
+
style
|
|
280
|
+
}) => {
|
|
281
|
+
const frame = useCurrentFrame6();
|
|
282
|
+
const localFrame = Math.max(0, frame - delay);
|
|
283
|
+
const t = Math.min(1, localFrame / Math.max(1, durationInFrames));
|
|
284
|
+
const decay = Math.exp(-4 * t);
|
|
285
|
+
const phase = t * cycles * Math.PI * 2;
|
|
286
|
+
const oscillation = Math.sin(phase);
|
|
287
|
+
const rotation = angle * oscillation * decay;
|
|
288
|
+
const dx = xAmplitude * oscillation * decay;
|
|
289
|
+
const dy = yAmplitude * Math.cos(phase * 1.3) * decay;
|
|
290
|
+
const isActive = localFrame < durationInFrames;
|
|
291
|
+
return /* @__PURE__ */ React7.createElement(
|
|
292
|
+
"div",
|
|
293
|
+
{
|
|
294
|
+
style: {
|
|
295
|
+
display: "inline-block",
|
|
296
|
+
transform: isActive ? `translate(${dx.toFixed(2)}px, ${dy.toFixed(2)}px) rotate(${rotation.toFixed(2)}deg)` : void 0,
|
|
297
|
+
transformOrigin: "center center",
|
|
298
|
+
...style
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
children
|
|
302
|
+
);
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
// ../execution/animate/src/composition/LaggedStart.tsx
|
|
306
|
+
import React8 from "react";
|
|
307
|
+
import { useCurrentFrame as useCurrentFrame7 } from "remotion";
|
|
308
|
+
var LaggedStart = ({
|
|
309
|
+
children,
|
|
310
|
+
lagRatio = 0.3,
|
|
311
|
+
durationInFrames = 60,
|
|
312
|
+
delay = 0,
|
|
313
|
+
easing = smooth,
|
|
314
|
+
style
|
|
315
|
+
}) => {
|
|
316
|
+
const frame = useCurrentFrame7();
|
|
317
|
+
const childArray = React8.Children.toArray(children);
|
|
318
|
+
const count = childArray.length;
|
|
319
|
+
if (count === 0) return null;
|
|
320
|
+
const staggerDelay = count > 1 ? lagRatio * durationInFrames / (count - 1) : 0;
|
|
321
|
+
const childDuration = durationInFrames - staggerDelay * Math.max(0, count - 1);
|
|
322
|
+
const effectiveChildDuration = Math.max(1, childDuration);
|
|
323
|
+
return /* @__PURE__ */ React8.createElement("div", { style }, childArray.map((child, index) => {
|
|
324
|
+
const childStart = delay + index * staggerDelay;
|
|
325
|
+
const localFrame = frame - childStart;
|
|
326
|
+
const t = Math.min(1, Math.max(0, localFrame / effectiveChildDuration));
|
|
327
|
+
const progress2 = easing(t);
|
|
328
|
+
return /* @__PURE__ */ React8.createElement(
|
|
329
|
+
"div",
|
|
330
|
+
{
|
|
331
|
+
key: index,
|
|
332
|
+
style: {
|
|
333
|
+
opacity: progress2,
|
|
334
|
+
transform: `scale(${0.8 + 0.2 * progress2})`,
|
|
335
|
+
transformOrigin: "center center"
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
child
|
|
339
|
+
);
|
|
340
|
+
}));
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
// ../execution/animate/src/composition/AnimationGroup.tsx
|
|
344
|
+
import React9 from "react";
|
|
345
|
+
import { useCurrentFrame as useCurrentFrame8 } from "remotion";
|
|
346
|
+
var AnimationGroup = ({
|
|
347
|
+
children,
|
|
348
|
+
stagger = 0,
|
|
349
|
+
delay = 0,
|
|
350
|
+
durationInFrames = 30,
|
|
351
|
+
easing = smooth,
|
|
352
|
+
style
|
|
353
|
+
}) => {
|
|
354
|
+
const frame = useCurrentFrame8();
|
|
355
|
+
const childArray = React9.Children.toArray(children);
|
|
356
|
+
if (childArray.length === 0) return null;
|
|
357
|
+
return /* @__PURE__ */ React9.createElement("div", { style }, childArray.map((child, index) => {
|
|
358
|
+
const childStart = delay + index * stagger;
|
|
359
|
+
const localFrame = frame - childStart;
|
|
360
|
+
const t = Math.min(1, Math.max(0, localFrame / Math.max(1, durationInFrames)));
|
|
361
|
+
const progress2 = easing(t);
|
|
362
|
+
return /* @__PURE__ */ React9.createElement(
|
|
363
|
+
"div",
|
|
364
|
+
{
|
|
365
|
+
key: index,
|
|
366
|
+
style: {
|
|
367
|
+
opacity: progress2
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
child
|
|
371
|
+
);
|
|
372
|
+
}));
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
// ../execution/animate/src/composition/Succession.tsx
|
|
376
|
+
import React10 from "react";
|
|
377
|
+
import { useCurrentFrame as useCurrentFrame9 } from "remotion";
|
|
378
|
+
var Succession = ({
|
|
379
|
+
children,
|
|
380
|
+
durationPerChild = 30,
|
|
381
|
+
delay = 0,
|
|
382
|
+
easing = smooth,
|
|
383
|
+
style
|
|
384
|
+
}) => {
|
|
385
|
+
const frame = useCurrentFrame9();
|
|
386
|
+
const childArray = React10.Children.toArray(children);
|
|
387
|
+
if (childArray.length === 0) return null;
|
|
388
|
+
return /* @__PURE__ */ React10.createElement("div", { style }, childArray.map((child, index) => {
|
|
389
|
+
const childStart = delay + index * durationPerChild;
|
|
390
|
+
const localFrame = frame - childStart;
|
|
391
|
+
const t = Math.min(1, Math.max(0, localFrame / Math.max(1, durationPerChild)));
|
|
392
|
+
const progress2 = easing(t);
|
|
393
|
+
return /* @__PURE__ */ React10.createElement(
|
|
394
|
+
"div",
|
|
395
|
+
{
|
|
396
|
+
key: index,
|
|
397
|
+
style: {
|
|
398
|
+
opacity: progress2
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
child
|
|
402
|
+
);
|
|
403
|
+
}));
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
// ../execution/animate/src/animations/Transform.tsx
|
|
407
|
+
import React11 from "react";
|
|
408
|
+
import { useCurrentFrame as useCurrentFrame10, interpolate as interpolate2 } from "remotion";
|
|
409
|
+
import { interpolatePath } from "@remotion/paths";
|
|
410
|
+
var Transform = ({
|
|
411
|
+
fromPath,
|
|
412
|
+
toPath,
|
|
413
|
+
stroke = "currentColor",
|
|
414
|
+
strokeWidth = 2,
|
|
415
|
+
fill = "none",
|
|
416
|
+
width = "100%",
|
|
417
|
+
height = "100%",
|
|
418
|
+
viewBox = "0 0 1920 1080",
|
|
419
|
+
durationInFrames = 30,
|
|
420
|
+
delay = 0,
|
|
421
|
+
easing = smooth,
|
|
422
|
+
fadeEdges = false,
|
|
423
|
+
style
|
|
424
|
+
}) => {
|
|
425
|
+
const frame = useCurrentFrame10();
|
|
426
|
+
const t = Math.min(1, Math.max(0, (frame - delay) / Math.max(1, durationInFrames)));
|
|
427
|
+
const progress2 = easing(t);
|
|
428
|
+
const currentPath = interpolatePath(progress2, fromPath, toPath);
|
|
429
|
+
const opacity = fadeEdges ? interpolate2(t, [0, 0.1, 0.9, 1], [0, 1, 1, 0], {
|
|
430
|
+
extrapolateLeft: "clamp",
|
|
431
|
+
extrapolateRight: "clamp"
|
|
432
|
+
}) : progress2;
|
|
433
|
+
return /* @__PURE__ */ React11.createElement("svg", { width, height, viewBox, style: { ...style, opacity } }, /* @__PURE__ */ React11.createElement(
|
|
434
|
+
"path",
|
|
435
|
+
{
|
|
436
|
+
d: currentPath,
|
|
437
|
+
stroke,
|
|
438
|
+
strokeWidth,
|
|
439
|
+
fill,
|
|
440
|
+
strokeLinecap: "round",
|
|
441
|
+
strokeLinejoin: "round"
|
|
442
|
+
}
|
|
443
|
+
));
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
// ../execution/animate/src/animations/MoveAlongPath.tsx
|
|
447
|
+
import React12 from "react";
|
|
448
|
+
import { useCurrentFrame as useCurrentFrame11 } from "remotion";
|
|
449
|
+
import { getLength, getPointAtLength, getTangentAtLength } from "@remotion/paths";
|
|
450
|
+
var MoveAlongPath = ({
|
|
451
|
+
children,
|
|
452
|
+
path,
|
|
453
|
+
durationInFrames = 60,
|
|
454
|
+
delay = 0,
|
|
455
|
+
easing = smooth,
|
|
456
|
+
rotate = false,
|
|
457
|
+
style
|
|
458
|
+
}) => {
|
|
459
|
+
const frame = useCurrentFrame11();
|
|
460
|
+
const t = Math.min(1, Math.max(0, (frame - delay) / Math.max(1, durationInFrames)));
|
|
461
|
+
const progress2 = easing(t);
|
|
462
|
+
const pathLength = getLength(path);
|
|
463
|
+
const distance = progress2 * pathLength;
|
|
464
|
+
const point = getPointAtLength(path, distance);
|
|
465
|
+
let rotation = 0;
|
|
466
|
+
if (rotate) {
|
|
467
|
+
const tangent = getTangentAtLength(path, distance);
|
|
468
|
+
rotation = Math.atan2(tangent.y - point.y, tangent.x - point.x) * (180 / Math.PI);
|
|
469
|
+
}
|
|
470
|
+
return /* @__PURE__ */ React12.createElement(
|
|
471
|
+
"div",
|
|
472
|
+
{
|
|
473
|
+
style: {
|
|
474
|
+
position: "absolute",
|
|
475
|
+
left: 0,
|
|
476
|
+
top: 0,
|
|
477
|
+
transform: `translate(${point.x}px, ${point.y}px) translate(-50%, -50%)${rotate ? ` rotate(${rotation}deg)` : ""}`,
|
|
478
|
+
...style
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
children
|
|
482
|
+
);
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// ../execution/animate/src/animations/GrowArrow.tsx
|
|
486
|
+
import React13 from "react";
|
|
487
|
+
import { useCurrentFrame as useCurrentFrame12 } from "remotion";
|
|
488
|
+
import { evolvePath as evolvePath2 } from "@remotion/paths";
|
|
489
|
+
var GrowArrow = ({
|
|
490
|
+
from,
|
|
491
|
+
to,
|
|
492
|
+
color = "currentColor",
|
|
493
|
+
strokeWidth = 2,
|
|
494
|
+
tipSize = 12,
|
|
495
|
+
width = "100%",
|
|
496
|
+
height = "100%",
|
|
497
|
+
viewBox = "0 0 1920 1080",
|
|
498
|
+
durationInFrames = 30,
|
|
499
|
+
delay = 0,
|
|
500
|
+
easing = smooth,
|
|
501
|
+
style
|
|
502
|
+
}) => {
|
|
503
|
+
const frame = useCurrentFrame12();
|
|
504
|
+
const t = Math.min(1, Math.max(0, (frame - delay) / Math.max(1, durationInFrames)));
|
|
505
|
+
const progress2 = easing(t);
|
|
506
|
+
const markerId = React13.useId();
|
|
507
|
+
const endId = `grow-arrow-${markerId}`;
|
|
508
|
+
const markerW = tipSize;
|
|
509
|
+
const markerH = tipSize * 0.7;
|
|
510
|
+
const path = `M ${from[0]},${from[1]} L ${to[0]},${to[1]}`;
|
|
511
|
+
const evolved = evolvePath2(progress2, path);
|
|
512
|
+
const tipOpacity = Math.min(1, Math.max(0, (progress2 - 0.8) / 0.2));
|
|
513
|
+
return /* @__PURE__ */ React13.createElement("svg", { width, height, viewBox, style }, /* @__PURE__ */ React13.createElement("defs", null, /* @__PURE__ */ React13.createElement(
|
|
514
|
+
"marker",
|
|
515
|
+
{
|
|
516
|
+
id: endId,
|
|
517
|
+
markerWidth: markerW,
|
|
518
|
+
markerHeight: markerH,
|
|
519
|
+
refX: markerW,
|
|
520
|
+
refY: markerH / 2,
|
|
521
|
+
orient: "auto",
|
|
522
|
+
markerUnits: "userSpaceOnUse"
|
|
523
|
+
},
|
|
524
|
+
/* @__PURE__ */ React13.createElement(
|
|
525
|
+
"polygon",
|
|
526
|
+
{
|
|
527
|
+
points: `0,0 ${markerW},${markerH / 2} 0,${markerH}`,
|
|
528
|
+
fill: color,
|
|
529
|
+
opacity: tipOpacity
|
|
530
|
+
}
|
|
531
|
+
)
|
|
532
|
+
)), /* @__PURE__ */ React13.createElement(
|
|
533
|
+
"path",
|
|
534
|
+
{
|
|
535
|
+
d: path,
|
|
536
|
+
stroke: color,
|
|
537
|
+
strokeWidth,
|
|
538
|
+
fill: "none",
|
|
539
|
+
strokeLinecap: "round",
|
|
540
|
+
strokeDasharray: evolved.strokeDasharray,
|
|
541
|
+
strokeDashoffset: evolved.strokeDashoffset,
|
|
542
|
+
markerEnd: `url(#${endId})`
|
|
543
|
+
}
|
|
544
|
+
));
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
// ../execution/animate/src/mobjects/Arrow.tsx
|
|
548
|
+
import React14 from "react";
|
|
549
|
+
var Arrow = ({
|
|
550
|
+
from,
|
|
551
|
+
to,
|
|
552
|
+
color = "currentColor",
|
|
553
|
+
strokeWidth = 2,
|
|
554
|
+
tipSize = 12,
|
|
555
|
+
width = "100%",
|
|
556
|
+
height = "100%",
|
|
557
|
+
viewBox = "0 0 1920 1080",
|
|
558
|
+
doubleEnded = false,
|
|
559
|
+
style
|
|
560
|
+
}) => {
|
|
561
|
+
const markerId = React14.useId();
|
|
562
|
+
const endId = `arrow-end-${markerId}`;
|
|
563
|
+
const startId = `arrow-start-${markerId}`;
|
|
564
|
+
const markerW = tipSize;
|
|
565
|
+
const markerH = tipSize * 0.7;
|
|
566
|
+
return /* @__PURE__ */ React14.createElement("svg", { width, height, viewBox, style }, /* @__PURE__ */ React14.createElement("defs", null, /* @__PURE__ */ React14.createElement(
|
|
567
|
+
"marker",
|
|
568
|
+
{
|
|
569
|
+
id: endId,
|
|
570
|
+
markerWidth: markerW,
|
|
571
|
+
markerHeight: markerH,
|
|
572
|
+
refX: markerW,
|
|
573
|
+
refY: markerH / 2,
|
|
574
|
+
orient: "auto",
|
|
575
|
+
markerUnits: "userSpaceOnUse"
|
|
576
|
+
},
|
|
577
|
+
/* @__PURE__ */ React14.createElement(
|
|
578
|
+
"polygon",
|
|
579
|
+
{
|
|
580
|
+
points: `0,0 ${markerW},${markerH / 2} 0,${markerH}`,
|
|
581
|
+
fill: color
|
|
582
|
+
}
|
|
583
|
+
)
|
|
584
|
+
), doubleEnded && /* @__PURE__ */ React14.createElement(
|
|
585
|
+
"marker",
|
|
586
|
+
{
|
|
587
|
+
id: startId,
|
|
588
|
+
markerWidth: markerW,
|
|
589
|
+
markerHeight: markerH,
|
|
590
|
+
refX: 0,
|
|
591
|
+
refY: markerH / 2,
|
|
592
|
+
orient: "auto-start-reverse",
|
|
593
|
+
markerUnits: "userSpaceOnUse"
|
|
594
|
+
},
|
|
595
|
+
/* @__PURE__ */ React14.createElement(
|
|
596
|
+
"polygon",
|
|
597
|
+
{
|
|
598
|
+
points: `0,0 ${markerW},${markerH / 2} 0,${markerH}`,
|
|
599
|
+
fill: color
|
|
600
|
+
}
|
|
601
|
+
)
|
|
602
|
+
)), /* @__PURE__ */ React14.createElement(
|
|
603
|
+
"line",
|
|
604
|
+
{
|
|
605
|
+
x1: from[0],
|
|
606
|
+
y1: from[1],
|
|
607
|
+
x2: to[0],
|
|
608
|
+
y2: to[1],
|
|
609
|
+
stroke: color,
|
|
610
|
+
strokeWidth,
|
|
611
|
+
strokeLinecap: "round",
|
|
612
|
+
markerEnd: `url(#${endId})`,
|
|
613
|
+
markerStart: doubleEnded ? `url(#${startId})` : void 0
|
|
614
|
+
}
|
|
615
|
+
));
|
|
616
|
+
};
|
|
617
|
+
function makeArrowPath(from, to) {
|
|
618
|
+
return `M ${from[0]},${from[1]} L ${to[0]},${to[1]}`;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// ../execution/animate/src/mobjects/BrandBox.tsx
|
|
622
|
+
import React15 from "react";
|
|
623
|
+
var BrandBox = ({
|
|
624
|
+
label,
|
|
625
|
+
color = "#1a1a2e",
|
|
626
|
+
width = 160,
|
|
627
|
+
height = 80,
|
|
628
|
+
borderRadius = 12,
|
|
629
|
+
fontFamily,
|
|
630
|
+
fontSize = 18,
|
|
631
|
+
fontWeight = 600,
|
|
632
|
+
textColor = "#fff",
|
|
633
|
+
border,
|
|
634
|
+
shadow,
|
|
635
|
+
children,
|
|
636
|
+
style
|
|
637
|
+
}) => {
|
|
638
|
+
return /* @__PURE__ */ React15.createElement(
|
|
639
|
+
"div",
|
|
640
|
+
{
|
|
641
|
+
style: {
|
|
642
|
+
display: "inline-flex",
|
|
643
|
+
alignItems: "center",
|
|
644
|
+
justifyContent: "center",
|
|
645
|
+
width,
|
|
646
|
+
height,
|
|
647
|
+
borderRadius,
|
|
648
|
+
background: color,
|
|
649
|
+
border,
|
|
650
|
+
boxShadow: shadow,
|
|
651
|
+
...style
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
children ?? /* @__PURE__ */ React15.createElement(
|
|
655
|
+
"span",
|
|
656
|
+
{
|
|
657
|
+
style: {
|
|
658
|
+
fontFamily,
|
|
659
|
+
fontSize,
|
|
660
|
+
fontWeight,
|
|
661
|
+
color: textColor,
|
|
662
|
+
letterSpacing: "0.02em",
|
|
663
|
+
userSelect: "none"
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
label
|
|
667
|
+
)
|
|
668
|
+
);
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
// ../execution/animate/src/mobjects/Graph.tsx
|
|
672
|
+
import React16, { useMemo } from "react";
|
|
673
|
+
import { useCurrentFrame as useCurrentFrame13 } from "remotion";
|
|
674
|
+
import {
|
|
675
|
+
forceSimulation,
|
|
676
|
+
forceLink,
|
|
677
|
+
forceManyBody,
|
|
678
|
+
forceCenter,
|
|
679
|
+
forceCollide
|
|
680
|
+
} from "d3-force";
|
|
681
|
+
var Graph = ({
|
|
682
|
+
nodes,
|
|
683
|
+
edges,
|
|
684
|
+
directed = false,
|
|
685
|
+
width = 800,
|
|
686
|
+
height = 500,
|
|
687
|
+
nodeRadius = 24,
|
|
688
|
+
nodeColor = "#3b82f6",
|
|
689
|
+
edgeColor = "#666",
|
|
690
|
+
edgeWidth = 2,
|
|
691
|
+
fontFamily,
|
|
692
|
+
fontSize = 14,
|
|
693
|
+
textColor = "#fff",
|
|
694
|
+
chargeStrength = -300,
|
|
695
|
+
durationInFrames = 60,
|
|
696
|
+
delay = 0,
|
|
697
|
+
easing = smooth,
|
|
698
|
+
style
|
|
699
|
+
}) => {
|
|
700
|
+
const frame = useCurrentFrame13();
|
|
701
|
+
const nodesKey = JSON.stringify(nodes);
|
|
702
|
+
const edgesKey = JSON.stringify(edges);
|
|
703
|
+
const nodeMap = useMemo(() => {
|
|
704
|
+
const parsedNodes = JSON.parse(nodesKey);
|
|
705
|
+
const parsedEdges = JSON.parse(edgesKey);
|
|
706
|
+
const simNodes = parsedNodes.map((n) => ({
|
|
707
|
+
id: n.id,
|
|
708
|
+
x: n.position ? n.position[0] : void 0,
|
|
709
|
+
y: n.position ? n.position[1] : void 0,
|
|
710
|
+
fx: n.position ? n.position[0] : void 0,
|
|
711
|
+
fy: n.position ? n.position[1] : void 0
|
|
712
|
+
}));
|
|
713
|
+
const simLinks = parsedEdges.map((e) => ({
|
|
714
|
+
source: e.source,
|
|
715
|
+
target: e.target
|
|
716
|
+
}));
|
|
717
|
+
const sim = forceSimulation(simNodes).force("link", forceLink(simLinks).id((d) => d.id).distance(120)).force("charge", forceManyBody().strength(chargeStrength)).force("center", forceCenter(width / 2, height / 2)).force("collide", forceCollide(nodeRadius * 2)).stop();
|
|
718
|
+
for (let i = 0; i < 300; i++) sim.tick();
|
|
719
|
+
const map = /* @__PURE__ */ new Map();
|
|
720
|
+
for (const n of simNodes) {
|
|
721
|
+
map.set(n.id, { x: n.x ?? 0, y: n.y ?? 0 });
|
|
722
|
+
}
|
|
723
|
+
return map;
|
|
724
|
+
}, [nodesKey, edgesKey, width, height, nodeRadius, chargeStrength]);
|
|
725
|
+
const nodeCount = nodes.length;
|
|
726
|
+
const edgeCount = edges.length;
|
|
727
|
+
const totalItems = edgeCount + nodeCount;
|
|
728
|
+
const markerId = React16.useId();
|
|
729
|
+
const uniqueEdgeColors = useMemo(() => {
|
|
730
|
+
if (!directed) return [];
|
|
731
|
+
const colors = /* @__PURE__ */ new Set();
|
|
732
|
+
colors.add(edgeColor);
|
|
733
|
+
for (const e of edges) {
|
|
734
|
+
if (e.color) colors.add(e.color);
|
|
735
|
+
}
|
|
736
|
+
return Array.from(colors);
|
|
737
|
+
}, [directed, edgeColor, edgesKey]);
|
|
738
|
+
const markerIdFor = (color) => `graph-arrow-${markerId}-${color.replace(/[^a-zA-Z0-9]/g, "")}`;
|
|
739
|
+
return /* @__PURE__ */ React16.createElement("svg", { width, height, style }, directed && /* @__PURE__ */ React16.createElement("defs", null, uniqueEdgeColors.map((c) => /* @__PURE__ */ React16.createElement(
|
|
740
|
+
"marker",
|
|
741
|
+
{
|
|
742
|
+
key: c,
|
|
743
|
+
id: markerIdFor(c),
|
|
744
|
+
markerWidth: 10,
|
|
745
|
+
markerHeight: 7,
|
|
746
|
+
refX: nodeRadius + 10,
|
|
747
|
+
refY: 3.5,
|
|
748
|
+
orient: "auto",
|
|
749
|
+
markerUnits: "userSpaceOnUse"
|
|
750
|
+
},
|
|
751
|
+
/* @__PURE__ */ React16.createElement("polygon", { points: "0,0 10,3.5 0,7", fill: c })
|
|
752
|
+
))), edges.map((edge, i) => {
|
|
753
|
+
const s = nodeMap.get(edge.source);
|
|
754
|
+
const t = nodeMap.get(edge.target);
|
|
755
|
+
if (!s || !t) return null;
|
|
756
|
+
const stagger = totalItems > 1 ? durationInFrames * 0.6 / totalItems : 0;
|
|
757
|
+
const edgeStart = delay + i * stagger;
|
|
758
|
+
const localFrame = frame - edgeStart;
|
|
759
|
+
const edgeDur = Math.max(4, durationInFrames * 0.3);
|
|
760
|
+
const tVal = Math.min(1, Math.max(0, localFrame / edgeDur));
|
|
761
|
+
const progress2 = easing(tVal);
|
|
762
|
+
const eColor = edge.color ?? edgeColor;
|
|
763
|
+
return /* @__PURE__ */ React16.createElement("g", { key: `e-${i}` }, /* @__PURE__ */ React16.createElement(
|
|
764
|
+
"line",
|
|
765
|
+
{
|
|
766
|
+
x1: s.x,
|
|
767
|
+
y1: s.y,
|
|
768
|
+
x2: s.x + (t.x - s.x) * progress2,
|
|
769
|
+
y2: s.y + (t.y - s.y) * progress2,
|
|
770
|
+
stroke: eColor,
|
|
771
|
+
strokeWidth: edgeWidth,
|
|
772
|
+
strokeLinecap: "round",
|
|
773
|
+
markerEnd: directed && progress2 > 0.9 ? `url(#${markerIdFor(eColor)})` : void 0
|
|
774
|
+
}
|
|
775
|
+
), edge.label && progress2 > 0.5 && /* @__PURE__ */ React16.createElement(
|
|
776
|
+
"text",
|
|
777
|
+
{
|
|
778
|
+
x: (s.x + t.x) / 2,
|
|
779
|
+
y: (s.y + t.y) / 2 - 8,
|
|
780
|
+
textAnchor: "middle",
|
|
781
|
+
fill: eColor,
|
|
782
|
+
fontSize: fontSize * 0.85,
|
|
783
|
+
fontFamily,
|
|
784
|
+
opacity: Math.min(1, (progress2 - 0.5) * 2)
|
|
785
|
+
},
|
|
786
|
+
edge.label
|
|
787
|
+
));
|
|
788
|
+
}), nodes.map((node, i) => {
|
|
789
|
+
const pos = nodeMap.get(node.id);
|
|
790
|
+
if (!pos) return null;
|
|
791
|
+
const itemIndex = edgeCount + i;
|
|
792
|
+
const stagger = totalItems > 1 ? durationInFrames * 0.6 / totalItems : 0;
|
|
793
|
+
const nodeStart = delay + itemIndex * stagger;
|
|
794
|
+
const localFrame = frame - nodeStart;
|
|
795
|
+
const nodeDur = Math.max(4, durationInFrames * 0.3);
|
|
796
|
+
const tVal = Math.min(1, Math.max(0, localFrame / nodeDur));
|
|
797
|
+
const progress2 = easing(tVal);
|
|
798
|
+
const nColor = node.color ?? nodeColor;
|
|
799
|
+
return /* @__PURE__ */ React16.createElement(
|
|
800
|
+
"g",
|
|
801
|
+
{
|
|
802
|
+
key: `n-${node.id}`,
|
|
803
|
+
transform: `translate(${pos.x}, ${pos.y}) scale(${progress2})`
|
|
804
|
+
},
|
|
805
|
+
/* @__PURE__ */ React16.createElement(
|
|
806
|
+
"circle",
|
|
807
|
+
{
|
|
808
|
+
r: nodeRadius,
|
|
809
|
+
fill: nColor,
|
|
810
|
+
opacity: progress2
|
|
811
|
+
}
|
|
812
|
+
),
|
|
813
|
+
node.label && /* @__PURE__ */ React16.createElement(
|
|
814
|
+
"text",
|
|
815
|
+
{
|
|
816
|
+
textAnchor: "middle",
|
|
817
|
+
dominantBaseline: "central",
|
|
818
|
+
fill: textColor,
|
|
819
|
+
fontSize,
|
|
820
|
+
fontFamily,
|
|
821
|
+
fontWeight: 600
|
|
822
|
+
},
|
|
823
|
+
node.label
|
|
824
|
+
)
|
|
825
|
+
);
|
|
826
|
+
}));
|
|
827
|
+
};
|
|
828
|
+
|
|
829
|
+
// ../execution/animate/src/mobjects/DiGraph.tsx
|
|
830
|
+
import React17 from "react";
|
|
831
|
+
var DiGraph = (props) => {
|
|
832
|
+
return /* @__PURE__ */ React17.createElement(Graph, { ...props, directed: true });
|
|
833
|
+
};
|
|
834
|
+
|
|
835
|
+
// ../execution/animate/src/stage/camera.ts
|
|
836
|
+
import { Euler, Matrix4, Quaternion, Vector3 } from "three";
|
|
837
|
+
var DEFAULT_CAMERA = { x: 0, y: 0, z: 0, rotX: 0, rotY: 0, rotZ: 0, fov: 40 };
|
|
838
|
+
var DEG = Math.PI / 180;
|
|
839
|
+
function perspectiveFor(fov, height) {
|
|
840
|
+
return height / 2 / Math.tan(fov * DEG / 2);
|
|
841
|
+
}
|
|
842
|
+
function cameraOps(c) {
|
|
843
|
+
return [
|
|
844
|
+
{ kind: "translate3d", x: -c.x, y: -c.y, z: -c.z },
|
|
845
|
+
{ kind: "rotateX", deg: -c.rotX },
|
|
846
|
+
{ kind: "rotateY", deg: -c.rotY },
|
|
847
|
+
{ kind: "rotateZ", deg: -c.rotZ }
|
|
848
|
+
];
|
|
849
|
+
}
|
|
850
|
+
function opCss(op) {
|
|
851
|
+
return op.kind === "translate3d" ? `translate3d(${op.x}px, ${op.y}px, ${op.z}px)` : `${op.kind}(${op.deg}deg)`;
|
|
852
|
+
}
|
|
853
|
+
function opMatrix(op) {
|
|
854
|
+
switch (op.kind) {
|
|
855
|
+
case "translate3d":
|
|
856
|
+
return new Matrix4().makeTranslation(op.x, op.y, op.z);
|
|
857
|
+
case "rotateX":
|
|
858
|
+
return new Matrix4().makeRotationX(op.deg * DEG);
|
|
859
|
+
case "rotateY":
|
|
860
|
+
return new Matrix4().makeRotationY(op.deg * DEG);
|
|
861
|
+
case "rotateZ":
|
|
862
|
+
return new Matrix4().makeRotationZ(op.deg * DEG);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
function worldTransform(c) {
|
|
866
|
+
return cameraOps(c).map(opCss).join(" ");
|
|
867
|
+
}
|
|
868
|
+
var KEYS = ["x", "y", "z", "rotX", "rotY", "rotZ", "fov"];
|
|
869
|
+
function resolveCamera(keyframes, frame, base = DEFAULT_CAMERA) {
|
|
870
|
+
if (keyframes.length === 0) return { ...base };
|
|
871
|
+
const sorted = [...keyframes].sort((a2, b2) => a2.frame - b2.frame);
|
|
872
|
+
const full = [];
|
|
873
|
+
for (let i2 = 0; i2 < sorted.length; i2++) {
|
|
874
|
+
full.push({ ...i2 === 0 ? base : full[i2 - 1], ...sorted[i2].camera });
|
|
875
|
+
}
|
|
876
|
+
if (frame <= sorted[0].frame) return { ...full[0] };
|
|
877
|
+
const last = sorted.length - 1;
|
|
878
|
+
if (frame >= sorted[last].frame) return { ...full[last] };
|
|
879
|
+
let i = 0;
|
|
880
|
+
while (frame > sorted[i + 1].frame) i++;
|
|
881
|
+
const a = sorted[i], b = sorted[i + 1];
|
|
882
|
+
const span = Math.max(1, b.frame - a.frame);
|
|
883
|
+
const t = (b.easing ?? ((v) => v))((frame - a.frame) / span);
|
|
884
|
+
const out = { ...full[i] };
|
|
885
|
+
for (const k of KEYS) out[k] = full[i][k] + (full[i + 1][k] - full[i][k]) * t;
|
|
886
|
+
return out;
|
|
887
|
+
}
|
|
888
|
+
function cameraOpsMatrix(c) {
|
|
889
|
+
const m = new Matrix4();
|
|
890
|
+
for (const op of cameraOps(c)) m.multiply(opMatrix(op));
|
|
891
|
+
return m;
|
|
892
|
+
}
|
|
893
|
+
var FLIP_Y = new Matrix4().makeScale(1, -1, 1);
|
|
894
|
+
function cameraToThree(c, width, height) {
|
|
895
|
+
const P = perspectiveFor(c.fov, height);
|
|
896
|
+
const pose = cameraOpsMatrix(c).invert().multiply(new Matrix4().makeTranslation(0, 0, P));
|
|
897
|
+
const three = FLIP_Y.clone().multiply(pose).multiply(FLIP_Y);
|
|
898
|
+
const position = new Vector3(), quaternion = new Quaternion(), scale = new Vector3();
|
|
899
|
+
three.decompose(position, quaternion, scale);
|
|
900
|
+
return {
|
|
901
|
+
position: [position.x, position.y, position.z],
|
|
902
|
+
quaternion: [quaternion.x, quaternion.y, quaternion.z, quaternion.w],
|
|
903
|
+
fov: c.fov,
|
|
904
|
+
aspect: width / height,
|
|
905
|
+
near: P / 100,
|
|
906
|
+
far: P * 40
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
var SCENE_DEFAULT_FOV = 40 * Math.PI / 180;
|
|
910
|
+
var SCENE_FOV_MIN = 18 * Math.PI / 180;
|
|
911
|
+
var SCENE_FOV_MAX = 80 * Math.PI / 180;
|
|
912
|
+
function sceneEyeDistance(referenceHeight, fov) {
|
|
913
|
+
return referenceHeight / (2 * Math.tan(fov / 2));
|
|
914
|
+
}
|
|
915
|
+
function defaultSceneCamera(referenceHeight, fov = SCENE_DEFAULT_FOV) {
|
|
916
|
+
return { position: [0, 0, sceneEyeDistance(referenceHeight, fov)], rotation: [0, 0, 0], fov };
|
|
917
|
+
}
|
|
918
|
+
var sceneCameraPlanes = sceneCameraPlanesV2;
|
|
919
|
+
function sceneCameraPose(camera, referenceHeight, scale, frame) {
|
|
920
|
+
const q = new Quaternion().setFromEuler(new Euler(camera.rotation[0], camera.rotation[1], camera.rotation[2], "XYZ"));
|
|
921
|
+
return {
|
|
922
|
+
position: [camera.position[0] * scale, camera.position[1] * scale, camera.position[2] * scale],
|
|
923
|
+
quaternion: [q.x, q.y, q.z, q.w],
|
|
924
|
+
fov: camera.fov,
|
|
925
|
+
aspect: frame.width / frame.height,
|
|
926
|
+
...sceneCameraPlanes(referenceHeight, camera.fov, scale)
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
function sceneCameraPoseFromV1(camera, referenceHeight, scale, frame) {
|
|
930
|
+
const fov = camera.fov * DEG;
|
|
931
|
+
const p = sceneEyeDistance(referenceHeight, fov) * scale;
|
|
932
|
+
const q = new Quaternion().setFromEuler(new Euler(-camera.rotX * DEG, camera.rotY * DEG, -camera.rotZ * DEG, "ZYX"));
|
|
933
|
+
const position = new Vector3(camera.x, -camera.y, camera.z + p).applyQuaternion(q);
|
|
934
|
+
return {
|
|
935
|
+
position: [position.x, position.y, position.z],
|
|
936
|
+
quaternion: [q.x, q.y, q.z, q.w],
|
|
937
|
+
fov,
|
|
938
|
+
aspect: frame.width / frame.height,
|
|
939
|
+
near: p / 100,
|
|
940
|
+
far: p * 40
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
// ../execution/animate/src/three/StageCameraRig.tsx
|
|
945
|
+
import { useLayoutEffect } from "react";
|
|
946
|
+
import { useThree } from "@react-three/fiber";
|
|
947
|
+
import { PerspectiveCamera } from "three";
|
|
948
|
+
function StageCameraRig({ camera, width, height }) {
|
|
949
|
+
const three = useThree((s) => s.camera);
|
|
950
|
+
const { x, y, z, rotX, rotY, rotZ, fov } = camera;
|
|
951
|
+
useLayoutEffect(() => {
|
|
952
|
+
if (!(three instanceof PerspectiveCamera)) return;
|
|
953
|
+
const pose = cameraToThree({ x, y, z, rotX, rotY, rotZ, fov }, width, height);
|
|
954
|
+
three.position.set(...pose.position);
|
|
955
|
+
three.quaternion.set(...pose.quaternion);
|
|
956
|
+
three.fov = pose.fov;
|
|
957
|
+
three.aspect = pose.aspect;
|
|
958
|
+
three.near = pose.near;
|
|
959
|
+
three.far = pose.far;
|
|
960
|
+
three.updateProjectionMatrix();
|
|
961
|
+
three.updateMatrixWorld(true);
|
|
962
|
+
}, [three, x, y, z, rotX, rotY, rotZ, fov, width, height]);
|
|
963
|
+
return null;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// ../execution/animate/src/three/ThreeCanvas.tsx
|
|
967
|
+
import React18, { useMemo as useMemo2 } from "react";
|
|
968
|
+
import { ThreeCanvas as RemotionThreeCanvas } from "@remotion/three";
|
|
969
|
+
|
|
970
|
+
// ../execution/animate/src/three/SceneCameraRig.tsx
|
|
971
|
+
import { useLayoutEffect as useLayoutEffect2 } from "react";
|
|
972
|
+
import { useThree as useThree2 } from "@react-three/fiber";
|
|
973
|
+
import { PerspectiveCamera as PerspectiveCamera2 } from "three";
|
|
974
|
+
function SceneCameraRig({ pose }) {
|
|
975
|
+
const three = useThree2((s) => s.camera);
|
|
976
|
+
const [px, py, pz] = pose.position;
|
|
977
|
+
const [qx, qy, qz, qw] = pose.quaternion;
|
|
978
|
+
const { fov, aspect, near, far } = pose;
|
|
979
|
+
useLayoutEffect2(() => {
|
|
980
|
+
if (!(three instanceof PerspectiveCamera2)) return;
|
|
981
|
+
three.position.set(px, py, pz);
|
|
982
|
+
three.quaternion.set(qx, qy, qz, qw);
|
|
983
|
+
three.fov = fov * 180 / Math.PI;
|
|
984
|
+
three.aspect = aspect;
|
|
985
|
+
three.near = near;
|
|
986
|
+
three.far = far;
|
|
987
|
+
three.updateProjectionMatrix();
|
|
988
|
+
three.updateMatrixWorld(true);
|
|
989
|
+
}, [three, px, py, pz, qx, qy, qz, qw, fov, aspect, near, far]);
|
|
990
|
+
return null;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// ../execution/animate/src/three/ThreeCanvas.tsx
|
|
994
|
+
var ThreeCanvas = ({
|
|
995
|
+
children,
|
|
996
|
+
width = 1920,
|
|
997
|
+
height = 1080,
|
|
998
|
+
fov = 75,
|
|
999
|
+
near,
|
|
1000
|
+
far,
|
|
1001
|
+
cameraPosition,
|
|
1002
|
+
orthographic = false,
|
|
1003
|
+
stageCamera,
|
|
1004
|
+
sceneCamera,
|
|
1005
|
+
shadows,
|
|
1006
|
+
dpr,
|
|
1007
|
+
gl,
|
|
1008
|
+
style
|
|
1009
|
+
}) => {
|
|
1010
|
+
const isOrthographic = orthographic && !stageCamera && !sceneCamera;
|
|
1011
|
+
const position = cameraPosition ?? (isOrthographic ? [0, 0, 100] : [0, 0, 5]);
|
|
1012
|
+
const sceneFov = sceneCamera ? sceneCamera.fov * 180 / Math.PI : null;
|
|
1013
|
+
const camera = useMemo2(
|
|
1014
|
+
() => {
|
|
1015
|
+
if (sceneCamera) {
|
|
1016
|
+
return { fov: sceneFov, near: sceneCamera.near, far: sceneCamera.far, position: sceneCamera.position };
|
|
1017
|
+
}
|
|
1018
|
+
if (stageCamera) {
|
|
1019
|
+
const pose = cameraToThree(stageCamera, width, height);
|
|
1020
|
+
return { fov: pose.fov, near: pose.near, far: pose.far, position: pose.position };
|
|
1021
|
+
}
|
|
1022
|
+
return isOrthographic ? {
|
|
1023
|
+
left: -width / 2,
|
|
1024
|
+
right: width / 2,
|
|
1025
|
+
top: height / 2,
|
|
1026
|
+
bottom: -height / 2,
|
|
1027
|
+
near: near ?? -5e3,
|
|
1028
|
+
far: far ?? 5e3,
|
|
1029
|
+
position
|
|
1030
|
+
} : {
|
|
1031
|
+
fov,
|
|
1032
|
+
near: near ?? 0.1,
|
|
1033
|
+
far: far ?? 1e3,
|
|
1034
|
+
position
|
|
1035
|
+
};
|
|
1036
|
+
},
|
|
1037
|
+
[sceneCamera, sceneFov, stageCamera, isOrthographic, width, height, fov, near, far, position[0], position[1], position[2]]
|
|
1038
|
+
);
|
|
1039
|
+
return /* @__PURE__ */ React18.createElement(
|
|
1040
|
+
RemotionThreeCanvas,
|
|
1041
|
+
{
|
|
1042
|
+
width,
|
|
1043
|
+
height,
|
|
1044
|
+
orthographic: isOrthographic,
|
|
1045
|
+
camera,
|
|
1046
|
+
shadows,
|
|
1047
|
+
dpr: dpr ?? 1,
|
|
1048
|
+
gl,
|
|
1049
|
+
style: {
|
|
1050
|
+
width: "100%",
|
|
1051
|
+
height: "100%",
|
|
1052
|
+
...style
|
|
1053
|
+
}
|
|
1054
|
+
},
|
|
1055
|
+
sceneCamera ? /* @__PURE__ */ React18.createElement(SceneCameraRig, { pose: sceneCamera }) : null,
|
|
1056
|
+
!sceneCamera && stageCamera ? /* @__PURE__ */ React18.createElement(StageCameraRig, { camera: stageCamera, width, height }) : null,
|
|
1057
|
+
children
|
|
1058
|
+
);
|
|
1059
|
+
};
|
|
1060
|
+
|
|
1061
|
+
// ../execution/animate/src/three/useImageTexture.ts
|
|
1062
|
+
import { useLayoutEffect as useLayoutEffect3, useRef, useState } from "react";
|
|
1063
|
+
import { cancelRender, continueRender, delayRender } from "remotion";
|
|
1064
|
+
import { SRGBColorSpace, TextureLoader } from "three";
|
|
1065
|
+
|
|
1066
|
+
// ../execution/animate/src/three/textureLifecycle.ts
|
|
1067
|
+
var NO_TEXTURE = { drawn: null };
|
|
1068
|
+
function commitImageTexture(held, next) {
|
|
1069
|
+
if (held.drawn && held.drawn !== next) held.drawn.dispose();
|
|
1070
|
+
return { drawn: next };
|
|
1071
|
+
}
|
|
1072
|
+
function releaseImageTexture(held) {
|
|
1073
|
+
held.drawn?.dispose();
|
|
1074
|
+
return NO_TEXTURE;
|
|
1075
|
+
}
|
|
1076
|
+
function discardStaleTexture(texture) {
|
|
1077
|
+
texture.dispose();
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
// ../execution/animate/src/three/useImageTexture.ts
|
|
1081
|
+
function useImageTexture(src) {
|
|
1082
|
+
const [texture, setTexture] = useState(null);
|
|
1083
|
+
const held = useRef(NO_TEXTURE);
|
|
1084
|
+
const [firstHandle] = useState(() => src ? delayRender(`three: load texture ${src}`) : null);
|
|
1085
|
+
const firstHandleSpent = useRef(false);
|
|
1086
|
+
useLayoutEffect3(() => {
|
|
1087
|
+
const takeHandle = () => {
|
|
1088
|
+
if (firstHandle !== null && !firstHandleSpent.current) {
|
|
1089
|
+
firstHandleSpent.current = true;
|
|
1090
|
+
return firstHandle;
|
|
1091
|
+
}
|
|
1092
|
+
return null;
|
|
1093
|
+
};
|
|
1094
|
+
if (!src) {
|
|
1095
|
+
const orphan = takeHandle();
|
|
1096
|
+
if (orphan !== null) continueRender(orphan);
|
|
1097
|
+
setTexture(null);
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
const handle = takeHandle() ?? delayRender(`three: load texture ${src}`);
|
|
1101
|
+
let disposed = false;
|
|
1102
|
+
new TextureLoader().load(
|
|
1103
|
+
src,
|
|
1104
|
+
(t) => {
|
|
1105
|
+
if (disposed) {
|
|
1106
|
+
discardStaleTexture(t);
|
|
1107
|
+
continueRender(handle);
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
t.colorSpace = SRGBColorSpace;
|
|
1111
|
+
t.anisotropy = 4;
|
|
1112
|
+
setTexture(t);
|
|
1113
|
+
continueRender(handle);
|
|
1114
|
+
},
|
|
1115
|
+
void 0,
|
|
1116
|
+
(err) => {
|
|
1117
|
+
if (disposed) {
|
|
1118
|
+
continueRender(handle);
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
cancelRender(err instanceof Error ? err : new Error(`texture failed: ${src}`));
|
|
1122
|
+
}
|
|
1123
|
+
);
|
|
1124
|
+
return () => {
|
|
1125
|
+
disposed = true;
|
|
1126
|
+
continueRender(handle);
|
|
1127
|
+
};
|
|
1128
|
+
}, [src, firstHandle]);
|
|
1129
|
+
useLayoutEffect3(() => {
|
|
1130
|
+
held.current = commitImageTexture(held.current, texture);
|
|
1131
|
+
}, [texture]);
|
|
1132
|
+
useLayoutEffect3(() => () => {
|
|
1133
|
+
held.current = releaseImageTexture(held.current);
|
|
1134
|
+
}, []);
|
|
1135
|
+
return texture;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
// ../execution/animate/src/three/defaultScreen.ts
|
|
1139
|
+
import { CanvasTexture, SRGBColorSpace as SRGBColorSpace2 } from "three";
|
|
1140
|
+
function defaultScreenLayout(w, h) {
|
|
1141
|
+
const pad = Math.round(w * 0.025);
|
|
1142
|
+
const sidebar = { x: pad, y: pad, w: Math.round(w * 0.18), h: h - pad * 2 };
|
|
1143
|
+
const contentX = sidebar.x + sidebar.w + pad;
|
|
1144
|
+
const contentW = w - contentX - pad;
|
|
1145
|
+
const cardW = Math.round((contentW - pad * 2) / 3);
|
|
1146
|
+
const cardH = Math.round(h * 0.18);
|
|
1147
|
+
const cards = [0, 1, 2].map((i) => ({ x: contentX + i * (cardW + pad), y: pad * 3, w: cardW, h: cardH }));
|
|
1148
|
+
const chartTop = cards[0].y + cardH + pad * 2;
|
|
1149
|
+
const chartH = h - chartTop - pad * 2;
|
|
1150
|
+
const chart = [];
|
|
1151
|
+
const n = 24;
|
|
1152
|
+
for (let i = 0; i <= n; i++) {
|
|
1153
|
+
const t = i / n;
|
|
1154
|
+
const v = 0.25 + 0.55 * (t * t * (3 - 2 * t)) + 0.08 * Math.sin(t * 9);
|
|
1155
|
+
chart.push({ x: contentX + t * contentW, y: chartTop + chartH * (1 - v) });
|
|
1156
|
+
}
|
|
1157
|
+
return { sidebar, cards, chart };
|
|
1158
|
+
}
|
|
1159
|
+
function makeDefaultScreenTexture(accent, w = 1600, h = 1e3) {
|
|
1160
|
+
const canvas = document.createElement("canvas");
|
|
1161
|
+
canvas.width = w;
|
|
1162
|
+
canvas.height = h;
|
|
1163
|
+
const ctx = canvas.getContext("2d");
|
|
1164
|
+
const L = defaultScreenLayout(w, h);
|
|
1165
|
+
ctx.fillStyle = "#0b0b0e";
|
|
1166
|
+
ctx.fillRect(0, 0, w, h);
|
|
1167
|
+
ctx.fillStyle = "#141418";
|
|
1168
|
+
ctx.fillRect(L.sidebar.x, L.sidebar.y, L.sidebar.w, L.sidebar.h);
|
|
1169
|
+
ctx.fillStyle = accent;
|
|
1170
|
+
ctx.fillRect(L.sidebar.x + 24, L.sidebar.y + 32, L.sidebar.w * 0.5, 14);
|
|
1171
|
+
ctx.fillStyle = "rgba(255,255,255,0.10)";
|
|
1172
|
+
for (let i = 0; i < 6; i++) ctx.fillRect(L.sidebar.x + 24, L.sidebar.y + 80 + i * 36, L.sidebar.w * (0.55 + i % 3 * 0.1), 10);
|
|
1173
|
+
for (const c of L.cards) {
|
|
1174
|
+
ctx.fillStyle = "#141418";
|
|
1175
|
+
ctx.fillRect(c.x, c.y, c.w, c.h);
|
|
1176
|
+
ctx.fillStyle = "rgba(255,255,255,0.85)";
|
|
1177
|
+
ctx.fillRect(c.x + 24, c.y + 28, c.w * 0.35, 16);
|
|
1178
|
+
ctx.fillStyle = "rgba(255,255,255,0.25)";
|
|
1179
|
+
ctx.fillRect(c.x + 24, c.y + 60, c.w * 0.55, 10);
|
|
1180
|
+
}
|
|
1181
|
+
ctx.strokeStyle = accent;
|
|
1182
|
+
ctx.lineWidth = 6;
|
|
1183
|
+
ctx.lineJoin = "round";
|
|
1184
|
+
ctx.beginPath();
|
|
1185
|
+
L.chart.forEach((p, i) => i ? ctx.lineTo(p.x, p.y) : ctx.moveTo(p.x, p.y));
|
|
1186
|
+
ctx.stroke();
|
|
1187
|
+
const tex = new CanvasTexture(canvas);
|
|
1188
|
+
tex.colorSpace = SRGBColorSpace2;
|
|
1189
|
+
return tex;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
// ../execution/animate/src/layout/solveFlex.ts
|
|
1193
|
+
import { loadYoga } from "yoga-layout/load";
|
|
1194
|
+
var Y = null;
|
|
1195
|
+
var flexReady = loadYoga().then((y) => {
|
|
1196
|
+
Y = y;
|
|
1197
|
+
});
|
|
1198
|
+
function isFlexReady() {
|
|
1199
|
+
return Y !== null;
|
|
1200
|
+
}
|
|
1201
|
+
function leafIds(cell) {
|
|
1202
|
+
if (!cell.children || cell.children.length === 0) return [cell.id];
|
|
1203
|
+
return cell.children.flatMap(leafIds);
|
|
1204
|
+
}
|
|
1205
|
+
function solveFlex(root, size, weights = {}) {
|
|
1206
|
+
if (Y === null) {
|
|
1207
|
+
throw new Error("solveFlex: layout engine not loaded \u2014 await flexReady first");
|
|
1208
|
+
}
|
|
1209
|
+
const out = {};
|
|
1210
|
+
const build = (cell, parentDir) => {
|
|
1211
|
+
const n = Y.Node.create();
|
|
1212
|
+
const grow = Math.max(0, weights[cell.id] ?? cell.grow ?? 1);
|
|
1213
|
+
const basis = Math.max(0, cell.basis ?? 0);
|
|
1214
|
+
const min = Math.max(0, cell.min ?? 0);
|
|
1215
|
+
const along = parentDir === "column" ? "Height" : "Width";
|
|
1216
|
+
n.setFlexGrow(grow);
|
|
1217
|
+
n.setFlexShrink(cell.shrink ?? (grow > 0 ? 1 : 0));
|
|
1218
|
+
n.setFlexBasis(basis);
|
|
1219
|
+
if (min > 0) n[`setMin${along}`](min);
|
|
1220
|
+
if (cell.max != null) n[`setMax${along}`](Math.max(0, cell.max));
|
|
1221
|
+
if (grow === 0 && basis === 0 && min === 0) n.setDisplay(Y.DISPLAY_NONE);
|
|
1222
|
+
const dir = cell.dir ?? "row";
|
|
1223
|
+
n.setFlexDirection(dir === "column" ? Y.FLEX_DIRECTION_COLUMN : Y.FLEX_DIRECTION_ROW);
|
|
1224
|
+
if (cell.gap) n.setGap(Y.GUTTER_ALL, cell.gap);
|
|
1225
|
+
if (cell.padding) n.setPadding(Y.EDGE_ALL, cell.padding);
|
|
1226
|
+
(cell.children ?? []).forEach((ch, i) => n.insertChild(build(ch, dir), i));
|
|
1227
|
+
return n;
|
|
1228
|
+
};
|
|
1229
|
+
const walk = (n, cell, ox, oy) => {
|
|
1230
|
+
const l = n.getComputedLayout();
|
|
1231
|
+
const x = ox + l.left;
|
|
1232
|
+
const y = oy + l.top;
|
|
1233
|
+
out[cell.id] = { x, y, w: l.width, h: l.height };
|
|
1234
|
+
(cell.children ?? []).forEach((ch, i) => walk(n.getChild(i), ch, x, y));
|
|
1235
|
+
};
|
|
1236
|
+
const node = build(root, "row");
|
|
1237
|
+
try {
|
|
1238
|
+
node.setWidth(size.w);
|
|
1239
|
+
node.setHeight(size.h);
|
|
1240
|
+
node.calculateLayout(size.w, size.h, Y.DIRECTION_LTR);
|
|
1241
|
+
walk(node, root, 0, 0);
|
|
1242
|
+
} finally {
|
|
1243
|
+
node.freeRecursive();
|
|
1244
|
+
}
|
|
1245
|
+
return out;
|
|
1246
|
+
}
|
|
1247
|
+
function flexBoxToThree(box2, size) {
|
|
1248
|
+
return {
|
|
1249
|
+
x: box2.x + box2.w / 2 - size.w / 2 || 0,
|
|
1250
|
+
y: -(box2.y + box2.h / 2 - size.h / 2) || 0
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// ../execution/animate/src/layout/fit.ts
|
|
1255
|
+
var STRETCH = { mode: "stretch" };
|
|
1256
|
+
function anchored(cell, w, h, anchor) {
|
|
1257
|
+
const ax = anchor?.x ?? 0.5;
|
|
1258
|
+
const ay = anchor?.y ?? 0.5;
|
|
1259
|
+
return { x: cell.x + (cell.w - w) * ax, y: cell.y + (cell.h - h) * ay, w, h };
|
|
1260
|
+
}
|
|
1261
|
+
function aspectBox(cell, aspect, cover, anchor) {
|
|
1262
|
+
if (cell.w <= 0 || cell.h <= 0) return { ...cell };
|
|
1263
|
+
const byWidth = cell.w;
|
|
1264
|
+
const byHeight = cell.h * aspect;
|
|
1265
|
+
const w = cover ? Math.max(byWidth, byHeight) : Math.min(byWidth, byHeight);
|
|
1266
|
+
return anchored(cell, w, w / aspect, anchor);
|
|
1267
|
+
}
|
|
1268
|
+
function fitBox(cell, fit = STRETCH) {
|
|
1269
|
+
const aspect = fit.aspect ?? (cell.h > 0 ? cell.w / cell.h : 1);
|
|
1270
|
+
switch (fit.mode) {
|
|
1271
|
+
case "contain":
|
|
1272
|
+
return { box: aspectBox(cell, aspect, false, fit.anchor), scale: 1, clip: null };
|
|
1273
|
+
case "cover":
|
|
1274
|
+
return { box: aspectBox(cell, aspect, true, fit.anchor), scale: 1, clip: null };
|
|
1275
|
+
case "scale": {
|
|
1276
|
+
if (!fit.size || fit.size.w <= 0 || fit.size.h <= 0) return { box: { ...cell }, scale: 1, clip: null };
|
|
1277
|
+
const s = Math.min(cell.w / fit.size.w, cell.h / fit.size.h);
|
|
1278
|
+
return { box: anchored(cell, fit.size.w * s, fit.size.h * s, fit.anchor), scale: s, clip: null };
|
|
1279
|
+
}
|
|
1280
|
+
case "matte": {
|
|
1281
|
+
const inner = aspectBox(cell, aspect, false, fit.anchor);
|
|
1282
|
+
return {
|
|
1283
|
+
box: { ...cell },
|
|
1284
|
+
scale: 1,
|
|
1285
|
+
clip: {
|
|
1286
|
+
top: inner.y - cell.y,
|
|
1287
|
+
left: inner.x - cell.x,
|
|
1288
|
+
right: cell.x + cell.w - (inner.x + inner.w),
|
|
1289
|
+
bottom: cell.y + cell.h - (inner.y + inner.h)
|
|
1290
|
+
}
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
case "position":
|
|
1294
|
+
case "stretch":
|
|
1295
|
+
default:
|
|
1296
|
+
return { box: { ...cell }, scale: 1, clip: null };
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
// ../execution/animate/src/layout/FlexLayout.tsx
|
|
1301
|
+
import React19 from "react";
|
|
1302
|
+
import {
|
|
1303
|
+
AbsoluteFill,
|
|
1304
|
+
Easing,
|
|
1305
|
+
continueRender as continueRender2,
|
|
1306
|
+
delayRender as delayRender2,
|
|
1307
|
+
interpolate as interpolate3,
|
|
1308
|
+
useCurrentFrame as useCurrentFrame14,
|
|
1309
|
+
useVideoConfig as useVideoConfig3
|
|
1310
|
+
} from "remotion";
|
|
1311
|
+
var crossOf = (d) => d === "row" ? "column" : "row";
|
|
1312
|
+
var spec = (t) => typeof t === "number" ? { weight: t } : t ?? { weight: 0 };
|
|
1313
|
+
var splitOf = (t) => typeof t === "object" && t !== null ? t.split : void 0;
|
|
1314
|
+
function unionTracks(a, b = []) {
|
|
1315
|
+
const n = Math.max(a.length, b.length);
|
|
1316
|
+
const out = [];
|
|
1317
|
+
for (let i = 0; i < n; i++) {
|
|
1318
|
+
const sa = spec(a[i]);
|
|
1319
|
+
const splitA = splitOf(a[i]);
|
|
1320
|
+
const splitB = splitOf(b[i]);
|
|
1321
|
+
if (!splitA && !splitB) {
|
|
1322
|
+
out.push({ ...sa, split: void 0 });
|
|
1323
|
+
continue;
|
|
1324
|
+
}
|
|
1325
|
+
const m = Math.max(splitA?.length ?? 1, splitB?.length ?? 1);
|
|
1326
|
+
const base = splitA ?? [sa.weight];
|
|
1327
|
+
const split = [];
|
|
1328
|
+
for (let j = 0; j < m; j++) split.push(base[j] ?? 0);
|
|
1329
|
+
out.push({ ...sa, split });
|
|
1330
|
+
}
|
|
1331
|
+
return out;
|
|
1332
|
+
}
|
|
1333
|
+
function weightIn(state, i, j) {
|
|
1334
|
+
const t = state[i];
|
|
1335
|
+
if (t === void 0) return 0;
|
|
1336
|
+
if (j === void 0) return spec(t).weight;
|
|
1337
|
+
const sp = splitOf(t);
|
|
1338
|
+
if (!sp) return j === 0 ? spec(t).weight : 0;
|
|
1339
|
+
const c = sp[j];
|
|
1340
|
+
return c === void 0 ? 0 : typeof c === "number" ? c : c.weight;
|
|
1341
|
+
}
|
|
1342
|
+
function weightsAt(tracks, tracksEnd, p) {
|
|
1343
|
+
const end2 = tracksEnd ?? tracks;
|
|
1344
|
+
const shape = unionTracks(tracks, tracksEnd);
|
|
1345
|
+
const mix = (a, b) => a + (b - a) * p;
|
|
1346
|
+
const out = {};
|
|
1347
|
+
shape.forEach((s, i) => {
|
|
1348
|
+
out[`t${i}`] = mix(weightIn(tracks, i), weightIn(end2, i));
|
|
1349
|
+
s.split?.forEach((_, j) => {
|
|
1350
|
+
out[`t${i}.${j}`] = mix(weightIn(tracks, i, j), weightIn(end2, i, j));
|
|
1351
|
+
});
|
|
1352
|
+
});
|
|
1353
|
+
return out;
|
|
1354
|
+
}
|
|
1355
|
+
function buildTree(tracks, direction, gap, padding, tracksEnd) {
|
|
1356
|
+
const shape = unionTracks(tracks, tracksEnd);
|
|
1357
|
+
return {
|
|
1358
|
+
id: "root",
|
|
1359
|
+
dir: direction,
|
|
1360
|
+
gap,
|
|
1361
|
+
padding,
|
|
1362
|
+
children: shape.map((s, i) => {
|
|
1363
|
+
const base = { id: `t${i}`, grow: s.weight, basis: s.basis, min: s.min, max: s.max, shrink: s.shrink };
|
|
1364
|
+
if (!s.split) return base;
|
|
1365
|
+
return {
|
|
1366
|
+
...base,
|
|
1367
|
+
dir: crossOf(direction),
|
|
1368
|
+
gap,
|
|
1369
|
+
children: s.split.map((c, j) => {
|
|
1370
|
+
const cs = typeof c === "number" ? { weight: c } : c;
|
|
1371
|
+
return { id: `t${i}.${j}`, grow: cs.weight, basis: cs.basis, min: cs.min, max: cs.max, shrink: cs.shrink };
|
|
1372
|
+
})
|
|
1373
|
+
};
|
|
1374
|
+
})
|
|
1375
|
+
};
|
|
1376
|
+
}
|
|
1377
|
+
function useFlexReady() {
|
|
1378
|
+
const [ready, setReady] = React19.useState(isFlexReady);
|
|
1379
|
+
const [handle] = React19.useState(() => isFlexReady() ? null : delayRender2("flex-layout: load engine"));
|
|
1380
|
+
React19.useEffect(() => {
|
|
1381
|
+
if (handle === null) return;
|
|
1382
|
+
flexReady.then(() => {
|
|
1383
|
+
setReady(true);
|
|
1384
|
+
continueRender2(handle);
|
|
1385
|
+
});
|
|
1386
|
+
}, [handle]);
|
|
1387
|
+
return ready;
|
|
1388
|
+
}
|
|
1389
|
+
var pct = (v, total) => `${total > 0 ? v / total * 100 : 0}%`;
|
|
1390
|
+
var LeafCell = ({ box: box2, fit, W, H, children }) => {
|
|
1391
|
+
if (box2.w <= 0 || box2.h <= 0) return null;
|
|
1392
|
+
const f = fitBox(box2, fit);
|
|
1393
|
+
const mode = fit?.mode ?? "stretch";
|
|
1394
|
+
const outer = {
|
|
1395
|
+
position: "absolute",
|
|
1396
|
+
left: pct(box2.x, W),
|
|
1397
|
+
top: pct(box2.y, H),
|
|
1398
|
+
width: pct(box2.w, W),
|
|
1399
|
+
height: pct(box2.h, H),
|
|
1400
|
+
overflow: "hidden",
|
|
1401
|
+
boxSizing: "border-box",
|
|
1402
|
+
...f.clip ? { clipPath: `inset(${pct(f.clip.top, box2.h)} ${pct(f.clip.right, box2.w)} ${pct(f.clip.bottom, box2.h)} ${pct(f.clip.left, box2.w)})` } : {}
|
|
1403
|
+
};
|
|
1404
|
+
if (mode === "position") {
|
|
1405
|
+
return /* @__PURE__ */ React19.createElement("div", { style: { ...outer, display: "flex", alignItems: "center", justifyContent: "center" } }, children);
|
|
1406
|
+
}
|
|
1407
|
+
if (mode === "stretch" || mode === "matte") {
|
|
1408
|
+
return /* @__PURE__ */ React19.createElement("div", { style: outer }, children);
|
|
1409
|
+
}
|
|
1410
|
+
const inner = {
|
|
1411
|
+
position: "absolute",
|
|
1412
|
+
left: pct(f.box.x - box2.x, box2.w),
|
|
1413
|
+
top: pct(f.box.y - box2.y, box2.h),
|
|
1414
|
+
width: pct(f.box.w, box2.w),
|
|
1415
|
+
height: pct(f.box.h, box2.h)
|
|
1416
|
+
};
|
|
1417
|
+
if (mode === "scale" && fit?.size) {
|
|
1418
|
+
return /* @__PURE__ */ React19.createElement("div", { style: outer }, /* @__PURE__ */ React19.createElement("div", { style: { ...inner, width: fit.size.w, height: fit.size.h, transform: `scale(${f.scale})`, transformOrigin: "top left" } }, children));
|
|
1419
|
+
}
|
|
1420
|
+
return /* @__PURE__ */ React19.createElement("div", { style: outer }, /* @__PURE__ */ React19.createElement("div", { style: inner }, children));
|
|
1421
|
+
};
|
|
1422
|
+
var FlexLayout = ({
|
|
1423
|
+
direction = "row",
|
|
1424
|
+
gap = 24,
|
|
1425
|
+
padding = 0,
|
|
1426
|
+
tracks = [1, 1],
|
|
1427
|
+
tracksEnd,
|
|
1428
|
+
fits,
|
|
1429
|
+
progress: progress2,
|
|
1430
|
+
outline = false,
|
|
1431
|
+
outlineColor = "rgba(244,236,224,0.10)",
|
|
1432
|
+
width,
|
|
1433
|
+
height,
|
|
1434
|
+
children
|
|
1435
|
+
}) => {
|
|
1436
|
+
const frame = useCurrentFrame14();
|
|
1437
|
+
const { width: vw, height: vh, durationInFrames } = useVideoConfig3();
|
|
1438
|
+
const W = width ?? vw;
|
|
1439
|
+
const H = height ?? vh;
|
|
1440
|
+
const ready = useFlexReady();
|
|
1441
|
+
if (!ready) return null;
|
|
1442
|
+
const p = progress2 !== void 0 ? Math.min(1, Math.max(0, progress2)) : tracksEnd ? interpolate3(frame, [0, Math.max(1, durationInFrames - 1)], [0, 1], {
|
|
1443
|
+
easing: Easing.inOut(Easing.cubic),
|
|
1444
|
+
extrapolateLeft: "clamp",
|
|
1445
|
+
extrapolateRight: "clamp"
|
|
1446
|
+
}) : 0;
|
|
1447
|
+
const tree = buildTree(tracks, direction, gap, padding, tracksEnd);
|
|
1448
|
+
const boxes = solveFlex(tree, { w: W, h: H }, weightsAt(tracks, tracksEnd, p));
|
|
1449
|
+
const leaves = leafIds(tree);
|
|
1450
|
+
const kids = React19.Children.toArray(children);
|
|
1451
|
+
return /* @__PURE__ */ React19.createElement(AbsoluteFill, null, leaves.map((id, i) => /* @__PURE__ */ React19.createElement(LeafCell, { key: id, box: boxes[id], fit: fits?.[i], W, H }, kids[i] ?? null)), outline && Object.entries(boxes).filter(([id, b]) => id !== "root" && b.w > 0 && b.h > 0).map(([id, b]) => /* @__PURE__ */ React19.createElement("div", { key: `o-${id}`, style: {
|
|
1452
|
+
position: "absolute",
|
|
1453
|
+
left: pct(b.x, W),
|
|
1454
|
+
top: pct(b.y, H),
|
|
1455
|
+
width: pct(b.w, W),
|
|
1456
|
+
height: pct(b.h, H),
|
|
1457
|
+
border: `1.5px solid ${outlineColor}`,
|
|
1458
|
+
boxSizing: "border-box",
|
|
1459
|
+
pointerEvents: "none"
|
|
1460
|
+
} })));
|
|
1461
|
+
};
|
|
1462
|
+
|
|
1463
|
+
// ../execution/animate/src/stage/presets.ts
|
|
1464
|
+
var end = (d) => Math.max(1, d - 1);
|
|
1465
|
+
var fovOf = (o) => o?.fov === void 0 ? {} : { fov: o.fov };
|
|
1466
|
+
var dollyIn = (d, o) => [
|
|
1467
|
+
{ frame: 0, camera: { z: o?.amount ?? 600, ...fovOf(o) } },
|
|
1468
|
+
{ frame: end(d), camera: { z: 0 }, easing: o?.easing ?? smooth }
|
|
1469
|
+
];
|
|
1470
|
+
var dollyOut = (d, o) => [
|
|
1471
|
+
{ frame: 0, camera: { z: 0, ...fovOf(o) } },
|
|
1472
|
+
{ frame: end(d), camera: { z: o?.amount ?? 600 }, easing: o?.easing ?? smooth }
|
|
1473
|
+
];
|
|
1474
|
+
var drift = (d, o) => {
|
|
1475
|
+
const a = o?.amount ?? 40;
|
|
1476
|
+
return [
|
|
1477
|
+
{ frame: 0, camera: { x: -a, rotY: -a / 12, ...fovOf(o) } },
|
|
1478
|
+
{ frame: end(d), camera: { x: a, rotY: a / 12 }, easing: o?.easing ?? ((t) => t) }
|
|
1479
|
+
];
|
|
1480
|
+
};
|
|
1481
|
+
var tiltReveal = (d, o) => [
|
|
1482
|
+
{ frame: 0, camera: { rotX: -(o?.amount ?? 18), z: 300, ...fovOf(o) } },
|
|
1483
|
+
{ frame: end(d), camera: { rotX: 0, z: 0 }, easing: o?.easing ?? smooth }
|
|
1484
|
+
];
|
|
1485
|
+
var orbit = (d, o) => {
|
|
1486
|
+
const a = o?.amount ?? 25;
|
|
1487
|
+
return [
|
|
1488
|
+
{ frame: 0, camera: { rotY: -a, ...fovOf(o) } },
|
|
1489
|
+
{ frame: end(d), camera: { rotY: a }, easing: o?.easing ?? smooth }
|
|
1490
|
+
];
|
|
1491
|
+
};
|
|
1492
|
+
var CAMERA_PRESETS = {
|
|
1493
|
+
static: () => [],
|
|
1494
|
+
"dolly-in": dollyIn,
|
|
1495
|
+
"dolly-out": dollyOut,
|
|
1496
|
+
drift,
|
|
1497
|
+
"tilt-reveal": tiltReveal,
|
|
1498
|
+
orbit
|
|
1499
|
+
};
|
|
1500
|
+
|
|
1501
|
+
// ../execution/animate/src/stage/dof.ts
|
|
1502
|
+
function dofBlur(layerZ, focus) {
|
|
1503
|
+
if (!focus || focus.range <= 0 || focus.maxBlur <= 0) return 0;
|
|
1504
|
+
const t = Math.min(1, Math.abs(layerZ - focus.z) / focus.range);
|
|
1505
|
+
return focus.maxBlur * t;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
// ../execution/animate/src/stage/PerspectiveStage.tsx
|
|
1509
|
+
import React20, { createContext, useContext, useMemo as useMemo3 } from "react";
|
|
1510
|
+
import { Internals } from "remotion";
|
|
1511
|
+
var StageContext = createContext(null);
|
|
1512
|
+
function useStage() {
|
|
1513
|
+
const ctx = useContext(StageContext);
|
|
1514
|
+
if (!ctx) throw new Error("StageLayer and ContactShadow must be rendered inside <PerspectiveStage>.");
|
|
1515
|
+
return ctx;
|
|
1516
|
+
}
|
|
1517
|
+
function useFrameSize(width, height) {
|
|
1518
|
+
const cfg = Internals.useUnsafeVideoConfig();
|
|
1519
|
+
const w = width ?? cfg?.width;
|
|
1520
|
+
const h = height ?? cfg?.height;
|
|
1521
|
+
if (w === void 0 || h === void 0) throw new Error("PerspectiveStage needs width/height outside a Remotion composition.");
|
|
1522
|
+
return { width: w, height: h };
|
|
1523
|
+
}
|
|
1524
|
+
var PerspectiveStage = ({ camera, width: w, height: h, focus, style, children }) => {
|
|
1525
|
+
const { width, height } = useFrameSize(w, h);
|
|
1526
|
+
const cam = useMemo3(() => ({ ...DEFAULT_CAMERA, ...camera }), [camera]);
|
|
1527
|
+
const value = useMemo3(() => ({ camera: cam, width, height, focus }), [cam, width, height, focus]);
|
|
1528
|
+
const perspective = Math.round(perspectiveFor(cam.fov, height) * 100) / 100;
|
|
1529
|
+
return /* @__PURE__ */ React20.createElement(StageContext.Provider, { value }, /* @__PURE__ */ React20.createElement(
|
|
1530
|
+
"div",
|
|
1531
|
+
{
|
|
1532
|
+
style: {
|
|
1533
|
+
position: "absolute",
|
|
1534
|
+
inset: 0,
|
|
1535
|
+
overflow: "hidden",
|
|
1536
|
+
perspective: `${perspective}px`,
|
|
1537
|
+
perspectiveOrigin: "50% 50%",
|
|
1538
|
+
...style
|
|
1539
|
+
}
|
|
1540
|
+
},
|
|
1541
|
+
/* @__PURE__ */ React20.createElement(
|
|
1542
|
+
"div",
|
|
1543
|
+
{
|
|
1544
|
+
style: {
|
|
1545
|
+
position: "absolute",
|
|
1546
|
+
inset: 0,
|
|
1547
|
+
transformStyle: "preserve-3d",
|
|
1548
|
+
transformOrigin: "50% 50%",
|
|
1549
|
+
transform: worldTransform(cam)
|
|
1550
|
+
}
|
|
1551
|
+
},
|
|
1552
|
+
children
|
|
1553
|
+
)
|
|
1554
|
+
));
|
|
1555
|
+
};
|
|
1556
|
+
var StageLayer = ({
|
|
1557
|
+
x = 0,
|
|
1558
|
+
y = 0,
|
|
1559
|
+
z = 0,
|
|
1560
|
+
rotX = 0,
|
|
1561
|
+
rotY = 0,
|
|
1562
|
+
rotZ = 0,
|
|
1563
|
+
scale = 1,
|
|
1564
|
+
width,
|
|
1565
|
+
height,
|
|
1566
|
+
shadow,
|
|
1567
|
+
style,
|
|
1568
|
+
children
|
|
1569
|
+
}) => {
|
|
1570
|
+
const stage = useStage();
|
|
1571
|
+
const w = width ?? stage.width;
|
|
1572
|
+
const h = height ?? stage.height;
|
|
1573
|
+
const inner = useMemo3(() => ({ ...stage, width: w, height: h }), [stage, w, h]);
|
|
1574
|
+
const blur = dofBlur(z, stage.focus);
|
|
1575
|
+
const filters = [];
|
|
1576
|
+
if (blur > 0) filters.push(`blur(${Math.round(blur * 100) / 100}px)`);
|
|
1577
|
+
if (shadow) {
|
|
1578
|
+
filters.push(`drop-shadow(0px ${shadow.offsetY ?? 24}px ${shadow.blur ?? 32}px rgba(0,0,0,${shadow.opacity ?? 0.45}))`);
|
|
1579
|
+
}
|
|
1580
|
+
return /* @__PURE__ */ React20.createElement(
|
|
1581
|
+
"div",
|
|
1582
|
+
{
|
|
1583
|
+
style: {
|
|
1584
|
+
position: "absolute",
|
|
1585
|
+
left: `${stage.width / 2 - w / 2}px`,
|
|
1586
|
+
top: `${stage.height / 2 - h / 2}px`,
|
|
1587
|
+
width: `${w}px`,
|
|
1588
|
+
height: `${h}px`,
|
|
1589
|
+
transformStyle: filters.length ? "flat" : "preserve-3d",
|
|
1590
|
+
transformOrigin: "50% 50%",
|
|
1591
|
+
transform: `translate3d(${x}px, ${y}px, ${z}px) rotateX(${rotX}deg) rotateY(${rotY}deg) rotateZ(${rotZ}deg)${scale === 1 ? "" : ` scale(${scale})`}`,
|
|
1592
|
+
...filters.length ? { filter: filters.join(" ") } : {},
|
|
1593
|
+
...style
|
|
1594
|
+
}
|
|
1595
|
+
},
|
|
1596
|
+
/* @__PURE__ */ React20.createElement(StageContext.Provider, { value: inner }, children)
|
|
1597
|
+
);
|
|
1598
|
+
};
|
|
1599
|
+
var ContactShadow = ({ y, width, depth, opacity = 0.45, z = 0 }) => {
|
|
1600
|
+
const stage = useStage();
|
|
1601
|
+
return /* @__PURE__ */ React20.createElement(
|
|
1602
|
+
"div",
|
|
1603
|
+
{
|
|
1604
|
+
style: {
|
|
1605
|
+
position: "absolute",
|
|
1606
|
+
left: `${stage.width / 2 - width / 2}px`,
|
|
1607
|
+
top: `${stage.height / 2 - depth / 2}px`,
|
|
1608
|
+
width: `${width}px`,
|
|
1609
|
+
height: `${depth}px`,
|
|
1610
|
+
transformOrigin: "50% 50%",
|
|
1611
|
+
transform: `translate3d(0px, ${y}px, ${z}px) rotateX(90deg)`,
|
|
1612
|
+
background: `radial-gradient(ellipse at center, rgba(0,0,0,${opacity}) 0%, rgba(0,0,0,${opacity * 0.5}) 35%, rgba(0,0,0,0) 70%)`,
|
|
1613
|
+
pointerEvents: "none"
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
);
|
|
1617
|
+
};
|
|
1618
|
+
|
|
1619
|
+
// ../execution/animate/src/media/MediaTileScene.tsx
|
|
1620
|
+
import React21, { useCallback, useLayoutEffect as useLayoutEffect4, useMemo as useMemo4, useRef as useRef2, useState as useState2 } from "react";
|
|
1621
|
+
import { useThree as useThree3 } from "@react-three/fiber";
|
|
1622
|
+
import { Video } from "@remotion/media";
|
|
1623
|
+
import { ThreeCanvas as ThreeCanvas2 } from "@remotion/three";
|
|
1624
|
+
import { BufferAttribute, BufferGeometry, Color, SRGBColorSpace as SRGBColorSpace3, Texture as Texture2, WebGLRenderer } from "three";
|
|
1625
|
+
import {
|
|
1626
|
+
Img,
|
|
1627
|
+
Internals as Internals2,
|
|
1628
|
+
cancelRender as cancelRender2,
|
|
1629
|
+
getRemotionEnvironment,
|
|
1630
|
+
useCurrentFrame as useCurrentFrame15,
|
|
1631
|
+
useDelayRender,
|
|
1632
|
+
useVideoConfig as useVideoConfig4
|
|
1633
|
+
} from "remotion";
|
|
1634
|
+
var RESOURCE_ERROR = "__cueframe_component_error_v2__:component_resource_exhausted:";
|
|
1635
|
+
var RUNTIME_ERROR = "__cueframe_component_error_v2__:component_runtime_error:";
|
|
1636
|
+
var nextMediaTileSceneId = 0;
|
|
1637
|
+
var MEDIA_TILE_SCENE_LIMITS = Object.freeze({
|
|
1638
|
+
streams: 8,
|
|
1639
|
+
tiles: 512,
|
|
1640
|
+
textureBytes: 128 * 1024 * 1024
|
|
1641
|
+
});
|
|
1642
|
+
function mediaTileFramesReady(sourceFrames, frame, playing) {
|
|
1643
|
+
return sourceFrames.every((sourceFrame) => {
|
|
1644
|
+
if (sourceFrame === void 0) return false;
|
|
1645
|
+
if (sourceFrame === null) return true;
|
|
1646
|
+
return playing || sourceFrame === frame;
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
function fail(prefix, message) {
|
|
1650
|
+
throw new Error(prefix + message);
|
|
1651
|
+
}
|
|
1652
|
+
function decodedSize(source) {
|
|
1653
|
+
const value = source;
|
|
1654
|
+
const width = value.videoWidth ?? value.naturalWidth ?? value.displayWidth ?? value.width ?? 0;
|
|
1655
|
+
const height = value.videoHeight ?? value.naturalHeight ?? value.displayHeight ?? value.height ?? 0;
|
|
1656
|
+
if (width === 0 || height === 0) return null;
|
|
1657
|
+
if (![width, height].every((dimension) => Number.isSafeInteger(dimension) && dimension > 0)) {
|
|
1658
|
+
fail(RUNTIME_ERROR, "A media tile stream produced invalid decoded dimensions.");
|
|
1659
|
+
}
|
|
1660
|
+
return { width, height };
|
|
1661
|
+
}
|
|
1662
|
+
function validCrop(crop) {
|
|
1663
|
+
if (!crop) return true;
|
|
1664
|
+
return [crop.x, crop.y, crop.width, crop.height].every(Number.isFinite) && crop.x >= 0 && crop.y >= 0 && crop.width > 0 && crop.height > 0 && crop.x + crop.width <= 1 && crop.y + crop.height <= 1;
|
|
1665
|
+
}
|
|
1666
|
+
function assertMediaTileScene(streams, tiles) {
|
|
1667
|
+
if (!streams || typeof streams !== "object" || Array.isArray(streams)) {
|
|
1668
|
+
fail(RUNTIME_ERROR, "MediaTileScene requires a `streams` object.");
|
|
1669
|
+
}
|
|
1670
|
+
if (!Array.isArray(tiles)) fail(RUNTIME_ERROR, "MediaTileScene requires a `tiles` array.");
|
|
1671
|
+
const ids = Object.keys(streams).sort();
|
|
1672
|
+
if (ids.length === 0) fail(RUNTIME_ERROR, "MediaTileScene requires at least one stream.");
|
|
1673
|
+
if (ids.length > MEDIA_TILE_SCENE_LIMITS.streams) {
|
|
1674
|
+
fail(RESOURCE_ERROR, `MediaTileScene supports at most ${MEDIA_TILE_SCENE_LIMITS.streams} media streams.`);
|
|
1675
|
+
}
|
|
1676
|
+
if (tiles.length === 0) fail(RUNTIME_ERROR, "MediaTileScene requires at least one tile.");
|
|
1677
|
+
if (tiles.length > MEDIA_TILE_SCENE_LIMITS.tiles) {
|
|
1678
|
+
fail(RESOURCE_ERROR, `MediaTileScene supports at most ${MEDIA_TILE_SCENE_LIMITS.tiles} tile instances.`);
|
|
1679
|
+
}
|
|
1680
|
+
for (const [id, stream2] of Object.entries(streams)) {
|
|
1681
|
+
if (!stream2?.asset?.handle || !["image", "video"].includes(stream2.asset.kind)) {
|
|
1682
|
+
fail(RUNTIME_ERROR, `MediaTileScene stream ${JSON.stringify(id)} has no supported media asset.`);
|
|
1683
|
+
}
|
|
1684
|
+
if (stream2.asset.kind === "image" && (stream2.trimBeforeFrames !== void 0 || stream2.trimAfterFrames !== void 0 || stream2.playbackRate !== void 0 || stream2.loop !== void 0)) {
|
|
1685
|
+
fail(RUNTIME_ERROR, `MediaTileScene image stream ${JSON.stringify(id)} cannot declare video timing.`);
|
|
1686
|
+
}
|
|
1687
|
+
if (stream2.playbackRate !== void 0 && (!Number.isFinite(stream2.playbackRate) || stream2.playbackRate <= 0)) {
|
|
1688
|
+
fail(RUNTIME_ERROR, `MediaTileScene stream ${JSON.stringify(id)} has an invalid playback rate.`);
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
for (const tile of tiles) {
|
|
1692
|
+
if (!streams[tile.stream]) fail(RUNTIME_ERROR, `MediaTileScene tile references unknown stream ${JSON.stringify(tile.stream)}.`);
|
|
1693
|
+
if (![tile.x, tile.y, tile.width, tile.height, tile.z ?? 0, tile.rotation ?? 0, tile.opacity ?? 1].every(Number.isFinite) || tile.width <= 0 || tile.height <= 0 || (tile.opacity ?? 1) < 0 || (tile.opacity ?? 1) > 1 || !validCrop(tile.crop)) {
|
|
1694
|
+
fail(RUNTIME_ERROR, "MediaTileScene received invalid tile geometry, opacity, or crop.");
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
const usedStreams = new Set(tiles.map((tile) => tile.stream));
|
|
1698
|
+
const unusedStream = ids.find((id) => !usedStreams.has(id));
|
|
1699
|
+
if (unusedStream) {
|
|
1700
|
+
fail(RUNTIME_ERROR, `MediaTileScene stream ${JSON.stringify(unusedStream)} has no tile.`);
|
|
1701
|
+
}
|
|
1702
|
+
return ids;
|
|
1703
|
+
}
|
|
1704
|
+
function mediaTileCropUvs(crop) {
|
|
1705
|
+
const value = crop ?? { x: 0, y: 0, width: 1, height: 1 };
|
|
1706
|
+
if (!validCrop(value)) fail(RUNTIME_ERROR, "MediaTileScene received an invalid normalized crop.");
|
|
1707
|
+
const left = value.x;
|
|
1708
|
+
const right = value.x + value.width;
|
|
1709
|
+
const top = 1 - value.y;
|
|
1710
|
+
const bottom = 1 - value.y - value.height;
|
|
1711
|
+
return [left, top, right, top, left, bottom, right, bottom];
|
|
1712
|
+
}
|
|
1713
|
+
function mediaTileFogDistances(fog, camera, perspective) {
|
|
1714
|
+
const cameraDistanceFromPlane = perspective - (camera?.z ?? 0);
|
|
1715
|
+
if (![fog.near, fog.far, cameraDistanceFromPlane].every(Number.isFinite) || fog.near < 0 || fog.far <= fog.near || cameraDistanceFromPlane <= 0) {
|
|
1716
|
+
fail(RUNTIME_ERROR, "MediaTileScene received an invalid fog or camera depth range.");
|
|
1717
|
+
}
|
|
1718
|
+
return [fog.color, cameraDistanceFromPlane + fog.near, cameraDistanceFromPlane + fog.far];
|
|
1719
|
+
}
|
|
1720
|
+
function ImageProducer({ id, stream: stream2, accept, report }) {
|
|
1721
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1722
|
+
Img,
|
|
1723
|
+
{
|
|
1724
|
+
src: stream2.asset.handle,
|
|
1725
|
+
crossOrigin: "anonymous",
|
|
1726
|
+
onLoad: (event) => {
|
|
1727
|
+
const source = event.currentTarget;
|
|
1728
|
+
const size = decodedSize(source);
|
|
1729
|
+
if (!size) return report(new Error(RUNTIME_ERROR + `Image stream ${JSON.stringify(id)} has no decoded dimensions.`));
|
|
1730
|
+
accept(id, { source, version: 1, frame: null, ...size });
|
|
1731
|
+
},
|
|
1732
|
+
onError: () => report(new Error(RUNTIME_ERROR + `Image stream ${JSON.stringify(id)} could not be decoded.`)),
|
|
1733
|
+
style: { position: "absolute", width: 1, height: 1, opacity: 0, pointerEvents: "none" }
|
|
1734
|
+
}
|
|
1735
|
+
);
|
|
1736
|
+
}
|
|
1737
|
+
function VideoProducer({ id, stream: stream2, accept, report }) {
|
|
1738
|
+
const container = useRef2(null);
|
|
1739
|
+
const version = useRef2(0);
|
|
1740
|
+
const acceptedFrame = useRef2(null);
|
|
1741
|
+
const frame = useCurrentFrame15();
|
|
1742
|
+
const handleVideoError = useCallback((error) => {
|
|
1743
|
+
report(error);
|
|
1744
|
+
return "fail";
|
|
1745
|
+
}, [report]);
|
|
1746
|
+
const onVideoFrame = useCallback(() => {
|
|
1747
|
+
queueMicrotask(() => {
|
|
1748
|
+
if (acceptedFrame.current === frame) return;
|
|
1749
|
+
const source = container.current?.querySelector("canvas");
|
|
1750
|
+
if (!source) return report(new Error(RUNTIME_ERROR + `Video stream ${JSON.stringify(id)} did not provide its decoded canvas.`));
|
|
1751
|
+
const size = decodedSize(source);
|
|
1752
|
+
if (!size) return report(new Error(RUNTIME_ERROR + `Video stream ${JSON.stringify(id)} has no decoded dimensions.`));
|
|
1753
|
+
acceptedFrame.current = frame;
|
|
1754
|
+
version.current += 1;
|
|
1755
|
+
accept(id, { source, version: version.current, frame, ...size });
|
|
1756
|
+
});
|
|
1757
|
+
}, [accept, frame, id, report]);
|
|
1758
|
+
return /* @__PURE__ */ React21.createElement("div", { ref: container, style: { position: "absolute", width: 1, height: 1, opacity: 0, pointerEvents: "none" } }, /* @__PURE__ */ React21.createElement(
|
|
1759
|
+
Video,
|
|
1760
|
+
{
|
|
1761
|
+
src: stream2.asset.handle,
|
|
1762
|
+
disallowFallbackToOffthreadVideo: true,
|
|
1763
|
+
onError: handleVideoError,
|
|
1764
|
+
onVideoFrame,
|
|
1765
|
+
trimBefore: stream2.trimBeforeFrames,
|
|
1766
|
+
trimAfter: stream2.trimAfterFrames,
|
|
1767
|
+
playbackRate: stream2.playbackRate ?? 1,
|
|
1768
|
+
loop: stream2.loop ?? false,
|
|
1769
|
+
muted: true,
|
|
1770
|
+
showInTimeline: false,
|
|
1771
|
+
delayRenderTimeoutInMilliseconds: 12e4,
|
|
1772
|
+
style: { width: 1, height: 1 }
|
|
1773
|
+
}
|
|
1774
|
+
));
|
|
1775
|
+
}
|
|
1776
|
+
function geometryForCrop(crop) {
|
|
1777
|
+
const geometry = new BufferGeometry();
|
|
1778
|
+
geometry.setAttribute("position", new BufferAttribute(new Float32Array([
|
|
1779
|
+
-0.5,
|
|
1780
|
+
0.5,
|
|
1781
|
+
0,
|
|
1782
|
+
0.5,
|
|
1783
|
+
0.5,
|
|
1784
|
+
0,
|
|
1785
|
+
-0.5,
|
|
1786
|
+
-0.5,
|
|
1787
|
+
0,
|
|
1788
|
+
0.5,
|
|
1789
|
+
-0.5,
|
|
1790
|
+
0
|
|
1791
|
+
]), 3));
|
|
1792
|
+
geometry.setAttribute("uv", new BufferAttribute(new Float32Array(mediaTileCropUvs(crop)), 2));
|
|
1793
|
+
geometry.setIndex([0, 2, 1, 2, 3, 1]);
|
|
1794
|
+
return geometry;
|
|
1795
|
+
}
|
|
1796
|
+
function StreamTiles({ entry, tiles }) {
|
|
1797
|
+
const invalidate = useThree3((state) => state.invalidate);
|
|
1798
|
+
const texture = useMemo4(() => {
|
|
1799
|
+
const value = new Texture2(entry.source);
|
|
1800
|
+
value.colorSpace = SRGBColorSpace3;
|
|
1801
|
+
value.needsUpdate = true;
|
|
1802
|
+
return value;
|
|
1803
|
+
}, [entry.source]);
|
|
1804
|
+
const geometries = useMemo4(() => {
|
|
1805
|
+
const values = /* @__PURE__ */ new Map();
|
|
1806
|
+
for (const tile of tiles) {
|
|
1807
|
+
const crop = tile.crop ?? { x: 0, y: 0, width: 1, height: 1 };
|
|
1808
|
+
const key = `${crop.x}:${crop.y}:${crop.width}:${crop.height}`;
|
|
1809
|
+
if (!values.has(key)) values.set(key, geometryForCrop(crop));
|
|
1810
|
+
}
|
|
1811
|
+
return values;
|
|
1812
|
+
}, [tiles]);
|
|
1813
|
+
useLayoutEffect4(() => {
|
|
1814
|
+
texture.needsUpdate = true;
|
|
1815
|
+
invalidate();
|
|
1816
|
+
}, [entry.version, invalidate, texture]);
|
|
1817
|
+
useLayoutEffect4(() => () => {
|
|
1818
|
+
texture.dispose();
|
|
1819
|
+
for (const geometry of geometries.values()) geometry.dispose();
|
|
1820
|
+
}, [geometries, texture]);
|
|
1821
|
+
return /* @__PURE__ */ React21.createElement(React21.Fragment, null, tiles.map((tile, index) => {
|
|
1822
|
+
const crop = tile.crop ?? { x: 0, y: 0, width: 1, height: 1 };
|
|
1823
|
+
const geometry = geometries.get(`${crop.x}:${crop.y}:${crop.width}:${crop.height}`);
|
|
1824
|
+
const opacity = tile.opacity ?? 1;
|
|
1825
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1826
|
+
"mesh",
|
|
1827
|
+
{
|
|
1828
|
+
key: index,
|
|
1829
|
+
geometry,
|
|
1830
|
+
position: [tile.x, -tile.y, -(tile.z ?? 0)],
|
|
1831
|
+
rotation: [0, 0, -(tile.rotation ?? 0) * Math.PI / 180],
|
|
1832
|
+
scale: [tile.width, tile.height, 1]
|
|
1833
|
+
},
|
|
1834
|
+
/* @__PURE__ */ React21.createElement("meshBasicMaterial", { map: texture, transparent: opacity < 1, opacity, depthWrite: opacity >= 1, ...UNLIT_COLOUR_MANAGED })
|
|
1835
|
+
);
|
|
1836
|
+
}));
|
|
1837
|
+
}
|
|
1838
|
+
function SceneContents({ streamIds, tiles, sources, camera, fog, background, announce, presentationReady, playing }) {
|
|
1839
|
+
const { advance, camera: threeCamera, gl, invalidate } = useThree3();
|
|
1840
|
+
const frame = useCurrentFrame15();
|
|
1841
|
+
const isRendering = getRemotionEnvironment().isRendering;
|
|
1842
|
+
const perspective = camera?.perspective ?? 1400;
|
|
1843
|
+
const { height } = useVideoConfig4();
|
|
1844
|
+
useLayoutEffect4(() => {
|
|
1845
|
+
threeCamera.position.set(camera?.x ?? 0, -(camera?.y ?? 0), perspective - (camera?.z ?? 0));
|
|
1846
|
+
threeCamera.zoom = camera?.zoom ?? 1;
|
|
1847
|
+
if ("fov" in threeCamera) threeCamera.fov = 2 * Math.atan(height / (2 * perspective)) * 180 / Math.PI;
|
|
1848
|
+
threeCamera.lookAt(camera?.x ?? 0, -(camera?.y ?? 0), 0);
|
|
1849
|
+
threeCamera.updateProjectionMatrix();
|
|
1850
|
+
const match = !background || background === "transparent" ? null : /^#([a-f\d]{6})([a-f\d]{2})?$/i.exec(background);
|
|
1851
|
+
if (background && background !== "transparent" && !match) {
|
|
1852
|
+
fail(RUNTIME_ERROR, "MediaTileScene background must be transparent, #RRGGBB, or #RRGGBBAA.");
|
|
1853
|
+
}
|
|
1854
|
+
gl.setClearColor(new Color(match ? `#${match[1]}` : "#000000"), match?.[2] ? Number.parseInt(match[2], 16) / 255 : match ? 1 : 0);
|
|
1855
|
+
invalidate();
|
|
1856
|
+
}, [background, camera, frame, gl, height, invalidate, perspective, threeCamera]);
|
|
1857
|
+
const sourceVersions = streamIds.map((id) => sources[id].version).join(":");
|
|
1858
|
+
useLayoutEffect4(() => {
|
|
1859
|
+
if (isRendering || !playing) advance(performance.now());
|
|
1860
|
+
else invalidate();
|
|
1861
|
+
if (presentationReady) announce();
|
|
1862
|
+
}, [advance, announce, frame, invalidate, isRendering, playing, presentationReady, sourceVersions]);
|
|
1863
|
+
return /* @__PURE__ */ React21.createElement(React21.Fragment, null, fog ? /* @__PURE__ */ React21.createElement("fog", { attach: "fog", args: mediaTileFogDistances(fog, camera, perspective) }) : null, streamIds.map((id) => /* @__PURE__ */ React21.createElement(
|
|
1864
|
+
StreamTiles,
|
|
1865
|
+
{
|
|
1866
|
+
key: id,
|
|
1867
|
+
entry: sources[id],
|
|
1868
|
+
tiles: tiles.filter((tile) => tile.stream === id)
|
|
1869
|
+
}
|
|
1870
|
+
)));
|
|
1871
|
+
}
|
|
1872
|
+
function createWebGl2Renderer(defaults) {
|
|
1873
|
+
const context = defaults.canvas.getContext("webgl2", { alpha: true, antialias: true });
|
|
1874
|
+
if (!context) fail(RUNTIME_ERROR, "MediaTileScene could not acquire its required WebGL2 context.");
|
|
1875
|
+
return new WebGLRenderer({ canvas: defaults.canvas, context, antialias: true, alpha: true });
|
|
1876
|
+
}
|
|
1877
|
+
function MediaTileScene({ streams, tiles, camera, fog, background, style }) {
|
|
1878
|
+
const frame = useCurrentFrame15();
|
|
1879
|
+
const [playing] = Internals2.Timeline.usePlayingState();
|
|
1880
|
+
const { width, height } = useVideoConfig4();
|
|
1881
|
+
const isRendering = getRemotionEnvironment().isRendering;
|
|
1882
|
+
const { delayRender: scopedDelayRender, continueRender: scopedContinueRender } = useDelayRender();
|
|
1883
|
+
const streamIds = useMemo4(() => assertMediaTileScene(streams, tiles), [streams, tiles]);
|
|
1884
|
+
const [sources, setSources] = useState2({});
|
|
1885
|
+
const [failure, setFailure] = useState2(null);
|
|
1886
|
+
const [sceneId] = useState2(() => `cueframe-media-tile-${++nextMediaTileSceneId}`);
|
|
1887
|
+
const announcedFrame = useRef2(null);
|
|
1888
|
+
const frameGate = useRef2(null);
|
|
1889
|
+
useLayoutEffect4(() => {
|
|
1890
|
+
if (!isRendering) return;
|
|
1891
|
+
const gate = {
|
|
1892
|
+
frame,
|
|
1893
|
+
handle: scopedDelayRender(`Waiting for MediaTileScene frame ${frame}`, {
|
|
1894
|
+
timeoutInMilliseconds: 12e4
|
|
1895
|
+
}),
|
|
1896
|
+
complete: false
|
|
1897
|
+
};
|
|
1898
|
+
frameGate.current = gate;
|
|
1899
|
+
return () => {
|
|
1900
|
+
if (!gate.complete) scopedContinueRender(gate.handle);
|
|
1901
|
+
if (frameGate.current === gate) frameGate.current = null;
|
|
1902
|
+
};
|
|
1903
|
+
}, [frame, isRendering, scopedContinueRender, scopedDelayRender]);
|
|
1904
|
+
const report = useCallback((error) => {
|
|
1905
|
+
const value = error instanceof Error ? error : new Error(String(error));
|
|
1906
|
+
if (isRendering) cancelRender2(value);
|
|
1907
|
+
else setFailure(value);
|
|
1908
|
+
}, [isRendering]);
|
|
1909
|
+
const accept = useCallback((id, value) => {
|
|
1910
|
+
setSources((current) => current[id]?.source === value.source && current[id]?.version === value.version ? current : { ...current, [id]: value });
|
|
1911
|
+
}, []);
|
|
1912
|
+
const announce = useCallback(() => {
|
|
1913
|
+
if (announcedFrame.current === frame) return;
|
|
1914
|
+
announcedFrame.current = frame;
|
|
1915
|
+
window.dispatchEvent(new CustomEvent("cueframe-media-tile-presented", { detail: { frame, sceneId } }));
|
|
1916
|
+
const gate = frameGate.current;
|
|
1917
|
+
if (gate && gate.frame === frame && !gate.complete) {
|
|
1918
|
+
gate.complete = true;
|
|
1919
|
+
scopedContinueRender(gate.handle);
|
|
1920
|
+
}
|
|
1921
|
+
}, [frame, sceneId, scopedContinueRender]);
|
|
1922
|
+
const ready = streamIds.every((id) => sources[id]);
|
|
1923
|
+
const presentationReady = mediaTileFramesReady(
|
|
1924
|
+
streamIds.map((id) => sources[id]?.frame),
|
|
1925
|
+
frame,
|
|
1926
|
+
!isRendering && playing
|
|
1927
|
+
);
|
|
1928
|
+
const textureBytes = streamIds.reduce((total, id) => total + (sources[id]?.width ?? 0) * (sources[id]?.height ?? 0) * 4, 0);
|
|
1929
|
+
if (textureBytes > MEDIA_TILE_SCENE_LIMITS.textureBytes) {
|
|
1930
|
+
fail(RESOURCE_ERROR, `MediaTileScene exceeds ${MEDIA_TILE_SCENE_LIMITS.textureBytes} bytes of decoded textures.`);
|
|
1931
|
+
}
|
|
1932
|
+
if (failure) throw failure;
|
|
1933
|
+
return /* @__PURE__ */ React21.createElement("div", { style: { position: "absolute", inset: 0, overflow: "hidden", ...style } }, /* @__PURE__ */ React21.createElement("div", { "data-cueframe-media-tile-scene": sceneId, style: { position: "absolute", inset: 0 } }, ready ? /* @__PURE__ */ React21.createElement(
|
|
1934
|
+
ThreeCanvas2,
|
|
1935
|
+
{
|
|
1936
|
+
width,
|
|
1937
|
+
height,
|
|
1938
|
+
frameloop: "demand",
|
|
1939
|
+
gl: createWebGl2Renderer,
|
|
1940
|
+
camera: { position: [0, 0, camera?.perspective ?? 1400], near: 0.1, far: 1e5 },
|
|
1941
|
+
style: { width: "100%", height: "100%" }
|
|
1942
|
+
},
|
|
1943
|
+
/* @__PURE__ */ React21.createElement(SceneContents, { ...{
|
|
1944
|
+
streamIds,
|
|
1945
|
+
tiles,
|
|
1946
|
+
sources,
|
|
1947
|
+
camera,
|
|
1948
|
+
fog,
|
|
1949
|
+
background,
|
|
1950
|
+
announce,
|
|
1951
|
+
presentationReady,
|
|
1952
|
+
playing
|
|
1953
|
+
} })
|
|
1954
|
+
) : null), streamIds.map((id) => streams[id].asset.kind === "image" ? /* @__PURE__ */ React21.createElement(ImageProducer, { key: id, id, stream: streams[id], accept, report }) : /* @__PURE__ */ React21.createElement(VideoProducer, { key: id, id, stream: streams[id], accept, report })));
|
|
1955
|
+
}
|
|
1956
|
+
var ImageTileScene = MediaTileScene;
|
|
1957
|
+
|
|
1958
|
+
// ../execution/animate/src/scene/errors.ts
|
|
1959
|
+
var SceneShotError = class extends Error {
|
|
1960
|
+
code;
|
|
1961
|
+
/** Dotted path into the scene spec the failure is about, when there is one. */
|
|
1962
|
+
path;
|
|
1963
|
+
constructor(code, detail, path = null) {
|
|
1964
|
+
super(path ? `${code}: ${detail} (at ${path})` : `${code}: ${detail}`);
|
|
1965
|
+
this.name = "SceneShotError";
|
|
1966
|
+
this.code = code;
|
|
1967
|
+
this.path = path;
|
|
1968
|
+
}
|
|
1969
|
+
};
|
|
1970
|
+
|
|
1971
|
+
// ../execution/animate/src/scene/scaling.ts
|
|
1972
|
+
function referenceScale(render, reference) {
|
|
1973
|
+
if (render.width * reference.height !== render.height * reference.width) {
|
|
1974
|
+
throw new SceneShotError(
|
|
1975
|
+
"scene_aspect_mismatch",
|
|
1976
|
+
`the shot is laid out for ${reference.width}x${reference.height} but the render is ${render.width}x${render.height}; re-layout the shot for the target aspect`,
|
|
1977
|
+
"referenceSize"
|
|
1978
|
+
);
|
|
1979
|
+
}
|
|
1980
|
+
return render.width / reference.width;
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
// ../execution/animate/src/scene/coordinates.ts
|
|
1984
|
+
import { Euler as Euler2, Matrix4 as Matrix42, Quaternion as Quaternion2, Vector3 as Vector32 } from "three";
|
|
1985
|
+
var SCENE_EULER_ORDER = "XYZ";
|
|
1986
|
+
var F = new Matrix42().makeScale(1, -1, 1);
|
|
1987
|
+
function conjugateF(m) {
|
|
1988
|
+
return F.clone().multiply(m).multiply(F);
|
|
1989
|
+
}
|
|
1990
|
+
function sceneWorldMatrix(t) {
|
|
1991
|
+
return new Matrix42().compose(
|
|
1992
|
+
new Vector32(t.position[0], t.position[1], t.position[2]),
|
|
1993
|
+
new Quaternion2().setFromEuler(new Euler2(t.rotation[0], t.rotation[1], t.rotation[2], SCENE_EULER_ORDER)),
|
|
1994
|
+
new Vector32(t.scale, t.scale, t.scale)
|
|
1995
|
+
);
|
|
1996
|
+
}
|
|
1997
|
+
function sceneCssMatrix(t) {
|
|
1998
|
+
return conjugateF(sceneWorldMatrix(t));
|
|
1999
|
+
}
|
|
2000
|
+
function sceneLayerPose(t) {
|
|
2001
|
+
const q = new Quaternion2().setFromEuler(new Euler2(t.rotation[0], t.rotation[1], t.rotation[2], SCENE_EULER_ORDER));
|
|
2002
|
+
return { position: [...t.position], quaternion: [q.x, q.y, q.z, q.w], scale: t.scale };
|
|
2003
|
+
}
|
|
2004
|
+
function scaleSceneTransform(t, scale) {
|
|
2005
|
+
return { position: [t.position[0] * scale, t.position[1] * scale, t.position[2] * scale], rotation: [...t.rotation], scale: t.scale };
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
// ../execution/animate/src/scene/v2/builders.tsx
|
|
2009
|
+
import React22, { useLayoutEffect as useLayoutEffect8, useMemo as useMemo5, useRef as useRef5 } from "react";
|
|
2010
|
+
import { DoubleSide as DoubleSide2, FrontSide as FrontSide2 } from "three";
|
|
2011
|
+
|
|
2012
|
+
// ../execution/animate/src/scene/deviceOpacity.ts
|
|
2013
|
+
var BASE_OPACITY = "cueframeBaseOpacity";
|
|
2014
|
+
var BASE_TRANSPARENT = "cueframeBaseTransparent";
|
|
2015
|
+
function applyLayerOpacity(root, opacity) {
|
|
2016
|
+
root.traverse((object) => {
|
|
2017
|
+
const mesh = object;
|
|
2018
|
+
if (!mesh.isMesh) return;
|
|
2019
|
+
const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
2020
|
+
for (const material of materials) {
|
|
2021
|
+
const stored = material.userData[BASE_OPACITY];
|
|
2022
|
+
const base = typeof stored === "number" ? stored : material.opacity;
|
|
2023
|
+
if (typeof stored !== "number") material.userData[BASE_OPACITY] = base;
|
|
2024
|
+
material.opacity = base * opacity;
|
|
2025
|
+
const storedTransparent = material.userData[BASE_TRANSPARENT];
|
|
2026
|
+
const baseTransparent = typeof storedTransparent === "boolean" ? storedTransparent : material.transparent;
|
|
2027
|
+
if (typeof storedTransparent !== "boolean") material.userData[BASE_TRANSPARENT] = baseTransparent;
|
|
2028
|
+
const transparent = baseTransparent || material.opacity < 1;
|
|
2029
|
+
if (material.transparent !== transparent) {
|
|
2030
|
+
material.transparent = transparent;
|
|
2031
|
+
material.needsUpdate = true;
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
});
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
// ../execution/animate/src/scene/planeFit.ts
|
|
2038
|
+
function planeFit(fit, plane2, image) {
|
|
2039
|
+
if (!(image.width > 0) || !(image.height > 0)) {
|
|
2040
|
+
throw new SceneShotError("scene_internal", `a page image decoded to ${image.width}x${image.height}`);
|
|
2041
|
+
}
|
|
2042
|
+
const ratio = image.width * plane2.height / (image.height * plane2.width);
|
|
2043
|
+
if (fit === "contain") {
|
|
2044
|
+
const size = ratio > 1 ? { width: plane2.width, height: plane2.width * image.height / image.width } : { width: plane2.height * image.width / image.height, height: plane2.height };
|
|
2045
|
+
return { size, repeat: [1, 1], offset: [0, 0] };
|
|
2046
|
+
}
|
|
2047
|
+
const repeat = ratio > 1 ? [1 / ratio, 1] : [1, ratio];
|
|
2048
|
+
return {
|
|
2049
|
+
size: { width: plane2.width, height: plane2.height },
|
|
2050
|
+
repeat,
|
|
2051
|
+
offset: [(1 - repeat[0]) / 2, (1 - repeat[1]) / 2]
|
|
2052
|
+
};
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
// ../execution/animate/src/scene/textureImageSize.ts
|
|
2056
|
+
function textureImageSize(texture, slot, layerIndex) {
|
|
2057
|
+
const image = texture.image;
|
|
2058
|
+
const width = image?.width ?? 0;
|
|
2059
|
+
const height = image?.height ?? 0;
|
|
2060
|
+
if (!(width > 0) || !(height > 0)) throw new SceneShotError("scene_internal", `page image slot "${slot}" decoded to ${width}x${height}`, `layers.${layerIndex}.image`);
|
|
2061
|
+
return { width, height };
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
// ../execution/animate/src/scene/UnlitPlane.tsx
|
|
2065
|
+
import { useLayoutEffect as useLayoutEffect5 } from "react";
|
|
2066
|
+
import { DoubleSide, FrontSide } from "three";
|
|
2067
|
+
var UNLIT_PLANE_ALPHA_TEST = 0.01;
|
|
2068
|
+
function UnlitPlane({ texture, fit, color = "#ffffff", transparent = true, depthWrite = true, backface = "hidden", resourceOwner, resourceName }) {
|
|
2069
|
+
const [rx, ry] = fit.repeat;
|
|
2070
|
+
const [ox, oy] = fit.offset;
|
|
2071
|
+
useLayoutEffect5(() => {
|
|
2072
|
+
if (texture.repeat.x !== rx || texture.repeat.y !== ry) texture.repeat.set(rx, ry);
|
|
2073
|
+
if (texture.offset.x !== ox || texture.offset.y !== oy) texture.offset.set(ox, oy);
|
|
2074
|
+
}, [texture, rx, ry, ox, oy]);
|
|
2075
|
+
return /* @__PURE__ */ React.createElement("mesh", null, /* @__PURE__ */ React.createElement(MeasuredPlaneGeometry, { width: fit.size.width, height: fit.size.height, owner: resourceOwner, name: resourceName }), /* @__PURE__ */ React.createElement(
|
|
2076
|
+
"meshBasicMaterial",
|
|
2077
|
+
{
|
|
2078
|
+
map: texture,
|
|
2079
|
+
color,
|
|
2080
|
+
...UNLIT_COLOUR_MANAGED,
|
|
2081
|
+
transparent,
|
|
2082
|
+
depthWrite,
|
|
2083
|
+
side: backface === "visible" ? DoubleSide : FrontSide,
|
|
2084
|
+
alphaTest: transparent ? UNLIT_PLANE_ALPHA_TEST : 0
|
|
2085
|
+
}
|
|
2086
|
+
));
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
// ../execution/animate/src/scene/useSceneImageTexture.ts
|
|
2090
|
+
import { useLayoutEffect as useLayoutEffect6, useRef as useRef3, useState as useState3 } from "react";
|
|
2091
|
+
import { useThree as useThree4 } from "@react-three/fiber";
|
|
2092
|
+
import { cancelRender as cancelRender3, continueRender as continueRender3, delayRender as delayRender3 } from "remotion";
|
|
2093
|
+
import { SRGBColorSpace as SRGBColorSpace4, TextureLoader as TextureLoader2 } from "three";
|
|
2094
|
+
|
|
2095
|
+
// ../execution/animate/src/scene/readiness.ts
|
|
2096
|
+
var LoadGenerations = class {
|
|
2097
|
+
current = 0;
|
|
2098
|
+
closed = false;
|
|
2099
|
+
begin() {
|
|
2100
|
+
this.current += 1;
|
|
2101
|
+
return this.current;
|
|
2102
|
+
}
|
|
2103
|
+
isLive(token) {
|
|
2104
|
+
return !this.closed && token === this.current;
|
|
2105
|
+
}
|
|
2106
|
+
close() {
|
|
2107
|
+
this.closed = true;
|
|
2108
|
+
}
|
|
2109
|
+
};
|
|
2110
|
+
var EMPTY_TEXTURE_STATE = { drawn: null, pending: null };
|
|
2111
|
+
function onTextureLoaded(generations, state, token, texture, handle, effects) {
|
|
2112
|
+
if (!generations.isLive(token)) {
|
|
2113
|
+
discardStaleTexture(texture);
|
|
2114
|
+
effects.continueRender(handle);
|
|
2115
|
+
return { state, commit: null };
|
|
2116
|
+
}
|
|
2117
|
+
return { state: { ...state, pending: texture }, commit: { texture, handle } };
|
|
2118
|
+
}
|
|
2119
|
+
function onTextureError(generations, token, error, handle, target, effects) {
|
|
2120
|
+
if (!generations.isLive(token)) {
|
|
2121
|
+
effects.continueRender(handle);
|
|
2122
|
+
return "released";
|
|
2123
|
+
}
|
|
2124
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
2125
|
+
effects.cancelRender(new SceneShotError("scene_asset_load_failed", `${target.what} slot "${target.slot}" failed to load: ${detail}`, `assets.${target.slot}`));
|
|
2126
|
+
return "cancelled";
|
|
2127
|
+
}
|
|
2128
|
+
function onTextureCommitted(state, committed, effects) {
|
|
2129
|
+
effects.redraw();
|
|
2130
|
+
effects.continueRender(committed.handle);
|
|
2131
|
+
const held = commitImageTexture({ drawn: state.drawn }, committed.texture);
|
|
2132
|
+
return { drawn: held.drawn, pending: state.pending === committed.texture ? null : state.pending };
|
|
2133
|
+
}
|
|
2134
|
+
function onTextureOwnerUnmounted(generations, state) {
|
|
2135
|
+
generations.close();
|
|
2136
|
+
releaseImageTexture({ drawn: state.drawn });
|
|
2137
|
+
if (state.pending && state.pending !== state.drawn) discardStaleTexture(state.pending);
|
|
2138
|
+
return EMPTY_TEXTURE_STATE;
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
// ../execution/animate/src/scene/redraw.ts
|
|
2142
|
+
function advanceRendererOnce(advance) {
|
|
2143
|
+
advance(performance.now());
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
// ../execution/animate/src/scene/useSceneImageTexture.ts
|
|
2147
|
+
function useSceneImageTexture(src, slot, what, resourceOwner = `surface:${slot}`) {
|
|
2148
|
+
const registerActual = useSceneActualResourceRegistrarV1();
|
|
2149
|
+
const advance = useThree4((s) => s.advance);
|
|
2150
|
+
const [generations] = useState3(() => new LoadGenerations());
|
|
2151
|
+
const [firstHandle] = useState3(() => delayRender3(`scene: ${what} "${slot}"`));
|
|
2152
|
+
const firstHandleSpent = useRef3(false);
|
|
2153
|
+
const [committed, setCommitted] = useState3(null);
|
|
2154
|
+
const state = useRef3(EMPTY_TEXTURE_STATE);
|
|
2155
|
+
useLayoutEffect6(() => {
|
|
2156
|
+
const token = generations.begin();
|
|
2157
|
+
let handle;
|
|
2158
|
+
if (!firstHandleSpent.current) {
|
|
2159
|
+
firstHandleSpent.current = true;
|
|
2160
|
+
handle = firstHandle;
|
|
2161
|
+
} else {
|
|
2162
|
+
handle = delayRender3(`scene: ${what} "${slot}"`);
|
|
2163
|
+
}
|
|
2164
|
+
new TextureLoader2().load(
|
|
2165
|
+
src,
|
|
2166
|
+
(texture) => {
|
|
2167
|
+
const size = textureImageSize(texture, slot, 0);
|
|
2168
|
+
const releaseMeasurement = registerActual(texture, [{
|
|
2169
|
+
owner: resourceOwner,
|
|
2170
|
+
name: "surface-texture",
|
|
2171
|
+
domain: "gl",
|
|
2172
|
+
bytes: sceneTextureBytes({
|
|
2173
|
+
width: size.width,
|
|
2174
|
+
height: size.height,
|
|
2175
|
+
format: "rgba8",
|
|
2176
|
+
mipLevels: sceneFullMipLevels(size.width, size.height)
|
|
2177
|
+
}),
|
|
2178
|
+
width: size.width,
|
|
2179
|
+
height: size.height
|
|
2180
|
+
}]);
|
|
2181
|
+
texture.addEventListener("dispose", releaseMeasurement);
|
|
2182
|
+
const result = onTextureLoaded(generations, state.current, token, texture, handle, { continueRender: continueRender3 });
|
|
2183
|
+
state.current = result.state;
|
|
2184
|
+
if (!result.commit) return;
|
|
2185
|
+
texture.colorSpace = SRGBColorSpace4;
|
|
2186
|
+
texture.anisotropy = 4;
|
|
2187
|
+
setCommitted(result.commit);
|
|
2188
|
+
},
|
|
2189
|
+
void 0,
|
|
2190
|
+
(error) => {
|
|
2191
|
+
onTextureError(generations, token, error, handle, { slot, what }, { continueRender: continueRender3, cancelRender: cancelRender3 });
|
|
2192
|
+
}
|
|
2193
|
+
);
|
|
2194
|
+
return () => {
|
|
2195
|
+
continueRender3(handle);
|
|
2196
|
+
};
|
|
2197
|
+
}, [src, slot, what, resourceOwner, generations, firstHandle, registerActual]);
|
|
2198
|
+
useLayoutEffect6(() => {
|
|
2199
|
+
if (!committed) return;
|
|
2200
|
+
state.current = onTextureCommitted(state.current, committed, { continueRender: continueRender3, redraw: () => advanceRendererOnce(advance) });
|
|
2201
|
+
}, [committed, advance]);
|
|
2202
|
+
useLayoutEffect6(() => () => {
|
|
2203
|
+
state.current = onTextureOwnerUnmounted(generations, state.current);
|
|
2204
|
+
}, [generations]);
|
|
2205
|
+
return committed?.texture ?? null;
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
// ../execution/animate/src/scene/useWorldTextTexture.ts
|
|
2209
|
+
import { useLayoutEffect as useLayoutEffect7, useRef as useRef4, useState as useState4 } from "react";
|
|
2210
|
+
import { useThree as useThree5 } from "@react-three/fiber";
|
|
2211
|
+
import { cancelRender as cancelRender4, continueRender as continueRender4, delayRender as delayRender4 } from "remotion";
|
|
2212
|
+
|
|
2213
|
+
// ../execution/animate/src/scene/fontReadiness.ts
|
|
2214
|
+
function documentFonts() {
|
|
2215
|
+
const fonts = globalThis.document?.fonts;
|
|
2216
|
+
return fonts ?? null;
|
|
2217
|
+
}
|
|
2218
|
+
function whenFontReady(fonts, shorthand, sample, path) {
|
|
2219
|
+
if (!fonts) {
|
|
2220
|
+
return Promise.reject(new SceneShotError(
|
|
2221
|
+
"scene_font_unavailable",
|
|
2222
|
+
`the font ${shorthand} cannot be gated on this host: it exposes no document.fonts, so a fallback face would draw unremarked`,
|
|
2223
|
+
path
|
|
2224
|
+
));
|
|
2225
|
+
}
|
|
2226
|
+
return fonts.load(shorthand, sample).then(() => fonts.ready).then(() => void 0).catch((error) => {
|
|
2227
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
2228
|
+
throw new SceneShotError("scene_font_unavailable", `the font ${shorthand} could not be loaded: ${detail}`, path);
|
|
2229
|
+
});
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
// ../execution/animate/src/scene/rasterCache.ts
|
|
2233
|
+
var RasterCache = class {
|
|
2234
|
+
entries = /* @__PURE__ */ new Map();
|
|
2235
|
+
acquire(key, create) {
|
|
2236
|
+
const existing = this.entries.get(key);
|
|
2237
|
+
if (existing) {
|
|
2238
|
+
existing.refs += 1;
|
|
2239
|
+
return existing.value;
|
|
2240
|
+
}
|
|
2241
|
+
const value = create();
|
|
2242
|
+
this.entries.set(key, { value, refs: 1 });
|
|
2243
|
+
return value;
|
|
2244
|
+
}
|
|
2245
|
+
release(key, value) {
|
|
2246
|
+
const entry = this.entries.get(key);
|
|
2247
|
+
if (!entry || entry.value !== value) {
|
|
2248
|
+
value.dispose();
|
|
2249
|
+
return;
|
|
2250
|
+
}
|
|
2251
|
+
entry.refs -= 1;
|
|
2252
|
+
if (entry.refs > 0) return;
|
|
2253
|
+
this.entries.delete(key);
|
|
2254
|
+
entry.value.dispose();
|
|
2255
|
+
}
|
|
2256
|
+
/** How many holders a key has right now; 0 when it is not cached. Tests and diagnostics only. */
|
|
2257
|
+
refs(key) {
|
|
2258
|
+
return this.entries.get(key)?.refs ?? 0;
|
|
2259
|
+
}
|
|
2260
|
+
get size() {
|
|
2261
|
+
return this.entries.size;
|
|
2262
|
+
}
|
|
2263
|
+
};
|
|
2264
|
+
var worldTextRasterCache = new RasterCache();
|
|
2265
|
+
|
|
2266
|
+
// ../execution/animate/src/scene/rasterReadiness.ts
|
|
2267
|
+
function onRasterReady(generations, cache, token, key, handle, create, effects) {
|
|
2268
|
+
if (!generations.isLive(token)) {
|
|
2269
|
+
effects.continueRender(handle);
|
|
2270
|
+
return null;
|
|
2271
|
+
}
|
|
2272
|
+
return { key, raster: cache.acquire(key, create), handle };
|
|
2273
|
+
}
|
|
2274
|
+
function onRasterCommitted(cache, held, committed, effects) {
|
|
2275
|
+
effects.redraw();
|
|
2276
|
+
effects.continueRender(committed.handle);
|
|
2277
|
+
if (held) cache.release(held.key, held.raster);
|
|
2278
|
+
return committed;
|
|
2279
|
+
}
|
|
2280
|
+
function onRasterOwnerUnmounted(generations, cache, held) {
|
|
2281
|
+
generations.close();
|
|
2282
|
+
if (held) cache.release(held.key, held.raster);
|
|
2283
|
+
return null;
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2286
|
+
// ../execution/animate/src/scene/textLayout.ts
|
|
2287
|
+
function textBlockLayout(layer, scale) {
|
|
2288
|
+
const fontSize = layer.fontSize * scale;
|
|
2289
|
+
const lineBox = fontSize * layer.lineHeight;
|
|
2290
|
+
return {
|
|
2291
|
+
width: layer.width * scale,
|
|
2292
|
+
height: layer.lines.length * lineBox,
|
|
2293
|
+
scale,
|
|
2294
|
+
fontSize,
|
|
2295
|
+
lineHeight: layer.lineHeight,
|
|
2296
|
+
lineBox,
|
|
2297
|
+
align: layer.align,
|
|
2298
|
+
lines: layer.lines.map((_, index) => ({ index, top: index * lineBox, height: lineBox }))
|
|
2299
|
+
};
|
|
2300
|
+
}
|
|
2301
|
+
function lineBaselineY(box2, metrics) {
|
|
2302
|
+
const halfLeading = (box2.height - (metrics.ascent + metrics.descent)) / 2;
|
|
2303
|
+
return box2.top + halfLeading + metrics.ascent;
|
|
2304
|
+
}
|
|
2305
|
+
function lineOriginX(layout, lineWidth) {
|
|
2306
|
+
switch (layout.align) {
|
|
2307
|
+
case "left":
|
|
2308
|
+
return 0;
|
|
2309
|
+
case "center":
|
|
2310
|
+
return (layout.width - lineWidth) / 2;
|
|
2311
|
+
case "right":
|
|
2312
|
+
return layout.width - lineWidth;
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
function resolveSceneFontFamily(family, path) {
|
|
2316
|
+
if (family.startsWith("$brand:")) {
|
|
2317
|
+
throw new SceneShotError("scene_brand_unresolved", `brand reference "${family}" was not resolved before rendering`, path);
|
|
2318
|
+
}
|
|
2319
|
+
return family;
|
|
2320
|
+
}
|
|
2321
|
+
function textFontShorthand(layer, scale, path = "fontFamily") {
|
|
2322
|
+
return `${layer.fontStyle} ${layer.fontWeight} ${layer.fontSize * scale}px "${resolveSceneFontFamily(layer.fontFamily, path)}"`;
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
// ../execution/animate/src/scene/worldTextTexture.ts
|
|
2326
|
+
import { CanvasTexture as CanvasTexture2, LinearFilter, LinearMipmapLinearFilter, SRGBColorSpace as SRGBColorSpace5 } from "three";
|
|
2327
|
+
|
|
2328
|
+
// ../execution/animate/src/scene/backdrop.ts
|
|
2329
|
+
function resolveSceneColor(color, path) {
|
|
2330
|
+
if (color.startsWith("$brand:")) {
|
|
2331
|
+
throw new SceneShotError("scene_brand_unresolved", `brand reference "${color}" was not resolved before rendering`, path);
|
|
2332
|
+
}
|
|
2333
|
+
return color;
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2336
|
+
// ../execution/animate/src/scene/worldTextRaster.ts
|
|
2337
|
+
var WORLD_TEXT_MAX_TEXTURE = STUDIO_SHADOW_MAP_BUDGET;
|
|
2338
|
+
function worldTextCacheKey(layer, scale, index) {
|
|
2339
|
+
return JSON.stringify([
|
|
2340
|
+
scale,
|
|
2341
|
+
resolveSceneFontFamily(layer.fontFamily, `layers.${index}.fontFamily`),
|
|
2342
|
+
layer.fontWeight,
|
|
2343
|
+
layer.fontStyle,
|
|
2344
|
+
layer.fontSize,
|
|
2345
|
+
layer.lineHeight,
|
|
2346
|
+
layer.letterSpacing,
|
|
2347
|
+
layer.align,
|
|
2348
|
+
layer.width,
|
|
2349
|
+
resolveSceneColor(layer.color, `layers.${index}.color`),
|
|
2350
|
+
layer.lines.map((line, l) => line.runs.map((run, r) => [
|
|
2351
|
+
run.text,
|
|
2352
|
+
run.emphasis ?? false,
|
|
2353
|
+
run.color === void 0 ? null : resolveSceneColor(run.color, `layers.${index}.lines.${l}.runs.${r}.color`)
|
|
2354
|
+
]))
|
|
2355
|
+
]);
|
|
2356
|
+
}
|
|
2357
|
+
function worldTextRasterSize(layout, layerId, index) {
|
|
2358
|
+
const width = Math.max(1, Math.ceil(layout.width));
|
|
2359
|
+
const height = Math.max(1, Math.ceil(layout.height));
|
|
2360
|
+
if (width > WORLD_TEXT_MAX_TEXTURE || height > WORLD_TEXT_MAX_TEXTURE) {
|
|
2361
|
+
throw new SceneShotError(
|
|
2362
|
+
"scene_resource_exhausted",
|
|
2363
|
+
`world text layer "${layerId}" rasterizes to ${width}x${height}, past the ${WORLD_TEXT_MAX_TEXTURE} texture limit; narrow the layer or render smaller`,
|
|
2364
|
+
`layers.${index}.width`
|
|
2365
|
+
);
|
|
2366
|
+
}
|
|
2367
|
+
return { width, height };
|
|
2368
|
+
}
|
|
2369
|
+
function faceMetrics(ctx, index) {
|
|
2370
|
+
const m = ctx.measureText("Hxg");
|
|
2371
|
+
if (m.fontBoundingBoxAscent === void 0 || m.fontBoundingBoxDescent === void 0) {
|
|
2372
|
+
throw new SceneShotError(
|
|
2373
|
+
"scene_internal",
|
|
2374
|
+
"this renderer's 2D context reports no font-box metrics (`fontBoundingBoxAscent`/`fontBoundingBoxDescent`), so a world-text baseline cannot be placed where the DOM path would place it; render on a browser that reports them",
|
|
2375
|
+
`layers.${index}`
|
|
2376
|
+
);
|
|
2377
|
+
}
|
|
2378
|
+
return { ascent: m.fontBoundingBoxAscent, descent: m.fontBoundingBoxDescent };
|
|
2379
|
+
}
|
|
2380
|
+
function drawWorldText(ctx, layer, layout, index) {
|
|
2381
|
+
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
2382
|
+
ctx.font = textFontShorthand(layer, layout.scale, `layers.${index}.fontFamily`);
|
|
2383
|
+
ctx.textAlign = "left";
|
|
2384
|
+
ctx.textBaseline = "alphabetic";
|
|
2385
|
+
ctx.letterSpacing = `${layer.letterSpacing * layout.scale}px`;
|
|
2386
|
+
const metrics = faceMetrics(ctx, index);
|
|
2387
|
+
const base = resolveSceneColor(layer.color, `layers.${index}.color`);
|
|
2388
|
+
layer.lines.forEach((line, lineIndex) => {
|
|
2389
|
+
const box2 = layout.lines[lineIndex];
|
|
2390
|
+
const y = lineBaselineY(box2, metrics);
|
|
2391
|
+
const faces = resolveCaptionFaces({ fontFamily: resolveSceneFontFamily(layer.fontFamily, `layers.${index}.fontFamily`), fontWeight: layer.fontWeight });
|
|
2392
|
+
const runFont = (emphasis) => `${emphasis ? faces.emphasis.style : layer.fontStyle} ${emphasis ? faces.emphasis.weight : layer.fontWeight} ${layout.fontSize}px "${resolveSceneFontFamily(layer.fontFamily, `layers.${index}.fontFamily`)}"`;
|
|
2393
|
+
const widths = line.runs.map((run) => {
|
|
2394
|
+
ctx.font = runFont(run.emphasis);
|
|
2395
|
+
return ctx.measureText(run.text).width;
|
|
2396
|
+
});
|
|
2397
|
+
let x = lineOriginX(layout, widths.reduce((a, b) => a + b, 0));
|
|
2398
|
+
line.runs.forEach((run, runIndex) => {
|
|
2399
|
+
ctx.font = runFont(run.emphasis);
|
|
2400
|
+
ctx.fillStyle = run.color === void 0 ? base : resolveSceneColor(run.color, `layers.${index}.lines.${lineIndex}.runs.${runIndex}.color`);
|
|
2401
|
+
ctx.fillText(run.text, x, y);
|
|
2402
|
+
x += widths[runIndex];
|
|
2403
|
+
});
|
|
2404
|
+
});
|
|
2405
|
+
}
|
|
2406
|
+
function worldTextLayout(layer, scale) {
|
|
2407
|
+
return textBlockLayout(layer, scale);
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
// ../execution/animate/src/scene/worldTextTexture.ts
|
|
2411
|
+
function createWorldTextTexture(request, registerActual = registerActualSceneResourcesV1) {
|
|
2412
|
+
const document2 = globalThis.document;
|
|
2413
|
+
if (!document2) throw new SceneShotError("scene_internal", "world text needs a document to rasterize into");
|
|
2414
|
+
const canvas = document2.createElement("canvas");
|
|
2415
|
+
canvas.width = request.size.width;
|
|
2416
|
+
canvas.height = request.size.height;
|
|
2417
|
+
const ctx = canvas.getContext("2d");
|
|
2418
|
+
if (!ctx) {
|
|
2419
|
+
throw new SceneShotError("scene_internal", `world text layer "${request.layer.id}" could not open a 2D context`, `layers.${request.index}.lines`);
|
|
2420
|
+
}
|
|
2421
|
+
drawWorldText(ctx, request.layer, request.layout, request.index);
|
|
2422
|
+
const texture = new CanvasTexture2(canvas);
|
|
2423
|
+
texture.colorSpace = SRGBColorSpace5;
|
|
2424
|
+
texture.generateMipmaps = true;
|
|
2425
|
+
texture.minFilter = LinearMipmapLinearFilter;
|
|
2426
|
+
texture.magFilter = LinearFilter;
|
|
2427
|
+
texture.anisotropy = request.anisotropy;
|
|
2428
|
+
texture.needsUpdate = true;
|
|
2429
|
+
const rgbaBytes = request.size.width * request.size.height * 4;
|
|
2430
|
+
const releaseMeasurement = registerActual(texture, [
|
|
2431
|
+
{
|
|
2432
|
+
owner: `text:${request.layer.id}`,
|
|
2433
|
+
name: "raster-canvas",
|
|
2434
|
+
domain: "cpu",
|
|
2435
|
+
bytes: rgbaBytes,
|
|
2436
|
+
width: request.size.width,
|
|
2437
|
+
height: request.size.height,
|
|
2438
|
+
byteLength: rgbaBytes
|
|
2439
|
+
},
|
|
2440
|
+
{
|
|
2441
|
+
owner: `text:${request.layer.id}`,
|
|
2442
|
+
name: "raster-mip-chain",
|
|
2443
|
+
domain: "gl",
|
|
2444
|
+
bytes: sceneTextureBytes({
|
|
2445
|
+
width: request.size.width,
|
|
2446
|
+
height: request.size.height,
|
|
2447
|
+
format: "rgba8",
|
|
2448
|
+
mipLevels: sceneFullMipLevels(request.size.width, request.size.height)
|
|
2449
|
+
}),
|
|
2450
|
+
width: request.size.width,
|
|
2451
|
+
height: request.size.height
|
|
2452
|
+
}
|
|
2453
|
+
]);
|
|
2454
|
+
texture.addEventListener("dispose", releaseMeasurement);
|
|
2455
|
+
return texture;
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2458
|
+
// ../execution/animate/src/scene/useWorldTextTexture.ts
|
|
2459
|
+
function useWorldTextTexture(prepared) {
|
|
2460
|
+
const registerActual = useSceneActualResourceRegistrarV1();
|
|
2461
|
+
const { layer, index, layout, size, key } = prepared;
|
|
2462
|
+
const advance = useThree5((s) => s.advance);
|
|
2463
|
+
const gl = useThree5((s) => s.gl);
|
|
2464
|
+
const [generations] = useState4(() => new LoadGenerations());
|
|
2465
|
+
const [firstHandle] = useState4(() => delayRender4(`scene: world text "${layer.id}"`));
|
|
2466
|
+
const firstHandleSpent = useRef4(false);
|
|
2467
|
+
const [committed, setCommitted] = useState4(null);
|
|
2468
|
+
const held = useRef4(null);
|
|
2469
|
+
const request = useRef4({ layer, layout, size, index });
|
|
2470
|
+
useLayoutEffect7(() => {
|
|
2471
|
+
request.current = { layer, layout, size, index };
|
|
2472
|
+
});
|
|
2473
|
+
useLayoutEffect7(() => {
|
|
2474
|
+
const token = generations.begin();
|
|
2475
|
+
let handle;
|
|
2476
|
+
if (!firstHandleSpent.current) {
|
|
2477
|
+
firstHandleSpent.current = true;
|
|
2478
|
+
handle = firstHandle;
|
|
2479
|
+
} else {
|
|
2480
|
+
handle = delayRender4(`scene: world text "${request.current.layer.id}"`);
|
|
2481
|
+
}
|
|
2482
|
+
const anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
2483
|
+
const { layer: current, index: at } = request.current;
|
|
2484
|
+
const shorthand = textFontShorthand(current, request.current.layout.scale, `layers.${at}.fontFamily`);
|
|
2485
|
+
const faces = resolveCaptionFaces({ fontFamily: current.fontFamily, fontWeight: current.fontWeight });
|
|
2486
|
+
const samples = { base: "", emphasis: "" };
|
|
2487
|
+
for (const line of current.lines) for (const run of line.runs) samples[run.emphasis ? "emphasis" : "base"] += run.text;
|
|
2488
|
+
const readiness = [whenFontReady(documentFonts(), shorthand, samples.base || " ", `layers.${at}.fontFamily`)];
|
|
2489
|
+
if (samples.emphasis) readiness.push(whenFontReady(documentFonts(), `${faces.emphasis.style} ${faces.emphasis.weight} ${request.current.layout.fontSize}px "${current.fontFamily}"`, samples.emphasis, `layers.${at}.fontWeight`));
|
|
2490
|
+
Promise.all(readiness).then(() => {
|
|
2491
|
+
const ready = onRasterReady(generations, worldTextRasterCache, token, key, handle, () => createWorldTextTexture({ ...request.current, anisotropy }, registerActual), { continueRender: continueRender4 });
|
|
2492
|
+
if (ready) setCommitted(ready);
|
|
2493
|
+
}).catch((error) => {
|
|
2494
|
+
if (!generations.isLive(token)) {
|
|
2495
|
+
continueRender4(handle);
|
|
2496
|
+
return;
|
|
2497
|
+
}
|
|
2498
|
+
cancelRender4(error instanceof Error ? error : new Error(String(error)));
|
|
2499
|
+
});
|
|
2500
|
+
return () => {
|
|
2501
|
+
continueRender4(handle);
|
|
2502
|
+
};
|
|
2503
|
+
}, [key, gl, generations, firstHandle, registerActual]);
|
|
2504
|
+
useLayoutEffect7(() => {
|
|
2505
|
+
if (!committed) return;
|
|
2506
|
+
held.current = onRasterCommitted(worldTextRasterCache, held.current, committed, { continueRender: continueRender4, redraw: () => advanceRendererOnce(advance) });
|
|
2507
|
+
}, [committed, advance]);
|
|
2508
|
+
useLayoutEffect7(() => () => {
|
|
2509
|
+
held.current = onRasterOwnerUnmounted(generations, worldTextRasterCache, held.current);
|
|
2510
|
+
}, [generations]);
|
|
2511
|
+
return committed?.raster ?? null;
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2514
|
+
// ../execution/animate/src/scene/preparedWorldText.ts
|
|
2515
|
+
function worldTextPlaneFit(layout) {
|
|
2516
|
+
return { size: { width: layout.width, height: layout.height }, repeat: [1, 1], offset: [0, 0] };
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2519
|
+
// ../execution/animate/src/scene/v2/builders.tsx
|
|
2520
|
+
function LoadedSceneSurface({ src, slot, what, resourceOwner, children }) {
|
|
2521
|
+
return children(useSceneImageTexture(src, slot, what, resourceOwner));
|
|
2522
|
+
}
|
|
2523
|
+
var sceneDeviceResourceOwnerV1 = (node) => `${node.kind}:${node.id}`;
|
|
2524
|
+
var slabContentFit = (width, height, image) => planeFit("contain", { width, height }, image);
|
|
2525
|
+
function PosedObject({ transform, scale, opacity, children }) {
|
|
2526
|
+
const group = useRef5(null);
|
|
2527
|
+
const pose = useMemo5(() => sceneLayerPose(scaleSceneTransform(transform, scale)), [
|
|
2528
|
+
transform.position[0],
|
|
2529
|
+
transform.position[1],
|
|
2530
|
+
transform.position[2],
|
|
2531
|
+
transform.rotation[0],
|
|
2532
|
+
transform.rotation[1],
|
|
2533
|
+
transform.rotation[2],
|
|
2534
|
+
transform.scale,
|
|
2535
|
+
scale
|
|
2536
|
+
]);
|
|
2537
|
+
useLayoutEffect8(() => {
|
|
2538
|
+
if (group.current) applyLayerOpacity(group.current, opacity);
|
|
2539
|
+
}, [opacity]);
|
|
2540
|
+
return /* @__PURE__ */ React22.createElement("group", { ref: group, visible: opacity > 0, position: pose.position, quaternion: pose.quaternion, scale: pose.scale }, children);
|
|
2541
|
+
}
|
|
2542
|
+
function LaptopObject({ node, src, screenColor, preparedSurface, scale, surfaceResourceOwner, glassOpacity = DEVICE_GLASS_OPACITY_LINEAR, mountEarly = false }) {
|
|
2543
|
+
const materialOverrides = Object.fromEntries((node.materials ?? []).map((material) => [material.role, material]));
|
|
2544
|
+
const binding = node.surfaces?.screen;
|
|
2545
|
+
const slot = binding && "assetSlot" in binding ? binding.assetSlot : `${node.id}.screen`;
|
|
2546
|
+
const render = (screen, color = screenColor, unbound = false) => {
|
|
2547
|
+
if (!unbound && !color && !mountEarly && !screen) return null;
|
|
2548
|
+
return /* @__PURE__ */ React22.createElement(PosedObject, { transform: node.transform, scale, opacity: node.opacity }, /* @__PURE__ */ React22.createElement(
|
|
2549
|
+
DeviceMesh,
|
|
2550
|
+
{
|
|
2551
|
+
kind: "laptop",
|
|
2552
|
+
screen: color ? null : screen,
|
|
2553
|
+
screenColor: color,
|
|
2554
|
+
materialOverrides,
|
|
2555
|
+
finish: node.materials?.find((material) => material.role === "shell")?.color ?? "#2a2a30",
|
|
2556
|
+
glassOpacity,
|
|
2557
|
+
openAngle: node.openAngle * 180 / Math.PI,
|
|
2558
|
+
width: node.width * scale,
|
|
2559
|
+
resourceOwner: sceneDeviceResourceOwnerV1(node)
|
|
2560
|
+
}
|
|
2561
|
+
));
|
|
2562
|
+
};
|
|
2563
|
+
if (preparedSurface) return render(preparedSurface.kind === "texture" ? preparedSurface.texture : null, preparedSurface.kind === "color" ? preparedSurface.color : void 0);
|
|
2564
|
+
if (screenColor) return render(null, screenColor);
|
|
2565
|
+
if (!src) return render(null, void 0, true);
|
|
2566
|
+
return /* @__PURE__ */ React22.createElement(LoadedSceneSurface, { src, slot, what: "screenshot", resourceOwner: surfaceResourceOwner }, render);
|
|
2567
|
+
}
|
|
2568
|
+
function PhoneObject({ node, src, screenColor, preparedSurface, scale, surfaceResourceOwner, glassOpacity = DEVICE_GLASS_OPACITY_LINEAR, mountEarly = false }) {
|
|
2569
|
+
const materialOverrides = Object.fromEntries((node.materials ?? []).map((material) => [material.role, material]));
|
|
2570
|
+
const binding = node.surfaces?.screen;
|
|
2571
|
+
const slot = binding && "assetSlot" in binding ? binding.assetSlot : `${node.id}.screen`;
|
|
2572
|
+
const render = (screen, color = screenColor, unbound = false) => {
|
|
2573
|
+
if (!unbound && !color && !mountEarly && !screen) return null;
|
|
2574
|
+
return /* @__PURE__ */ React22.createElement(PosedObject, { transform: node.transform, scale, opacity: node.opacity }, /* @__PURE__ */ React22.createElement(
|
|
2575
|
+
DeviceMesh,
|
|
2576
|
+
{
|
|
2577
|
+
kind: "phone",
|
|
2578
|
+
screen: color ? null : screen,
|
|
2579
|
+
screenColor: color,
|
|
2580
|
+
materialOverrides,
|
|
2581
|
+
finish: node.materials?.find((material) => material.role === "shell")?.color ?? "#2a2a30",
|
|
2582
|
+
glassOpacity,
|
|
2583
|
+
width: node.width * scale,
|
|
2584
|
+
resourceOwner: sceneDeviceResourceOwnerV1(node)
|
|
2585
|
+
}
|
|
2586
|
+
));
|
|
2587
|
+
};
|
|
2588
|
+
if (preparedSurface) return render(preparedSurface.kind === "texture" ? preparedSurface.texture : null, preparedSurface.kind === "color" ? preparedSurface.color : void 0);
|
|
2589
|
+
if (screenColor) return render(null, screenColor);
|
|
2590
|
+
if (!src) return render(null, void 0, true);
|
|
2591
|
+
return /* @__PURE__ */ React22.createElement(LoadedSceneSurface, { src, slot, what: "screenshot", resourceOwner: surfaceResourceOwner }, render);
|
|
2592
|
+
}
|
|
2593
|
+
var SLAB_CONTENT_OFFSET = SCENE_SLAB_CONTENT_OFFSET;
|
|
2594
|
+
function SlabObject({ node, src, frontColor, preparedSurface, scale, surfaceResourceOwner, mountEarly = false, expectedBodyTriangles }) {
|
|
2595
|
+
const bound = node.surfaces?.front;
|
|
2596
|
+
const faceOverride = node.materials?.find((material) => material.role === "face");
|
|
2597
|
+
const frontSlot = bound && "assetSlot" in bound ? bound.assetSlot : `${node.id}.front`;
|
|
2598
|
+
const hasFront = Boolean(bound || frontColor || preparedSurface);
|
|
2599
|
+
const width = node.width * scale;
|
|
2600
|
+
const height = node.height * scale;
|
|
2601
|
+
const thickness = node.thickness * scale;
|
|
2602
|
+
const { geometry, finish } = useOwnedSlabResources(
|
|
2603
|
+
width,
|
|
2604
|
+
height,
|
|
2605
|
+
thickness,
|
|
2606
|
+
node.cornerRadius * scale,
|
|
2607
|
+
node.edgeRadius * scale,
|
|
2608
|
+
node.finish,
|
|
2609
|
+
node.materials?.find((material) => material.role === "body")?.color ?? SLAB_DEFAULTS.baseColor,
|
|
2610
|
+
node.materials?.find((material) => material.role === "body"),
|
|
2611
|
+
`slab:${node.id}`
|
|
2612
|
+
);
|
|
2613
|
+
if (expectedBodyTriangles !== void 0 && slabTriangleCount(geometry) !== expectedBodyTriangles) {
|
|
2614
|
+
throw new Error(`scene_builder_descriptor_mismatch: slab '${node.id}' built ${slabTriangleCount(geometry)} body triangles; sealed ${expectedBodyTriangles}.`);
|
|
2615
|
+
}
|
|
2616
|
+
const render = (front, color = frontColor) => {
|
|
2617
|
+
const contentFit = front && bound ? slabContentFit(width, height, textureImageSize(front, frontSlot, 0)) : null;
|
|
2618
|
+
if (bound && !color && !mountEarly && !front) return null;
|
|
2619
|
+
return /* @__PURE__ */ React22.createElement(PosedObject, { transform: node.transform, scale, opacity: node.opacity }, /* @__PURE__ */ React22.createElement(
|
|
2620
|
+
"mesh",
|
|
2621
|
+
{
|
|
2622
|
+
geometry,
|
|
2623
|
+
material: finish.material,
|
|
2624
|
+
castShadow: true,
|
|
2625
|
+
receiveShadow: true,
|
|
2626
|
+
onBeforeRender: takeSceneEnvironment
|
|
2627
|
+
}
|
|
2628
|
+
), hasFront && (color || front || mountEarly) ? /* @__PURE__ */ React22.createElement("group", { position: [0, 0, thickness / 2 + SLAB_CONTENT_OFFSET * scale] }, mountEarly ? /* @__PURE__ */ React22.createElement("mesh", null, /* @__PURE__ */ React22.createElement("planeGeometry", { args: [width, height] }), /* @__PURE__ */ React22.createElement("meshBasicMaterial", { map: front, transparent: true, ...UNLIT_COLOUR_MANAGED })) : color ? /* @__PURE__ */ React22.createElement("mesh", null, /* @__PURE__ */ React22.createElement(MeasuredPlaneGeometry, { width, height, owner: `slab:${node.id}`, name: "front-geometry" }), /* @__PURE__ */ React22.createElement("meshBasicMaterial", { color: faceOverride?.color ?? color, ...UNLIT_COLOUR_MANAGED })) : front && contentFit ? /* @__PURE__ */ React22.createElement(UnlitPlane, { texture: front, fit: contentFit, color: faceOverride?.color, resourceOwner: `slab:${node.id}`, resourceName: "front-geometry" }) : null) : null);
|
|
2629
|
+
};
|
|
2630
|
+
if (preparedSurface) return render(preparedSurface.kind === "texture" ? preparedSurface.texture : null, preparedSurface.kind === "color" ? preparedSurface.color : void 0);
|
|
2631
|
+
if (frontColor) return render(null, frontColor);
|
|
2632
|
+
if (!src) return render(null);
|
|
2633
|
+
return /* @__PURE__ */ React22.createElement(LoadedSceneSurface, { src, slot: frontSlot, what: "page image", resourceOwner: surfaceResourceOwner }, render);
|
|
2634
|
+
}
|
|
2635
|
+
function useOwnedSlabResources(width, height, thickness, cornerRadius, edgeRadius, finishName, baseColor, materialOverride, owner = "slab:unscoped") {
|
|
2636
|
+
const registerActual = useSceneActualResourceRegistrarV1();
|
|
2637
|
+
const geometry = useMemo5(
|
|
2638
|
+
() => slabBodyGeometry(width, height, thickness, cornerRadius, edgeRadius),
|
|
2639
|
+
[width, height, thickness, cornerRadius, edgeRadius]
|
|
2640
|
+
);
|
|
2641
|
+
const finish = useMemo5(() => slabFinishMaterial(finishName, baseColor, materialOverride, owner, registerActual), [
|
|
2642
|
+
finishName,
|
|
2643
|
+
baseColor,
|
|
2644
|
+
materialOverride?.type,
|
|
2645
|
+
materialOverride?.color,
|
|
2646
|
+
materialOverride?.roughness,
|
|
2647
|
+
materialOverride?.metalness,
|
|
2648
|
+
materialOverride?.clearcoat,
|
|
2649
|
+
materialOverride?.clearcoatRoughness,
|
|
2650
|
+
materialOverride?.anisotropy,
|
|
2651
|
+
materialOverride?.anisotropyRotation,
|
|
2652
|
+
materialOverride?.ior,
|
|
2653
|
+
materialOverride?.reflectivity,
|
|
2654
|
+
owner,
|
|
2655
|
+
registerActual
|
|
2656
|
+
]);
|
|
2657
|
+
const geometryBytes = (geometry.index?.array.byteLength ?? 0) + Object.values(geometry.attributes).reduce((sum, attribute) => sum + attribute.array.byteLength, 0);
|
|
2658
|
+
const geometryMeasurement = useMemo5(() => registerActual(geometry, [
|
|
2659
|
+
{ owner, name: "body-geometry", domain: "gl", bytes: geometryBytes },
|
|
2660
|
+
{ owner, name: "body-geometry-arrays", domain: "cpu", bytes: geometryBytes }
|
|
2661
|
+
]), [geometry, geometryBytes, owner, registerActual]);
|
|
2662
|
+
useLayoutEffect8(() => () => {
|
|
2663
|
+
geometry.dispose();
|
|
2664
|
+
geometryMeasurement();
|
|
2665
|
+
}, [geometry, geometryMeasurement]);
|
|
2666
|
+
useLayoutEffect8(() => () => finish.dispose(), [finish]);
|
|
2667
|
+
return { geometry, finish };
|
|
2668
|
+
}
|
|
2669
|
+
function PageObject({ node, src, contentColor, preparedSurface, scale, surfaceResourceOwner, mountEarly = false }) {
|
|
2670
|
+
const binding = node.surfaces?.content;
|
|
2671
|
+
const slot = binding && "assetSlot" in binding ? binding.assetSlot : `${node.id}.content`;
|
|
2672
|
+
const baseOverride = node.materials?.find((material) => material.role === "base");
|
|
2673
|
+
const box2 = { width: node.width * scale, height: node.height * scale };
|
|
2674
|
+
const render = (texture, color = contentColor) => {
|
|
2675
|
+
if (mountEarly) {
|
|
2676
|
+
return /* @__PURE__ */ React22.createElement(PosedObject, { transform: node.transform, scale, opacity: node.opacity }, /* @__PURE__ */ React22.createElement("mesh", null, /* @__PURE__ */ React22.createElement("planeGeometry", { args: [box2.width, box2.height] }), /* @__PURE__ */ React22.createElement("meshBasicMaterial", { map: texture, ...UNLIT_COLOUR_MANAGED, transparent: true, alphaTest: UNLIT_PLANE_ALPHA_TEST })));
|
|
2677
|
+
}
|
|
2678
|
+
if (color) return /* @__PURE__ */ React22.createElement(PosedObject, { transform: node.transform, scale, opacity: node.opacity }, /* @__PURE__ */ React22.createElement("mesh", null, /* @__PURE__ */ React22.createElement(MeasuredPlaneGeometry, { width: box2.width, height: box2.height, owner: `page:${node.id}`, name: "content-geometry" }), /* @__PURE__ */ React22.createElement(
|
|
2679
|
+
"meshBasicMaterial",
|
|
2680
|
+
{
|
|
2681
|
+
color: baseOverride?.color ?? color,
|
|
2682
|
+
...UNLIT_COLOUR_MANAGED,
|
|
2683
|
+
transparent: node.transparency !== "opaque",
|
|
2684
|
+
depthWrite: node.depthWrite,
|
|
2685
|
+
side: node.backface === "visible" ? DoubleSide2 : FrontSide2
|
|
2686
|
+
}
|
|
2687
|
+
)));
|
|
2688
|
+
if (!texture) return null;
|
|
2689
|
+
const image = textureImageSize(texture, slot, 0);
|
|
2690
|
+
const fit = planeFit(node.fit, box2, image);
|
|
2691
|
+
return /* @__PURE__ */ React22.createElement(PosedObject, { transform: node.transform, scale, opacity: node.opacity }, /* @__PURE__ */ React22.createElement(UnlitPlane, { texture, fit, color: baseOverride?.color, transparent: node.transparency !== "opaque", depthWrite: node.depthWrite, backface: node.backface, resourceOwner: `page:${node.id}`, resourceName: "content-geometry" }));
|
|
2692
|
+
};
|
|
2693
|
+
if (preparedSurface) return render(preparedSurface.kind === "texture" ? preparedSurface.texture : null, preparedSurface.kind === "color" ? preparedSurface.color : void 0);
|
|
2694
|
+
if (contentColor) return render(null, contentColor);
|
|
2695
|
+
return /* @__PURE__ */ React22.createElement(LoadedSceneSurface, { src, slot, what: "page image", resourceOwner: surfaceResourceOwner }, render);
|
|
2696
|
+
}
|
|
2697
|
+
function WorldTextObject({ node, index, scale, referenceWidth }) {
|
|
2698
|
+
const prepared = useMemo5(() => {
|
|
2699
|
+
const rasterNode = { ...node, width: node.maxWidth ?? referenceWidth };
|
|
2700
|
+
const layout = worldTextLayout(rasterNode, scale);
|
|
2701
|
+
return {
|
|
2702
|
+
kind: "worldText",
|
|
2703
|
+
layer: rasterNode,
|
|
2704
|
+
index,
|
|
2705
|
+
layout,
|
|
2706
|
+
size: worldTextRasterSize(layout, node.id, index),
|
|
2707
|
+
key: worldTextCacheKey(rasterNode, scale, index)
|
|
2708
|
+
};
|
|
2709
|
+
}, [node, index, scale, referenceWidth]);
|
|
2710
|
+
const texture = useWorldTextTexture(prepared);
|
|
2711
|
+
if (!texture) return null;
|
|
2712
|
+
return /* @__PURE__ */ React22.createElement(PosedObject, { transform: node.transform, scale, opacity: node.opacity }, /* @__PURE__ */ React22.createElement(UnlitPlane, { texture, fit: worldTextPlaneFit(prepared.layout), resourceOwner: `text:${node.id}`, resourceName: "plane-geometry" }));
|
|
2713
|
+
}
|
|
2714
|
+
|
|
2715
|
+
// ../execution/animate/src/scene/v2/slots.ts
|
|
2716
|
+
var BOTH_SCALES = [2, 3];
|
|
2717
|
+
function sceneSlotsFor(node) {
|
|
2718
|
+
switch (node.kind) {
|
|
2719
|
+
case "laptop":
|
|
2720
|
+
return [{
|
|
2721
|
+
slot: "screen",
|
|
2722
|
+
attachment: { part: "lid", materialRole: "screen" },
|
|
2723
|
+
dimensions: { width: node.width * 0.86, height: node.width * 0.54 },
|
|
2724
|
+
uvOrigin: "top-left",
|
|
2725
|
+
fit: "contain",
|
|
2726
|
+
alpha: "straight",
|
|
2727
|
+
depth: "test-only",
|
|
2728
|
+
required: false,
|
|
2729
|
+
bakeScales: BOTH_SCALES
|
|
2730
|
+
}];
|
|
2731
|
+
case "slab":
|
|
2732
|
+
return [{
|
|
2733
|
+
slot: "front",
|
|
2734
|
+
attachment: { part: "body", materialRole: "face" },
|
|
2735
|
+
dimensions: { width: node.width, height: node.height },
|
|
2736
|
+
uvOrigin: "top-left",
|
|
2737
|
+
fit: "contain",
|
|
2738
|
+
alpha: "straight",
|
|
2739
|
+
depth: "test-only",
|
|
2740
|
+
required: false,
|
|
2741
|
+
bakeScales: BOTH_SCALES
|
|
2742
|
+
}];
|
|
2743
|
+
case "page":
|
|
2744
|
+
return [{
|
|
2745
|
+
slot: "content",
|
|
2746
|
+
attachment: { part: "quad", materialRole: "base" },
|
|
2747
|
+
dimensions: { width: node.width, height: node.height },
|
|
2748
|
+
// A page's alpha and depth follow its own declared fields; `fit` is the author's.
|
|
2749
|
+
uvOrigin: "top-left",
|
|
2750
|
+
fit: node.fit,
|
|
2751
|
+
alpha: "straight",
|
|
2752
|
+
depth: "write",
|
|
2753
|
+
// The ONE required slot in the table: a page with no content is not a page.
|
|
2754
|
+
required: true,
|
|
2755
|
+
bakeScales: BOTH_SCALES
|
|
2756
|
+
}];
|
|
2757
|
+
default:
|
|
2758
|
+
return [];
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
function collect(nodes, ancestors, out) {
|
|
2762
|
+
for (const node of nodes) {
|
|
2763
|
+
if (node.kind === "text" && node.space === "screen") continue;
|
|
2764
|
+
const chain = [...ancestors, node.transform];
|
|
2765
|
+
if (node.kind === "group") {
|
|
2766
|
+
collect(node.children, chain, out);
|
|
2767
|
+
continue;
|
|
2768
|
+
}
|
|
2769
|
+
const bindings = node.surfaces;
|
|
2770
|
+
if (!bindings) continue;
|
|
2771
|
+
for (const descriptor of sceneSlotsFor(node)) {
|
|
2772
|
+
const binding = bindings[descriptor.slot];
|
|
2773
|
+
if (binding) out.push({ layerId: node.id, slot: descriptor.slot, binding, dimensions: descriptor.dimensions, chain });
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
function sceneBoundSurfaces(spec2) {
|
|
2778
|
+
const out = [];
|
|
2779
|
+
collect(spec2.layers, [], out);
|
|
2780
|
+
return out;
|
|
2781
|
+
}
|
|
2782
|
+
function assertSceneSurfaceResolution(spec2, output) {
|
|
2783
|
+
for (const surface of sceneBoundSurfaces(spec2)) {
|
|
2784
|
+
if (surface.binding.source !== "component") continue;
|
|
2785
|
+
const { layout, bakeScale } = surface.binding;
|
|
2786
|
+
selectSceneBakeScale({
|
|
2787
|
+
surfaceId: surface.layerId,
|
|
2788
|
+
slotName: surface.slot,
|
|
2789
|
+
slot: surface.dimensions,
|
|
2790
|
+
layout,
|
|
2791
|
+
contentDuration: 1,
|
|
2792
|
+
output,
|
|
2793
|
+
referenceSize: spec2.referenceSize,
|
|
2794
|
+
evaluate: () => ({ camera: spec2.camera, chain: surface.chain })
|
|
2795
|
+
}, bakeScale);
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
|
|
2799
|
+
// ../execution/animate/src/scene/v2/videoBinding.tsx
|
|
2800
|
+
import React23, { useCallback as useCallback2, useLayoutEffect as useLayoutEffect9, useRef as useRef6, useState as useState5 } from "react";
|
|
2801
|
+
import { flushSync } from "react-dom";
|
|
2802
|
+
import { useThree as useThree6 } from "@react-three/fiber";
|
|
2803
|
+
import { Video as Video2 } from "@remotion/media";
|
|
2804
|
+
import { Sequence, cancelRender as cancelRender5, continueRender as continueRender5, delayRender as delayRender5, useCurrentFrame as useCurrentFrame16 } from "remotion";
|
|
2805
|
+
import { CanvasTexture as CanvasTexture3, LinearFilter as LinearFilter2, LinearMipmapLinearFilter as LinearMipmapLinearFilter2, SRGBColorSpace as SRGBColorSpace6 } from "three";
|
|
2806
|
+
var VIDEO_ERROR = "__cueframe_component_error_v2__:scene_video_runtime_error:";
|
|
2807
|
+
function sceneHasVideoTextureV1(scene, texture) {
|
|
2808
|
+
let attached = false;
|
|
2809
|
+
scene.traverse((object) => {
|
|
2810
|
+
const material = object.material;
|
|
2811
|
+
const rows = Array.isArray(material) ? material : [material];
|
|
2812
|
+
if (rows.some((row) => row?.map === texture)) attached = true;
|
|
2813
|
+
});
|
|
2814
|
+
return attached;
|
|
2815
|
+
}
|
|
2816
|
+
function decodedDimensions(image) {
|
|
2817
|
+
const value = image;
|
|
2818
|
+
const width = value.displayWidth ?? value.videoWidth ?? value.width ?? 0;
|
|
2819
|
+
const height = value.displayHeight ?? value.videoHeight ?? value.height ?? 0;
|
|
2820
|
+
if (!Number.isSafeInteger(width) || width <= 0 || !Number.isSafeInteger(height) || height <= 0) throw new Error(`${VIDEO_ERROR} decoded video frame has invalid dimensions.`);
|
|
2821
|
+
return { width, height };
|
|
2822
|
+
}
|
|
2823
|
+
function SceneVideoBindingV1({ src, schedule, contentFrame, width, height, resourceOwner = `video:${src}`, children }) {
|
|
2824
|
+
const registerActual = useSceneActualResourceRegistrarV1();
|
|
2825
|
+
const compositionFrame = useCurrentFrame16();
|
|
2826
|
+
const address = sceneVideoMidpointAddressV1(contentFrame, schedule);
|
|
2827
|
+
const expected = useRef6("");
|
|
2828
|
+
const alive = useRef6(true);
|
|
2829
|
+
const canvas = useRef6(null);
|
|
2830
|
+
const texture = useRef6(null);
|
|
2831
|
+
const releaseTextureMeasurement = useRef6(null);
|
|
2832
|
+
const accepted = useRef6(null);
|
|
2833
|
+
const revision = useRef6(0);
|
|
2834
|
+
const drawReceipt = useRef6({ request: null, revision: null });
|
|
2835
|
+
const readinessHandle = useRef6(null);
|
|
2836
|
+
const [binding, setBinding] = useState5(null);
|
|
2837
|
+
const request = `${contentFrame}:${address.sourceIndex}:${address.mediaFrame}`;
|
|
2838
|
+
expected.current = request;
|
|
2839
|
+
useLayoutEffect9(() => {
|
|
2840
|
+
alive.current = true;
|
|
2841
|
+
return () => {
|
|
2842
|
+
alive.current = false;
|
|
2843
|
+
if (readinessHandle.current !== null) continueRender5(readinessHandle.current);
|
|
2844
|
+
readinessHandle.current = null;
|
|
2845
|
+
if (texture.current) {
|
|
2846
|
+
texture.current.dispose();
|
|
2847
|
+
releaseTextureMeasurement.current?.();
|
|
2848
|
+
}
|
|
2849
|
+
releaseTextureMeasurement.current = null;
|
|
2850
|
+
texture.current = null;
|
|
2851
|
+
canvas.current = null;
|
|
2852
|
+
accepted.current = null;
|
|
2853
|
+
};
|
|
2854
|
+
}, []);
|
|
2855
|
+
const onVideoFrame = useCallback2((image) => {
|
|
2856
|
+
if (!alive.current || expected.current !== request || accepted.current === request) return;
|
|
2857
|
+
const size = decodedDimensions(image);
|
|
2858
|
+
if (size.width !== width || size.height !== height) throw new Error(`${VIDEO_ERROR} decoded dimensions ${size.width}x${size.height} differ from admitted ${width}x${height}.`);
|
|
2859
|
+
let owned = canvas.current;
|
|
2860
|
+
if (!owned) {
|
|
2861
|
+
owned = document.createElement("canvas");
|
|
2862
|
+
owned.width = size.width;
|
|
2863
|
+
owned.height = size.height;
|
|
2864
|
+
canvas.current = owned;
|
|
2865
|
+
const uploaded = new CanvasTexture3(owned);
|
|
2866
|
+
uploaded.colorSpace = SRGBColorSpace6;
|
|
2867
|
+
uploaded.minFilter = LinearMipmapLinearFilter2;
|
|
2868
|
+
uploaded.magFilter = LinearFilter2;
|
|
2869
|
+
uploaded.generateMipmaps = true;
|
|
2870
|
+
releaseTextureMeasurement.current = registerActual(uploaded, [
|
|
2871
|
+
{ owner: resourceOwner, name: "owned-video-canvas", domain: "cpu", bytes: size.width * size.height * 4, width: size.width, height: size.height, byteLength: size.width * size.height * 4 },
|
|
2872
|
+
{ owner: resourceOwner, name: "surface-texture", domain: "gl", bytes: sceneTextureBytes({ width: size.width, height: size.height, format: "rgba8", mipLevels: sceneFullMipLevels(size.width, size.height) }), width: size.width, height: size.height }
|
|
2873
|
+
]);
|
|
2874
|
+
texture.current = uploaded;
|
|
2875
|
+
} else if (owned.width !== size.width || owned.height !== size.height) {
|
|
2876
|
+
throw new Error(`${VIDEO_ERROR} decoded dimensions changed after admission.`);
|
|
2877
|
+
}
|
|
2878
|
+
const context = owned.getContext("2d", { alpha: true });
|
|
2879
|
+
context.clearRect(0, 0, size.width, size.height);
|
|
2880
|
+
context.drawImage(image, 0, 0, size.width, size.height);
|
|
2881
|
+
accepted.current = request;
|
|
2882
|
+
revision.current += 1;
|
|
2883
|
+
drawReceipt.current = { request: null, revision: null };
|
|
2884
|
+
if (readinessHandle.current !== null) continueRender5(readinessHandle.current);
|
|
2885
|
+
readinessHandle.current = delayRender5(`Commit video texture ${request}`, { timeoutInMilliseconds: 12e4 });
|
|
2886
|
+
const handle = readinessHandle.current;
|
|
2887
|
+
const next = { kind: "video-texture", texture: texture.current, visual: { kind: "texture", texture: texture.current, readiness: "committed" }, sourceIndex: address.sourceIndex, revision: revision.current, request, drawReceipt: drawReceipt.current, readinessHandle: handle, releaseReadiness: () => {
|
|
2888
|
+
if (readinessHandle.current !== handle) return;
|
|
2889
|
+
readinessHandle.current = null;
|
|
2890
|
+
continueRender5(handle);
|
|
2891
|
+
} };
|
|
2892
|
+
flushSync(() => setBinding(next));
|
|
2893
|
+
}, [address.sourceIndex, height, request, resourceOwner, width, registerActual]);
|
|
2894
|
+
const handleError = useCallback2((error) => {
|
|
2895
|
+
cancelRender5(error);
|
|
2896
|
+
return "fail";
|
|
2897
|
+
}, []);
|
|
2898
|
+
return /* @__PURE__ */ React23.createElement(React23.Fragment, null, children(binding), /* @__PURE__ */ React23.createElement(Sequence, { from: compositionFrame - address.mediaFrame, layout: "none" }, /* @__PURE__ */ React23.createElement(
|
|
2899
|
+
Video2,
|
|
2900
|
+
{
|
|
2901
|
+
src,
|
|
2902
|
+
muted: true,
|
|
2903
|
+
headless: true,
|
|
2904
|
+
showInTimeline: false,
|
|
2905
|
+
disallowFallbackToOffthreadVideo: true,
|
|
2906
|
+
playbackRate: address.playbackRate,
|
|
2907
|
+
onVideoFrame,
|
|
2908
|
+
onError: handleError,
|
|
2909
|
+
delayRenderTimeoutInMilliseconds: 12e4
|
|
2910
|
+
}
|
|
2911
|
+
)));
|
|
2912
|
+
}
|
|
2913
|
+
function SceneVideoTextureCommitV1({ binding }) {
|
|
2914
|
+
const { advance, scene } = useThree6((state) => ({ advance: state.advance, scene: state.scene }));
|
|
2915
|
+
useLayoutEffect9(() => {
|
|
2916
|
+
if (!sceneHasVideoTextureV1(scene, binding.texture)) throw new Error(`${VIDEO_ERROR} matching texture was not attached to a material before readiness.`);
|
|
2917
|
+
binding.texture.needsUpdate = true;
|
|
2918
|
+
advance(performance.now());
|
|
2919
|
+
binding.drawReceipt.request = binding.request;
|
|
2920
|
+
binding.drawReceipt.revision = binding.revision;
|
|
2921
|
+
binding.releaseReadiness();
|
|
2922
|
+
}, [advance, binding, scene]);
|
|
2923
|
+
return null;
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2926
|
+
// ../execution/animate/src/scene/v2/SceneShotV2.tsx
|
|
2927
|
+
import React26, { useLayoutEffect as useLayoutEffect11 } from "react";
|
|
2928
|
+
import { useThree as useThree8 } from "@react-three/fiber";
|
|
2929
|
+
import { getRemotionEnvironment as getRemotionEnvironment2, Internals as Internals3 } from "remotion";
|
|
2930
|
+
|
|
2931
|
+
// ../execution/animate/src/scene/assets.ts
|
|
2932
|
+
function sceneImageHandle(assets, ref) {
|
|
2933
|
+
const binding = assets[ref.slot];
|
|
2934
|
+
const handle = binding && typeof binding === "object" ? binding : null;
|
|
2935
|
+
const kind = handle?.kind;
|
|
2936
|
+
if (!handle || typeof handle.handle !== "string" || handle.handle.length === 0 || kind !== void 0 && kind !== "image") {
|
|
2937
|
+
throw new SceneShotError(
|
|
2938
|
+
"scene_asset_unbound",
|
|
2939
|
+
`${ref.what} slot "${ref.slot}" of layer "${ref.layerId}" is not bound to an admitted image asset`,
|
|
2940
|
+
`${ref.layerPath ?? `layers.${ref.layerIndex}`}.${ref.field}`
|
|
2941
|
+
);
|
|
2942
|
+
}
|
|
2943
|
+
return handle.handle;
|
|
2944
|
+
}
|
|
2945
|
+
|
|
2946
|
+
// ../execution/animate/src/scene/finishing.tsx
|
|
2947
|
+
import React24 from "react";
|
|
2948
|
+
|
|
2949
|
+
// ../execution/animate/src/scene/finishingMath.ts
|
|
2950
|
+
var VIGNETTE_CORE_INSET = 0.15;
|
|
2951
|
+
var VIGNETTE_SIGMA = 0.16;
|
|
2952
|
+
function vignetteGeometry(size) {
|
|
2953
|
+
return {
|
|
2954
|
+
x0: size.width * VIGNETTE_CORE_INSET,
|
|
2955
|
+
y0: size.height * VIGNETTE_CORE_INSET,
|
|
2956
|
+
x1: size.width * (1 - VIGNETTE_CORE_INSET),
|
|
2957
|
+
y1: size.height * (1 - VIGNETTE_CORE_INSET),
|
|
2958
|
+
sigmaX: size.width * VIGNETTE_SIGMA,
|
|
2959
|
+
sigmaY: size.height * VIGNETTE_SIGMA
|
|
2960
|
+
};
|
|
2961
|
+
}
|
|
2962
|
+
|
|
2963
|
+
// ../execution/animate/src/scene/grainNoise.ts
|
|
2964
|
+
var GRAIN_LATTICE = 256;
|
|
2965
|
+
var GRAIN_CHANNELS = 4;
|
|
2966
|
+
var GRAIN_OCTAVES = 2;
|
|
2967
|
+
var GRAIN_GREY_COEFFICIENT = 0.3333;
|
|
2968
|
+
var GRAIN_SAMPLE_OFFSET = 1;
|
|
2969
|
+
var RAND_M = 2147483647;
|
|
2970
|
+
var RAND_A = 16807;
|
|
2971
|
+
var RAND_Q = 127773;
|
|
2972
|
+
var RAND_R = 2836;
|
|
2973
|
+
function grainSetupSeed(seed) {
|
|
2974
|
+
let s = Math.round(Math.fround(seed));
|
|
2975
|
+
if (s <= 0) s = -(s % (RAND_M - 1)) + 1;
|
|
2976
|
+
if (s > RAND_M - 1) s = RAND_M - 1;
|
|
2977
|
+
return s;
|
|
2978
|
+
}
|
|
2979
|
+
function grainNextRandom(seed) {
|
|
2980
|
+
const r = RAND_A * (seed % RAND_Q) - RAND_R * Math.floor(seed / RAND_Q);
|
|
2981
|
+
return r <= 0 ? r + RAND_M : r;
|
|
2982
|
+
}
|
|
2983
|
+
function grainLattice(seed) {
|
|
2984
|
+
let s = grainSetupSeed(seed);
|
|
2985
|
+
const selector = new Int32Array(GRAIN_LATTICE + GRAIN_LATTICE + 2);
|
|
2986
|
+
const gradient = Array.from({ length: GRAIN_CHANNELS }, () => new Float64Array((GRAIN_LATTICE + GRAIN_LATTICE + 2) * 2));
|
|
2987
|
+
for (let k = 0; k < GRAIN_CHANNELS; k++) {
|
|
2988
|
+
const g = gradient[k];
|
|
2989
|
+
for (let i = 0; i < GRAIN_LATTICE; i++) {
|
|
2990
|
+
selector[i] = i;
|
|
2991
|
+
for (let j = 0; j < 2; j++) {
|
|
2992
|
+
s = grainNextRandom(s);
|
|
2993
|
+
g[i * 2 + j] = (s % (GRAIN_LATTICE + GRAIN_LATTICE) - GRAIN_LATTICE) / GRAIN_LATTICE;
|
|
2994
|
+
}
|
|
2995
|
+
const gx = g[i * 2], gy = g[i * 2 + 1];
|
|
2996
|
+
const length = Math.sqrt(gx * gx + gy * gy);
|
|
2997
|
+
g[i * 2] = gx / length;
|
|
2998
|
+
g[i * 2 + 1] = gy / length;
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
for (let i = GRAIN_LATTICE - 1; i > 0; i--) {
|
|
3002
|
+
const k = selector[i];
|
|
3003
|
+
s = grainNextRandom(s);
|
|
3004
|
+
const j = s % GRAIN_LATTICE;
|
|
3005
|
+
selector[i] = selector[j];
|
|
3006
|
+
selector[j] = k;
|
|
3007
|
+
}
|
|
3008
|
+
for (let i = 0; i < GRAIN_LATTICE + 2; i++) {
|
|
3009
|
+
selector[GRAIN_LATTICE + i] = selector[i];
|
|
3010
|
+
for (let k = 0; k < GRAIN_CHANNELS; k++) {
|
|
3011
|
+
const g = gradient[k];
|
|
3012
|
+
g[(GRAIN_LATTICE + i) * 2] = g[i * 2];
|
|
3013
|
+
g[(GRAIN_LATTICE + i) * 2 + 1] = g[i * 2 + 1];
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
return { selector, gradient };
|
|
3017
|
+
}
|
|
3018
|
+
function fitFrequency(frequency, tile) {
|
|
3019
|
+
if (frequency === 0) return frequency;
|
|
3020
|
+
const lo = Math.floor(tile * frequency) / tile;
|
|
3021
|
+
const hi = Math.ceil(tile * frequency) / tile;
|
|
3022
|
+
return frequency / lo < hi / frequency ? lo : hi;
|
|
3023
|
+
}
|
|
3024
|
+
function grainStitch(frequency, tileWidth, tileHeight) {
|
|
3025
|
+
const baseX = fitFrequency(frequency, tileWidth);
|
|
3026
|
+
const baseY = fitFrequency(frequency, tileHeight);
|
|
3027
|
+
const width = Math.floor(tileWidth * baseX + 0.5);
|
|
3028
|
+
const height = Math.floor(tileHeight * baseY + 0.5);
|
|
3029
|
+
return { baseX, baseY, width, height, wrapX: width, wrapY: height };
|
|
3030
|
+
}
|
|
3031
|
+
var GRAIN_TABLE_WIDTH = GRAIN_LATTICE + GRAIN_LATTICE + 2;
|
|
3032
|
+
var GRAIN_TABLE_HEIGHT = 3;
|
|
3033
|
+
function grainLatticeTable(seed) {
|
|
3034
|
+
const lattice = grainLattice(seed);
|
|
3035
|
+
const table = new Float32Array(GRAIN_TABLE_WIDTH * GRAIN_TABLE_HEIGHT * 4);
|
|
3036
|
+
for (let i = 0; i < GRAIN_TABLE_WIDTH; i++) {
|
|
3037
|
+
table[i * 4] = lattice.selector[i];
|
|
3038
|
+
}
|
|
3039
|
+
const row = GRAIN_TABLE_WIDTH * 4;
|
|
3040
|
+
for (let i = 0; i < GRAIN_TABLE_WIDTH; i++) {
|
|
3041
|
+
table[row + i * 4] = lattice.gradient[0][i * 2];
|
|
3042
|
+
table[row + i * 4 + 1] = lattice.gradient[0][i * 2 + 1];
|
|
3043
|
+
table[row + i * 4 + 2] = lattice.gradient[1][i * 2];
|
|
3044
|
+
table[row + i * 4 + 3] = lattice.gradient[1][i * 2 + 1];
|
|
3045
|
+
table[row * 2 + i * 4] = lattice.gradient[2][i * 2];
|
|
3046
|
+
table[row * 2 + i * 4 + 1] = lattice.gradient[2][i * 2 + 1];
|
|
3047
|
+
}
|
|
3048
|
+
return table;
|
|
3049
|
+
}
|
|
3050
|
+
|
|
3051
|
+
// ../execution/animate/src/scene/finishing.tsx
|
|
3052
|
+
function hashSeed(seed) {
|
|
3053
|
+
let hash = 2166136261;
|
|
3054
|
+
for (let i = 0; i < seed.length; i++) {
|
|
3055
|
+
hash ^= seed.charCodeAt(i);
|
|
3056
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
3057
|
+
}
|
|
3058
|
+
return hash >>> 0;
|
|
3059
|
+
}
|
|
3060
|
+
function grainSeed(seed, frame) {
|
|
3061
|
+
return hashSeed(`${seed}#${frame}`) % 2147483647;
|
|
3062
|
+
}
|
|
3063
|
+
function postFilterId(seed) {
|
|
3064
|
+
return `cf-scene-post-${hashSeed(seed).toString(16).padStart(8, "0")}`;
|
|
3065
|
+
}
|
|
3066
|
+
function postFilterStages(post) {
|
|
3067
|
+
const stages = [];
|
|
3068
|
+
if (post.grain > 0) stages.push("grain");
|
|
3069
|
+
if (post.vignette > 0) stages.push("vignette");
|
|
3070
|
+
return stages;
|
|
3071
|
+
}
|
|
3072
|
+
function postFilterStyle(id, post) {
|
|
3073
|
+
return postFilterStages(post).length ? { filter: `url(#${id})` } : {};
|
|
3074
|
+
}
|
|
3075
|
+
var GRAIN_BASE_FREQUENCY = 0.85;
|
|
3076
|
+
function grainFrequency(scale) {
|
|
3077
|
+
return GRAIN_BASE_FREQUENCY / scale;
|
|
3078
|
+
}
|
|
3079
|
+
var GREY = "0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 0 1";
|
|
3080
|
+
var OPAQUE = "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1";
|
|
3081
|
+
function PostFilter({ id, post, seed, frame, size, scale }) {
|
|
3082
|
+
const stages = postFilterStages(post);
|
|
3083
|
+
if (stages.length === 0) return null;
|
|
3084
|
+
const primitives = [
|
|
3085
|
+
/* @__PURE__ */ React24.createElement("feColorMatrix", { key: "opaque", in: "SourceGraphic", type: "matrix", values: OPAQUE, result: "cfOpaque" })
|
|
3086
|
+
];
|
|
3087
|
+
let input = "cfOpaque";
|
|
3088
|
+
if (stages.includes("grain")) {
|
|
3089
|
+
const g = post.grain;
|
|
3090
|
+
primitives.push(
|
|
3091
|
+
/* @__PURE__ */ React24.createElement("feTurbulence", { key: "noise", type: "fractalNoise", baseFrequency: grainFrequency(scale), numOctaves: GRAIN_OCTAVES, seed: grainSeed(seed, frame), stitchTiles: "stitch", result: "cfNoise" }),
|
|
3092
|
+
/* @__PURE__ */ React24.createElement("feColorMatrix", { key: "grey", in: "cfNoise", type: "matrix", values: GREY, result: "cfGrey" }),
|
|
3093
|
+
/* @__PURE__ */ React24.createElement("feComponentTransfer", { key: "level", in: "cfGrey", result: "cfGrain" }, /* @__PURE__ */ React24.createElement("feFuncR", { type: "linear", slope: g, intercept: (1 - g) / 2 }), /* @__PURE__ */ React24.createElement("feFuncG", { type: "linear", slope: g, intercept: (1 - g) / 2 }), /* @__PURE__ */ React24.createElement("feFuncB", { type: "linear", slope: g, intercept: (1 - g) / 2 })),
|
|
3094
|
+
/* @__PURE__ */ React24.createElement("feBlend", { key: "grainBlend", mode: "overlay", in: "cfGrain", in2: input, result: "cfGrained" })
|
|
3095
|
+
);
|
|
3096
|
+
input = "cfGrained";
|
|
3097
|
+
}
|
|
3098
|
+
if (stages.includes("vignette")) {
|
|
3099
|
+
const v = post.vignette;
|
|
3100
|
+
const { width, height } = size;
|
|
3101
|
+
const g = vignetteGeometry(size);
|
|
3102
|
+
primitives.push(
|
|
3103
|
+
/* @__PURE__ */ React24.createElement("feFlood", { key: "core", floodColor: "#ffffff", x: g.x0, y: g.y0, width: g.x1 - g.x0, height: g.y1 - g.y0, result: "cfCore" }),
|
|
3104
|
+
/* @__PURE__ */ React24.createElement("feGaussianBlur", { key: "soft", in: "cfCore", stdDeviation: `${g.sigmaX} ${g.sigmaY}`, x: 0, y: 0, width, height, result: "cfSoft" }),
|
|
3105
|
+
/* @__PURE__ */ React24.createElement("feColorMatrix", { key: "factor", in: "cfSoft", type: "matrix", values: `0 0 0 ${v} ${1 - v} 0 0 0 ${v} ${1 - v} 0 0 0 ${v} ${1 - v} 0 0 0 0 1`, x: 0, y: 0, width, height, result: "cfFactor" }),
|
|
3106
|
+
/* @__PURE__ */ React24.createElement("feBlend", { key: "vignetteBlend", mode: "multiply", in: "cfFactor", in2: input, result: "cfDarkened" })
|
|
3107
|
+
);
|
|
3108
|
+
input = "cfDarkened";
|
|
3109
|
+
}
|
|
3110
|
+
primitives.push(/* @__PURE__ */ React24.createElement("feComposite", { key: "alpha", in: input, in2: "SourceGraphic", operator: "in" }));
|
|
3111
|
+
return /* @__PURE__ */ React24.createElement("svg", { "aria-hidden": "true", style: { position: "absolute", width: 0, height: 0, overflow: "hidden" } }, /* @__PURE__ */ React24.createElement("filter", { id, x: "0", y: "0", width: "100%", height: "100%", colorInterpolationFilters: "sRGB" }, primitives));
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
// ../execution/animate/src/scene/finishingPass.ts
|
|
3115
|
+
function sceneFinishingUniforms(post, seed, frame, size, scale) {
|
|
3116
|
+
const stages = postFilterStages(post);
|
|
3117
|
+
const grain = stages.includes("grain") ? post.grain : 0;
|
|
3118
|
+
const vignette = stages.includes("vignette") ? post.vignette : 0;
|
|
3119
|
+
const noiseSeed = grainSeed(seed, frame);
|
|
3120
|
+
const stitch = grainStitch(grainFrequency(scale), size.width, size.height);
|
|
3121
|
+
const g = vignetteGeometry(size);
|
|
3122
|
+
return {
|
|
3123
|
+
grain,
|
|
3124
|
+
vignette,
|
|
3125
|
+
frame: [size.width, size.height],
|
|
3126
|
+
seed: noiseSeed,
|
|
3127
|
+
grainBase: [stitch.baseX, stitch.baseY],
|
|
3128
|
+
grainStitch: [stitch.width, stitch.height, stitch.wrapX, stitch.wrapY],
|
|
3129
|
+
vignetteCore: [g.x0, g.y0, g.x1, g.y1],
|
|
3130
|
+
vignetteSigma: [g.sigmaX, g.sigmaY],
|
|
3131
|
+
lattice: grain > 0 ? grainLatticeTable(noiseSeed) : null
|
|
3132
|
+
};
|
|
3133
|
+
}
|
|
3134
|
+
|
|
3135
|
+
// ../execution/animate/src/scene/FocusPass.tsx
|
|
3136
|
+
import { useLayoutEffect as useLayoutEffect10, useState as useState6 } from "react";
|
|
3137
|
+
import { useFrame, useThree as useThree7 } from "@react-three/fiber";
|
|
3138
|
+
|
|
3139
|
+
// ../execution/animate/src/scene/focusBlur.ts
|
|
3140
|
+
var FOCUS_TAPS = 8;
|
|
3141
|
+
var FOCUS_OFF = { distance: 1, range: 1, maxBlur: 0 };
|
|
3142
|
+
function focusUniforms(focus, scale, camera, frame) {
|
|
3143
|
+
const authored = focus ?? FOCUS_OFF;
|
|
3144
|
+
return {
|
|
3145
|
+
distance: authored.distance * scale,
|
|
3146
|
+
range: authored.range * scale,
|
|
3147
|
+
maxBlur: authored.maxBlur * scale,
|
|
3148
|
+
near: camera.near,
|
|
3149
|
+
far: camera.far,
|
|
3150
|
+
texel: [1 / frame.width, 1 / frame.height]
|
|
3151
|
+
};
|
|
3152
|
+
}
|
|
3153
|
+
|
|
3154
|
+
// ../execution/animate/src/scene/focusResources.ts
|
|
3155
|
+
import {
|
|
3156
|
+
ClampToEdgeWrapping,
|
|
3157
|
+
DataTexture,
|
|
3158
|
+
DepthFormat,
|
|
3159
|
+
DepthTexture,
|
|
3160
|
+
FloatType,
|
|
3161
|
+
HalfFloatType,
|
|
3162
|
+
LinearFilter as LinearFilter3,
|
|
3163
|
+
NearestFilter,
|
|
3164
|
+
NoBlending,
|
|
3165
|
+
OrthographicCamera,
|
|
3166
|
+
PlaneGeometry,
|
|
3167
|
+
RGBAFormat,
|
|
3168
|
+
Scene,
|
|
3169
|
+
ShaderMaterial,
|
|
3170
|
+
UnsignedIntType,
|
|
3171
|
+
Mesh,
|
|
3172
|
+
Vector2,
|
|
3173
|
+
Vector4,
|
|
3174
|
+
WebGLRenderTarget
|
|
3175
|
+
} from "three";
|
|
3176
|
+
|
|
3177
|
+
// ../execution/animate/src/scene/focusShaders.ts
|
|
3178
|
+
var FOCUS_VERTEX_SHADER = (
|
|
3179
|
+
/* glsl */
|
|
3180
|
+
`
|
|
3181
|
+
varying vec2 vUv;
|
|
3182
|
+
void main() {
|
|
3183
|
+
vUv = uv;
|
|
3184
|
+
gl_Position = vec4(position.xy, 0.0, 1.0);
|
|
3185
|
+
}
|
|
3186
|
+
`
|
|
3187
|
+
);
|
|
3188
|
+
var FOCUS_GATHER_CHUNK = (
|
|
3189
|
+
/* glsl */
|
|
3190
|
+
`
|
|
3191
|
+
uniform sampler2D tColor;
|
|
3192
|
+
uniform sampler2D tDepth;
|
|
3193
|
+
uniform vec2 uTexel;
|
|
3194
|
+
uniform vec2 uDirection;
|
|
3195
|
+
uniform float uNear;
|
|
3196
|
+
uniform float uFar;
|
|
3197
|
+
uniform float uFocusDistance;
|
|
3198
|
+
uniform float uFocusRange;
|
|
3199
|
+
uniform float uMaxBlur;
|
|
3200
|
+
varying vec2 vUv;
|
|
3201
|
+
|
|
3202
|
+
float focusViewDistance(vec2 uv) {
|
|
3203
|
+
float depth = texture2D(tDepth, uv).x;
|
|
3204
|
+
return -((uNear * uFar) / ((uFar - uNear) * depth - uFar));
|
|
3205
|
+
}
|
|
3206
|
+
|
|
3207
|
+
float focusCircleOfConfusion(float distance) {
|
|
3208
|
+
return min(1.0, abs(distance - uFocusDistance) / uFocusRange) * uMaxBlur;
|
|
3209
|
+
}
|
|
3210
|
+
|
|
3211
|
+
void focusTap(vec2 offset, float radius, float weight, float centreDistance, inout vec4 sum, inout float total) {
|
|
3212
|
+
vec2 uv = vUv + offset;
|
|
3213
|
+
float tapDistance = focusViewDistance(uv);
|
|
3214
|
+
float allow = tapDistance < centreDistance ? step(radius, focusCircleOfConfusion(tapDistance)) : 1.0;
|
|
3215
|
+
float w = weight * allow;
|
|
3216
|
+
sum += texture2D(tColor, uv) * w;
|
|
3217
|
+
total += w;
|
|
3218
|
+
}
|
|
3219
|
+
|
|
3220
|
+
vec4 focusGather() {
|
|
3221
|
+
float centreDistance = focusViewDistance(vUv);
|
|
3222
|
+
float centreRadius = focusCircleOfConfusion(centreDistance);
|
|
3223
|
+
vec4 sum = texture2D(tColor, vUv);
|
|
3224
|
+
float total = 1.0;
|
|
3225
|
+
for (int i = 1; i <= FOCUS_TAPS; i++) {
|
|
3226
|
+
float t = float(i) / float(FOCUS_TAPS);
|
|
3227
|
+
float weight = exp(-2.0 * t * t);
|
|
3228
|
+
float radius = t * centreRadius;
|
|
3229
|
+
vec2 offset = uDirection * uTexel * radius;
|
|
3230
|
+
focusTap(offset, radius, weight, centreDistance, sum, total);
|
|
3231
|
+
focusTap(-offset, radius, weight, centreDistance, sum, total);
|
|
3232
|
+
}
|
|
3233
|
+
return sum / total;
|
|
3234
|
+
}
|
|
3235
|
+
`
|
|
3236
|
+
);
|
|
3237
|
+
var FOCUS_BLUR_FRAGMENT_SHADER = `${FOCUS_GATHER_CHUNK}
|
|
3238
|
+
void main() {
|
|
3239
|
+
gl_FragColor = focusGather();
|
|
3240
|
+
}
|
|
3241
|
+
`;
|
|
3242
|
+
var FOCUS_FINISHING_CHUNK = (
|
|
3243
|
+
/* glsl */
|
|
3244
|
+
`
|
|
3245
|
+
uniform float uGrain;
|
|
3246
|
+
uniform float uVignette;
|
|
3247
|
+
uniform vec2 uFrameSize;
|
|
3248
|
+
/** The stitched base frequency, per axis: cycles per output pixel. */
|
|
3249
|
+
uniform vec2 uGrainBase;
|
|
3250
|
+
/** The stitch: lattice period in x and y, then the wrap point in x and y. */
|
|
3251
|
+
uniform vec4 uGrainStitch;
|
|
3252
|
+
/** The vignette core rectangle: left, top, right, bottom, in frame pixels. */
|
|
3253
|
+
uniform vec4 uVignetteCore;
|
|
3254
|
+
uniform vec2 uVignetteSigma;
|
|
3255
|
+
uniform sampler2D tGrainLattice;
|
|
3256
|
+
|
|
3257
|
+
const float SCENE_SQRT2 = 1.4142135623730951;
|
|
3258
|
+
|
|
3259
|
+
/** Abramowitz\u2013Stegun 7.1.26, the series finishingMath.ts evaluates, sign and all. */
|
|
3260
|
+
float sceneErf(float x) {
|
|
3261
|
+
float s = sign(x);
|
|
3262
|
+
float a = abs(x);
|
|
3263
|
+
float t = 1.0 / (1.0 + 0.3275911 * a);
|
|
3264
|
+
float y = 1.0 - (((((1.061405429 * t - 1.453152027) * t) + 1.421413741) * t - 0.284496736) * t + 0.254829592) * t * exp(-a * a);
|
|
3265
|
+
return s * y;
|
|
3266
|
+
}
|
|
3267
|
+
|
|
3268
|
+
float sceneBlurredCoverage(float a, float b, float sigma, float p) {
|
|
3269
|
+
return 0.5 * (sceneErf((b - p) / (sigma * SCENE_SQRT2)) - sceneErf((a - p) / (sigma * SCENE_SQRT2)));
|
|
3270
|
+
}
|
|
3271
|
+
|
|
3272
|
+
float sceneVignetteFactor(vec2 point) {
|
|
3273
|
+
float coverage = sceneBlurredCoverage(uVignetteCore.x, uVignetteCore.z, uVignetteSigma.x, point.x)
|
|
3274
|
+
* sceneBlurredCoverage(uVignetteCore.y, uVignetteCore.w, uVignetteSigma.y, point.y);
|
|
3275
|
+
return uVignette * coverage + (1.0 - uVignette);
|
|
3276
|
+
}
|
|
3277
|
+
|
|
3278
|
+
float sceneGrainSelector(float index) {
|
|
3279
|
+
return texture2D(tGrainLattice, vec2((index + 0.5) / float(GRAIN_TABLE_WIDTH), 0.5 / float(GRAIN_TABLE_HEIGHT))).r;
|
|
3280
|
+
}
|
|
3281
|
+
|
|
3282
|
+
/** One lattice corner's gradient dotted with (rx, ry), for the three channels the grey averages. */
|
|
3283
|
+
vec3 sceneGrainCorner(float index, float rx, float ry) {
|
|
3284
|
+
vec4 ab = texture2D(tGrainLattice, vec2((index + 0.5) / float(GRAIN_TABLE_WIDTH), 1.5 / float(GRAIN_TABLE_HEIGHT)));
|
|
3285
|
+
vec2 c = texture2D(tGrainLattice, vec2((index + 0.5) / float(GRAIN_TABLE_WIDTH), 2.5 / float(GRAIN_TABLE_HEIGHT))).rg;
|
|
3286
|
+
return vec3(rx * ab.x + ry * ab.y, rx * ab.z + ry * ab.w, rx * c.x + ry * c.y);
|
|
3287
|
+
}
|
|
3288
|
+
|
|
3289
|
+
/** The spec's noise2 for three channels at once, with the stitch wrap already folded. */
|
|
3290
|
+
vec3 sceneGrainNoise(vec2 v, vec4 stitch) {
|
|
3291
|
+
float bx0 = floor(v.x), bx1 = bx0 + 1.0;
|
|
3292
|
+
float rx0 = v.x - bx0, rx1 = rx0 - 1.0;
|
|
3293
|
+
float by0 = floor(v.y), by1 = by0 + 1.0;
|
|
3294
|
+
float ry0 = v.y - by0, ry1 = ry0 - 1.0;
|
|
3295
|
+
if (bx0 >= stitch.z) bx0 -= stitch.x;
|
|
3296
|
+
if (bx1 >= stitch.z) bx1 -= stitch.x;
|
|
3297
|
+
if (by0 >= stitch.w) by0 -= stitch.y;
|
|
3298
|
+
if (by1 >= stitch.w) by1 -= stitch.y;
|
|
3299
|
+
bx0 = mod(bx0, float(GRAIN_LATTICE));
|
|
3300
|
+
bx1 = mod(bx1, float(GRAIN_LATTICE));
|
|
3301
|
+
by0 = mod(by0, float(GRAIN_LATTICE));
|
|
3302
|
+
by1 = mod(by1, float(GRAIN_LATTICE));
|
|
3303
|
+
float i = sceneGrainSelector(bx0);
|
|
3304
|
+
float j = sceneGrainSelector(bx1);
|
|
3305
|
+
float sx = rx0 * rx0 * (3.0 - 2.0 * rx0);
|
|
3306
|
+
float sy = ry0 * ry0 * (3.0 - 2.0 * ry0);
|
|
3307
|
+
vec3 a = mix(sceneGrainCorner(sceneGrainSelector(i + by0), rx0, ry0), sceneGrainCorner(sceneGrainSelector(j + by0), rx1, ry0), sx);
|
|
3308
|
+
vec3 b = mix(sceneGrainCorner(sceneGrainSelector(i + by1), rx0, ry1), sceneGrainCorner(sceneGrainSelector(j + by1), rx1, ry1), sx);
|
|
3309
|
+
return mix(a, b, sy);
|
|
3310
|
+
}
|
|
3311
|
+
|
|
3312
|
+
/** type="fractalNoise" over two octaves, greyed by the filter's own 0.3333 coefficient. */
|
|
3313
|
+
float sceneGrainField(vec2 point) {
|
|
3314
|
+
vec2 v = point * uGrainBase;
|
|
3315
|
+
vec4 stitch = uGrainStitch;
|
|
3316
|
+
vec3 sum = vec3(0.0);
|
|
3317
|
+
float ratio = 1.0;
|
|
3318
|
+
for (int octave = 0; octave < GRAIN_OCTAVES; octave++) {
|
|
3319
|
+
sum += sceneGrainNoise(v, stitch) / ratio;
|
|
3320
|
+
v *= 2.0;
|
|
3321
|
+
ratio *= 2.0;
|
|
3322
|
+
stitch *= 2.0;
|
|
3323
|
+
}
|
|
3324
|
+
vec3 fractal = (sum + 1.0) * 0.5;
|
|
3325
|
+
return clamp((fractal.x + fractal.y + fractal.z) * GRAIN_GREY_COEFFICIENT, 0.0, 1.0);
|
|
3326
|
+
}
|
|
3327
|
+
|
|
3328
|
+
/** feBlend mode="overlay": the CSS blend formula, switching on the backdrop. */
|
|
3329
|
+
vec3 sceneOverlay(vec3 backdrop, float source) {
|
|
3330
|
+
vec3 lo = 2.0 * backdrop * source;
|
|
3331
|
+
vec3 hi = 1.0 - 2.0 * (1.0 - backdrop) * (1.0 - source);
|
|
3332
|
+
return mix(hi, lo, step(backdrop, vec3(0.5)));
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3335
|
+
vec3 sceneFinishing(vec3 color) {
|
|
3336
|
+
if (uGrain <= 0.0 && uVignette <= 0.0) return color;
|
|
3337
|
+
// The pixel's top-left corner in the frame's own pixels, y down: the space both halves share.
|
|
3338
|
+
vec2 pixel = vec2(gl_FragCoord.x - 0.5, uFrameSize.y - gl_FragCoord.y - 0.5);
|
|
3339
|
+
vec3 finished = clamp(color, 0.0, 1.0);
|
|
3340
|
+
if (uGrain > 0.0) {
|
|
3341
|
+
float level = uGrain * sceneGrainField(pixel + float(GRAIN_SAMPLE_OFFSET)) + (1.0 - uGrain) * 0.5;
|
|
3342
|
+
finished = sceneOverlay(finished, level);
|
|
3343
|
+
}
|
|
3344
|
+
if (uVignette > 0.0) {
|
|
3345
|
+
finished *= sceneVignetteFactor(pixel + 0.5);
|
|
3346
|
+
}
|
|
3347
|
+
return finished;
|
|
3348
|
+
}
|
|
3349
|
+
`
|
|
3350
|
+
);
|
|
3351
|
+
var FOCUS_COMPOSITE_FRAGMENT_SHADER = `${FOCUS_GATHER_CHUNK}
|
|
3352
|
+
${FOCUS_FINISHING_CHUNK}
|
|
3353
|
+
void main() {
|
|
3354
|
+
vec4 gathered = focusGather();
|
|
3355
|
+
float coverage = gathered.a;
|
|
3356
|
+
gl_FragColor = vec4(coverage > 0.0 ? gathered.rgb / coverage : gathered.rgb, coverage);
|
|
3357
|
+
#include <colorspace_fragment>
|
|
3358
|
+
gl_FragColor.rgb = sceneFinishing(gl_FragColor.rgb);
|
|
3359
|
+
gl_FragColor.rgb *= coverage;
|
|
3360
|
+
}
|
|
3361
|
+
`;
|
|
3362
|
+
|
|
3363
|
+
// ../execution/animate/src/scene/focusResources.ts
|
|
3364
|
+
var HALF_FLOAT_TARGET_EXTENSIONS = ["EXT_color_buffer_half_float", "EXT_color_buffer_float"];
|
|
3365
|
+
var FOCUS_SPEC_PATH = "post";
|
|
3366
|
+
function assertHalfFloatColorTargets(gl, path) {
|
|
3367
|
+
if (HALF_FLOAT_TARGET_EXTENSIONS.some((name) => gl.extensions.has(name))) return;
|
|
3368
|
+
throw new SceneShotError(
|
|
3369
|
+
"scene_render_target_unsupported",
|
|
3370
|
+
`the world pass renders through half-float colour targets, which this renderer cannot allocate: neither ${HALF_FLOAT_TARGET_EXTENSIONS.join(" nor ")} is available`,
|
|
3371
|
+
path
|
|
3372
|
+
);
|
|
3373
|
+
}
|
|
3374
|
+
function canvasSampleCount(gl, path) {
|
|
3375
|
+
if (gl.getRenderTarget() !== null) {
|
|
3376
|
+
throw new SceneShotError(
|
|
3377
|
+
"scene_internal",
|
|
3378
|
+
"the world pass reads its multisample count from the canvas, but a render target was bound when it was constructed",
|
|
3379
|
+
path
|
|
3380
|
+
);
|
|
3381
|
+
}
|
|
3382
|
+
const context = gl.getContext();
|
|
3383
|
+
const samples = context.getParameter(context.SAMPLES);
|
|
3384
|
+
if (typeof samples !== "number" || !Number.isFinite(samples)) {
|
|
3385
|
+
throw new SceneShotError(
|
|
3386
|
+
"scene_internal",
|
|
3387
|
+
`the world pass reads its multisample count from the canvas, but this renderer reported SAMPLES as ${typeof samples === "string" ? JSON.stringify(samples) : String(samples)}`,
|
|
3388
|
+
path
|
|
3389
|
+
);
|
|
3390
|
+
}
|
|
3391
|
+
return samples > 1 ? samples : 0;
|
|
3392
|
+
}
|
|
3393
|
+
function focusUniformValues() {
|
|
3394
|
+
return {
|
|
3395
|
+
tColor: { value: null },
|
|
3396
|
+
tDepth: { value: null },
|
|
3397
|
+
uTexel: { value: new Vector2(1, 1) },
|
|
3398
|
+
uDirection: { value: new Vector2(1, 0) },
|
|
3399
|
+
uNear: { value: 1 },
|
|
3400
|
+
uFar: { value: 1 },
|
|
3401
|
+
uFocusDistance: { value: 0 },
|
|
3402
|
+
uFocusRange: { value: 1 },
|
|
3403
|
+
uMaxBlur: { value: 0 }
|
|
3404
|
+
};
|
|
3405
|
+
}
|
|
3406
|
+
function finishingUniformValues(lattice) {
|
|
3407
|
+
return {
|
|
3408
|
+
uGrain: { value: 0 },
|
|
3409
|
+
uVignette: { value: 0 },
|
|
3410
|
+
uFrameSize: { value: new Vector2(1, 1) },
|
|
3411
|
+
uGrainBase: { value: new Vector2(0, 0) },
|
|
3412
|
+
uGrainStitch: { value: new Vector4(1, 1, 1, 1) },
|
|
3413
|
+
uVignetteCore: { value: new Vector4(0, 0, 1, 1) },
|
|
3414
|
+
uVignetteSigma: { value: new Vector2(1, 1) },
|
|
3415
|
+
tGrainLattice: { value: lattice }
|
|
3416
|
+
};
|
|
3417
|
+
}
|
|
3418
|
+
var FINISHING_DEFINES = {
|
|
3419
|
+
GRAIN_TABLE_WIDTH,
|
|
3420
|
+
GRAIN_TABLE_HEIGHT,
|
|
3421
|
+
GRAIN_LATTICE,
|
|
3422
|
+
GRAIN_OCTAVES,
|
|
3423
|
+
GRAIN_GREY_COEFFICIENT,
|
|
3424
|
+
GRAIN_SAMPLE_OFFSET
|
|
3425
|
+
};
|
|
3426
|
+
function focusMaterial(fragmentShader, uniforms = {}, defines = {}) {
|
|
3427
|
+
return new ShaderMaterial({
|
|
3428
|
+
defines: { FOCUS_TAPS, ...defines },
|
|
3429
|
+
uniforms: { ...focusUniformValues(), ...uniforms },
|
|
3430
|
+
vertexShader: FOCUS_VERTEX_SHADER,
|
|
3431
|
+
fragmentShader,
|
|
3432
|
+
// The quad replaces the frame outright, alpha included; blending or a depth test would let
|
|
3433
|
+
// whatever was underneath survive and would break the coverage a transparent shot must keep.
|
|
3434
|
+
blending: NoBlending,
|
|
3435
|
+
depthTest: false,
|
|
3436
|
+
depthWrite: false,
|
|
3437
|
+
transparent: true
|
|
3438
|
+
});
|
|
3439
|
+
}
|
|
3440
|
+
var FocusResources = class {
|
|
3441
|
+
constructor(gl, width, height, registerActual = registerActualSceneResourcesV1) {
|
|
3442
|
+
this.registerActual = registerActual;
|
|
3443
|
+
this.renderer = gl;
|
|
3444
|
+
assertHalfFloatColorTargets(gl, FOCUS_SPEC_PATH);
|
|
3445
|
+
this.samples = canvasSampleCount(gl, FOCUS_SPEC_PATH);
|
|
3446
|
+
if (this.samples !== 4) {
|
|
3447
|
+
throw new SceneShotError(
|
|
3448
|
+
"scene_internal",
|
|
3449
|
+
`the prepared scene plan requires the admitted 4-sample canvas, but this renderer reported ${this.samples}`,
|
|
3450
|
+
FOCUS_SPEC_PATH
|
|
3451
|
+
);
|
|
3452
|
+
}
|
|
3453
|
+
this.toneMapping = gl.toneMapping;
|
|
3454
|
+
const depthTexture = new DepthTexture(width, height, UnsignedIntType);
|
|
3455
|
+
depthTexture.format = DepthFormat;
|
|
3456
|
+
depthTexture.minFilter = NearestFilter;
|
|
3457
|
+
depthTexture.magFilter = NearestFilter;
|
|
3458
|
+
this.world = new WebGLRenderTarget(width, height, {
|
|
3459
|
+
format: RGBAFormat,
|
|
3460
|
+
type: HalfFloatType,
|
|
3461
|
+
minFilter: LinearFilter3,
|
|
3462
|
+
magFilter: LinearFilter3,
|
|
3463
|
+
wrapS: ClampToEdgeWrapping,
|
|
3464
|
+
wrapT: ClampToEdgeWrapping,
|
|
3465
|
+
depthBuffer: true,
|
|
3466
|
+
stencilBuffer: false,
|
|
3467
|
+
depthTexture,
|
|
3468
|
+
samples: this.samples
|
|
3469
|
+
});
|
|
3470
|
+
this.gathered = new WebGLRenderTarget(width, height, {
|
|
3471
|
+
format: RGBAFormat,
|
|
3472
|
+
type: HalfFloatType,
|
|
3473
|
+
minFilter: LinearFilter3,
|
|
3474
|
+
magFilter: LinearFilter3,
|
|
3475
|
+
wrapS: ClampToEdgeWrapping,
|
|
3476
|
+
wrapT: ClampToEdgeWrapping,
|
|
3477
|
+
depthBuffer: false,
|
|
3478
|
+
stencilBuffer: false
|
|
3479
|
+
});
|
|
3480
|
+
this.grainLattice = new DataTexture(
|
|
3481
|
+
new Float32Array(GRAIN_TABLE_WIDTH * GRAIN_TABLE_HEIGHT * 4),
|
|
3482
|
+
GRAIN_TABLE_WIDTH,
|
|
3483
|
+
GRAIN_TABLE_HEIGHT,
|
|
3484
|
+
RGBAFormat,
|
|
3485
|
+
FloatType
|
|
3486
|
+
);
|
|
3487
|
+
this.grainLattice.minFilter = NearestFilter;
|
|
3488
|
+
this.grainLattice.magFilter = NearestFilter;
|
|
3489
|
+
this.grainLattice.needsUpdate = true;
|
|
3490
|
+
this.blur = focusMaterial(FOCUS_BLUR_FRAGMENT_SHADER);
|
|
3491
|
+
this.composite = focusMaterial(FOCUS_COMPOSITE_FRAGMENT_SHADER, finishingUniformValues(this.grainLattice), FINISHING_DEFINES);
|
|
3492
|
+
this.geometry = new PlaneGeometry(2, 2);
|
|
3493
|
+
this.mesh = new Mesh(this.geometry, this.blur);
|
|
3494
|
+
this.mesh.frustumCulled = false;
|
|
3495
|
+
this.quadScene = new Scene();
|
|
3496
|
+
this.quadScene.add(this.mesh);
|
|
3497
|
+
this.quadCamera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
|
3498
|
+
this.releaseMeasurement = this.registerActual(this, sceneFocusPreparationAllocationsV1(width, height, 4).map((row) => ({
|
|
3499
|
+
owner: row.owner,
|
|
3500
|
+
name: row.name,
|
|
3501
|
+
domain: row.domain,
|
|
3502
|
+
bytes: row.bytes,
|
|
3503
|
+
width,
|
|
3504
|
+
height,
|
|
3505
|
+
samples: row.name.includes("msaa") ? 4 : void 0
|
|
3506
|
+
})));
|
|
3507
|
+
}
|
|
3508
|
+
registerActual;
|
|
3509
|
+
/**
|
|
3510
|
+
* The renderer these resources were built for and measured against.
|
|
3511
|
+
*
|
|
3512
|
+
* Kept so the pass can check it is still being driven by that renderer. The targets, their
|
|
3513
|
+
* textures and their framebuffers belong to one GL context, and `samples` was read from that
|
|
3514
|
+
* context's canvas; handing them to a different renderer would draw through objects it has never
|
|
3515
|
+
* uploaded. Fiber builds one renderer per canvas and never swaps it, so this is a guard against a
|
|
3516
|
+
* future change rather than a case anyone can reach today — but the symptom would be a blank or
|
|
3517
|
+
* wrong frame with no error, which is exactly the kind of thing that has to be asserted.
|
|
3518
|
+
*/
|
|
3519
|
+
renderer;
|
|
3520
|
+
world;
|
|
3521
|
+
gathered;
|
|
3522
|
+
blur;
|
|
3523
|
+
composite;
|
|
3524
|
+
quadScene;
|
|
3525
|
+
quadCamera;
|
|
3526
|
+
/** The canvas's multisample count, read once at construction and kept across resizes. */
|
|
3527
|
+
samples;
|
|
3528
|
+
/**
|
|
3529
|
+
* The renderer's tone-mapping curve when these resources were built.
|
|
3530
|
+
*
|
|
3531
|
+
* Kept for the same reason `renderer` is, and checked the same way. Every lit material this
|
|
3532
|
+
* package draws carries its own copy of the curve, injected by `onBeforeCompile` from
|
|
3533
|
+
* `renderer.toneMapping` — and three calls that ONCE PER PROGRAM, then serves the compiled
|
|
3534
|
+
* program out of its cache. `customProgramCacheKey` cannot repair that: three computes the cache
|
|
3535
|
+
* key before the material has ever seen a renderer, so the key could only ever carry the curve
|
|
3536
|
+
* of a PREVIOUS compile, and a genuine change would still hit the stale program. So the curve is
|
|
3537
|
+
* asserted constant instead of keyed — which is the truth of this renderer anyway, since fiber
|
|
3538
|
+
* sets it from `flat` at canvas construction and nothing in this package writes it afterwards.
|
|
3539
|
+
*/
|
|
3540
|
+
toneMapping;
|
|
3541
|
+
/**
|
|
3542
|
+
* One frame's grain lattice, as a float texture the composite samples.
|
|
3543
|
+
*
|
|
3544
|
+
* Owned per instance like everything else here, and refreshed only when the frame's seed changes
|
|
3545
|
+
* — which is every frame a shot with grain renders, since `grainSeed` re-seeds per frame, and
|
|
3546
|
+
* never for a shot without it.
|
|
3547
|
+
*/
|
|
3548
|
+
grainLattice;
|
|
3549
|
+
grainLatticeSeed = null;
|
|
3550
|
+
geometry;
|
|
3551
|
+
mesh;
|
|
3552
|
+
releaseMeasurement;
|
|
3553
|
+
get size() {
|
|
3554
|
+
return { width: this.world.width, height: this.world.height };
|
|
3555
|
+
}
|
|
3556
|
+
/**
|
|
3557
|
+
* Follow the frame. `WebGLRenderTarget.setSize` resizes its colour textures but not the depth
|
|
3558
|
+
* texture attached to it, which would leave the depth attachment at the old size and the
|
|
3559
|
+
* framebuffer incomplete — so the depth texture is resized here and dropped, and Three rebuilds
|
|
3560
|
+
* both from the new sizes on the next draw.
|
|
3561
|
+
*/
|
|
3562
|
+
resize(width, height) {
|
|
3563
|
+
if (this.world.width === width && this.world.height === height) return;
|
|
3564
|
+
this.releaseMeasurement();
|
|
3565
|
+
const depth = this.world.depthTexture;
|
|
3566
|
+
if (depth) {
|
|
3567
|
+
depth.image.width = width;
|
|
3568
|
+
depth.image.height = height;
|
|
3569
|
+
depth.dispose();
|
|
3570
|
+
}
|
|
3571
|
+
this.world.setSize(width, height);
|
|
3572
|
+
this.gathered.setSize(width, height);
|
|
3573
|
+
this.releaseMeasurement = this.registerActual(this, sceneFocusPreparationAllocationsV1(width, height, 4).map((row) => ({
|
|
3574
|
+
owner: row.owner,
|
|
3575
|
+
name: row.name,
|
|
3576
|
+
domain: row.domain,
|
|
3577
|
+
bytes: row.bytes,
|
|
3578
|
+
width,
|
|
3579
|
+
height,
|
|
3580
|
+
samples: row.name.includes("msaa") ? 4 : void 0
|
|
3581
|
+
})));
|
|
3582
|
+
}
|
|
3583
|
+
/** Point the quad at one of the two materials; the pass draws the same geometry twice. */
|
|
3584
|
+
use(material) {
|
|
3585
|
+
this.mesh.material = material;
|
|
3586
|
+
}
|
|
3587
|
+
/** Write one frame's focus into both materials. Uniform writes only: no program is rebuilt. */
|
|
3588
|
+
apply(uniforms) {
|
|
3589
|
+
for (const material of [this.blur, this.composite]) {
|
|
3590
|
+
const u = material.uniforms;
|
|
3591
|
+
u.uNear.value = uniforms.near;
|
|
3592
|
+
u.uFar.value = uniforms.far;
|
|
3593
|
+
u.uFocusDistance.value = uniforms.distance;
|
|
3594
|
+
u.uFocusRange.value = uniforms.range;
|
|
3595
|
+
u.uMaxBlur.value = uniforms.maxBlur;
|
|
3596
|
+
u.uTexel.value.set(uniforms.texel[0], uniforms.texel[1]);
|
|
3597
|
+
}
|
|
3598
|
+
this.blur.uniforms.tColor.value = this.world.texture;
|
|
3599
|
+
this.blur.uniforms.tDepth.value = this.world.depthTexture;
|
|
3600
|
+
this.blur.uniforms.uDirection.value.set(1, 0);
|
|
3601
|
+
this.composite.uniforms.tColor.value = this.gathered.texture;
|
|
3602
|
+
this.composite.uniforms.tDepth.value = this.world.depthTexture;
|
|
3603
|
+
this.composite.uniforms.uDirection.value.set(0, 1);
|
|
3604
|
+
}
|
|
3605
|
+
/**
|
|
3606
|
+
* Write one frame's finishing into the composite material.
|
|
3607
|
+
*
|
|
3608
|
+
* Uniform writes and, when the seed moved, one 25 KB texture upload; no program is rebuilt. The
|
|
3609
|
+
* lattice is skipped when grain is off, because nothing samples it then.
|
|
3610
|
+
*/
|
|
3611
|
+
applyFinishing(finishing) {
|
|
3612
|
+
const u = this.composite.uniforms;
|
|
3613
|
+
u.uGrain.value = finishing.grain;
|
|
3614
|
+
u.uVignette.value = finishing.vignette;
|
|
3615
|
+
u.uFrameSize.value.set(finishing.frame[0], finishing.frame[1]);
|
|
3616
|
+
u.uGrainBase.value.set(finishing.grainBase[0], finishing.grainBase[1]);
|
|
3617
|
+
u.uGrainStitch.value.set(finishing.grainStitch[0], finishing.grainStitch[1], finishing.grainStitch[2], finishing.grainStitch[3]);
|
|
3618
|
+
u.uVignetteCore.value.set(finishing.vignetteCore[0], finishing.vignetteCore[1], finishing.vignetteCore[2], finishing.vignetteCore[3]);
|
|
3619
|
+
u.uVignetteSigma.value.set(finishing.vignetteSigma[0], finishing.vignetteSigma[1]);
|
|
3620
|
+
if (finishing.lattice && this.grainLatticeSeed !== finishing.seed) {
|
|
3621
|
+
this.grainLattice.image.data.set(finishing.lattice);
|
|
3622
|
+
this.grainLattice.needsUpdate = true;
|
|
3623
|
+
this.grainLatticeSeed = finishing.seed;
|
|
3624
|
+
}
|
|
3625
|
+
}
|
|
3626
|
+
dispose() {
|
|
3627
|
+
this.world.depthTexture?.dispose();
|
|
3628
|
+
this.world.dispose();
|
|
3629
|
+
this.gathered.dispose();
|
|
3630
|
+
this.blur.dispose();
|
|
3631
|
+
this.composite.dispose();
|
|
3632
|
+
this.grainLattice.dispose();
|
|
3633
|
+
this.geometry.dispose();
|
|
3634
|
+
this.quadScene.remove(this.mesh);
|
|
3635
|
+
this.releaseMeasurement();
|
|
3636
|
+
}
|
|
3637
|
+
};
|
|
3638
|
+
function renderFocusPass(gl, scene, camera, resources, uniforms, finishing) {
|
|
3639
|
+
const output = gl.getRenderTarget();
|
|
3640
|
+
resources.apply(uniforms);
|
|
3641
|
+
resources.applyFinishing(finishing);
|
|
3642
|
+
gl.setRenderTarget(resources.world);
|
|
3643
|
+
gl.render(scene, camera);
|
|
3644
|
+
resources.use(resources.blur);
|
|
3645
|
+
gl.setRenderTarget(resources.gathered);
|
|
3646
|
+
gl.render(resources.quadScene, resources.quadCamera);
|
|
3647
|
+
resources.use(resources.composite);
|
|
3648
|
+
gl.setRenderTarget(output);
|
|
3649
|
+
gl.render(resources.quadScene, resources.quadCamera);
|
|
3650
|
+
}
|
|
3651
|
+
|
|
3652
|
+
// ../execution/animate/src/scene/FocusPass.tsx
|
|
3653
|
+
var FOCUS_PASS_PRIORITY = 1;
|
|
3654
|
+
function focusCameraPlanes(camera) {
|
|
3655
|
+
const perspective = camera;
|
|
3656
|
+
if (!perspective.isPerspectiveCamera) {
|
|
3657
|
+
throw new SceneShotError(
|
|
3658
|
+
"scene_internal",
|
|
3659
|
+
`the focus pass reconstructs view distance from a perspective depth buffer, but this shot's camera is ${perspective.type ?? "of an unknown kind"}`,
|
|
3660
|
+
FOCUS_SPEC_PATH
|
|
3661
|
+
);
|
|
3662
|
+
}
|
|
3663
|
+
return { near: perspective.near, far: perspective.far };
|
|
3664
|
+
}
|
|
3665
|
+
function assertPassRenderer(resources, gl) {
|
|
3666
|
+
if (resources.renderer !== gl) {
|
|
3667
|
+
throw new SceneShotError(
|
|
3668
|
+
"scene_internal",
|
|
3669
|
+
"the world pass was built for one renderer and is being drawn by another; its targets, its textures and its multisample count all belong to the first",
|
|
3670
|
+
FOCUS_SPEC_PATH
|
|
3671
|
+
);
|
|
3672
|
+
}
|
|
3673
|
+
if (resources.toneMapping !== gl.toneMapping) {
|
|
3674
|
+
throw new SceneShotError(
|
|
3675
|
+
"scene_internal",
|
|
3676
|
+
`the world pass was built while this renderer tone-mapped with ${resources.toneMapping} and is being drawn with ${gl.toneMapping}; every lit material compiled the first curve into its own program and would keep drawing it`,
|
|
3677
|
+
FOCUS_SPEC_PATH
|
|
3678
|
+
);
|
|
3679
|
+
}
|
|
3680
|
+
}
|
|
3681
|
+
function FocusPass({ focus, finishing, scale, frame }) {
|
|
3682
|
+
const registerActual = useSceneActualResourceRegistrarV1();
|
|
3683
|
+
const gl = useThree7((s) => s.gl);
|
|
3684
|
+
const scene = useThree7((s) => s.scene);
|
|
3685
|
+
const camera = useThree7((s) => s.camera);
|
|
3686
|
+
const [resources] = useState6(() => new FocusResources(gl, frame.width, frame.height, registerActual));
|
|
3687
|
+
useLayoutEffect10(() => {
|
|
3688
|
+
resources.resize(frame.width, frame.height);
|
|
3689
|
+
}, [resources, frame.width, frame.height]);
|
|
3690
|
+
useLayoutEffect10(() => () => resources.dispose(), [resources]);
|
|
3691
|
+
assertPassRenderer(resources, gl);
|
|
3692
|
+
const planes = focusCameraPlanes(camera);
|
|
3693
|
+
useFrame(() => {
|
|
3694
|
+
renderFocusPass(gl, scene, camera, resources, focusUniforms(focus, scale, planes, frame), finishing);
|
|
3695
|
+
}, FOCUS_PASS_PRIORITY);
|
|
3696
|
+
return null;
|
|
3697
|
+
}
|
|
3698
|
+
|
|
3699
|
+
// ../execution/animate/src/scene/text.tsx
|
|
3700
|
+
import React25 from "react";
|
|
3701
|
+
function screenTextStyle(layer, index, evaluated, scale, frame) {
|
|
3702
|
+
const layout = textBlockLayout(layer, scale);
|
|
3703
|
+
const { width, height } = layout;
|
|
3704
|
+
return {
|
|
3705
|
+
position: "absolute",
|
|
3706
|
+
left: `${frame.width / 2 + evaluated.x * scale - width / 2}px`,
|
|
3707
|
+
top: `${frame.height / 2 + evaluated.y * scale - height / 2}px`,
|
|
3708
|
+
width: `${width}px`,
|
|
3709
|
+
height: `${height}px`,
|
|
3710
|
+
transformOrigin: "50% 50%",
|
|
3711
|
+
transform: `rotate(${evaluated.rotation}deg) scale(${evaluated.scale})`,
|
|
3712
|
+
opacity: evaluated.opacity,
|
|
3713
|
+
color: resolveSceneColor(layer.color, `layers.${index}.color`),
|
|
3714
|
+
fontFamily: resolveSceneFontFamily(layer.fontFamily, `layers.${index}.fontFamily`),
|
|
3715
|
+
fontWeight: layer.fontWeight,
|
|
3716
|
+
fontStyle: layer.fontStyle,
|
|
3717
|
+
fontSize: `${layout.fontSize}px`,
|
|
3718
|
+
lineHeight: `${layout.lineHeight}`,
|
|
3719
|
+
textAlign: layout.align,
|
|
3720
|
+
whiteSpace: "pre",
|
|
3721
|
+
pointerEvents: "none"
|
|
3722
|
+
};
|
|
3723
|
+
}
|
|
3724
|
+
function ScreenText({ layer, index, evaluated, scale, frame }) {
|
|
3725
|
+
return /* @__PURE__ */ React25.createElement("div", { style: screenTextStyle(layer, index, evaluated, scale, frame), "data-scene-layer": layer.id }, layer.lines.map((line, lineIndex) => /* @__PURE__ */ React25.createElement("div", { key: lineIndex }, line.runs.map((run, runIndex) => /* @__PURE__ */ React25.createElement(
|
|
3726
|
+
"span",
|
|
3727
|
+
{
|
|
3728
|
+
key: runIndex,
|
|
3729
|
+
style: run.color === void 0 ? void 0 : { color: resolveSceneColor(run.color, `layers.${index}.lines.${lineIndex}.runs.${runIndex}.color`) }
|
|
3730
|
+
},
|
|
3731
|
+
run.text
|
|
3732
|
+
)))));
|
|
3733
|
+
}
|
|
3734
|
+
|
|
3735
|
+
// ../execution/animate/src/scene/v2/SceneShotV2.tsx
|
|
3736
|
+
function backdropStyleV2(backdrop) {
|
|
3737
|
+
const stops = (rows) => rows.map((row) => `${row.color} ${row.at * 100}%`).join(", ");
|
|
3738
|
+
switch (backdrop.kind) {
|
|
3739
|
+
case "transparent":
|
|
3740
|
+
return {};
|
|
3741
|
+
case "solid":
|
|
3742
|
+
return { background: backdrop.color };
|
|
3743
|
+
case "linear":
|
|
3744
|
+
return { background: `linear-gradient(${backdrop.angle * 180 / Math.PI}deg, ${stops(backdrop.stops)})` };
|
|
3745
|
+
case "radial":
|
|
3746
|
+
return { background: `radial-gradient(circle at ${backdrop.at[0] * 100}% ${backdrop.at[1] * 100}%, ${stops(backdrop.stops)})` };
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
function scaleBounds(b, scale) {
|
|
3750
|
+
return {
|
|
3751
|
+
minX: b.minX * scale,
|
|
3752
|
+
maxX: b.maxX * scale,
|
|
3753
|
+
minY: b.minY * scale,
|
|
3754
|
+
maxY: b.maxY * scale,
|
|
3755
|
+
minZ: b.minZ * scale,
|
|
3756
|
+
maxZ: b.maxZ * scale
|
|
3757
|
+
};
|
|
3758
|
+
}
|
|
3759
|
+
var isScreenText = (node) => node.kind === "text" && node.space === "screen";
|
|
3760
|
+
function drawSceneFrameV2({ advance, invalidate, isRendering, playing, now }) {
|
|
3761
|
+
if (isRendering || !playing) advance(now);
|
|
3762
|
+
else invalidate();
|
|
3763
|
+
}
|
|
3764
|
+
function SceneFrameCommitV2({ frame, children }) {
|
|
3765
|
+
const { advance, invalidate } = useThree8((state) => ({ advance: state.advance, invalidate: state.invalidate }));
|
|
3766
|
+
const [playing] = Internals3.Timeline.usePlayingState();
|
|
3767
|
+
const isRendering = getRemotionEnvironment2().isRendering;
|
|
3768
|
+
useLayoutEffect11(() => {
|
|
3769
|
+
drawSceneFrameV2({ advance, invalidate, isRendering, playing, now: performance.now() });
|
|
3770
|
+
}, [advance, frame, invalidate, isRendering, playing]);
|
|
3771
|
+
return /* @__PURE__ */ React26.createElement(React26.Fragment, null, children);
|
|
3772
|
+
}
|
|
3773
|
+
function resolveSceneAssetsV2(layers, assets) {
|
|
3774
|
+
const out = /* @__PURE__ */ new Map();
|
|
3775
|
+
const walk = (nodes, parentPath = "layers") => {
|
|
3776
|
+
nodes.forEach((node, index) => {
|
|
3777
|
+
const layerPath = `${parentPath}.${index}`;
|
|
3778
|
+
if (node.kind === "group") {
|
|
3779
|
+
walk(node.children, `${layerPath}.children`);
|
|
3780
|
+
return;
|
|
3781
|
+
}
|
|
3782
|
+
const binding = node.kind === "laptop" || node.kind === "phone" ? node.surfaces?.screen : node.kind === "page" ? node.surfaces.content : node.kind === "slab" ? node.surfaces?.front : void 0;
|
|
3783
|
+
if (!binding || binding.source === "color") return;
|
|
3784
|
+
if (binding.source !== "image") throw new Error(`scene_prepared_surface_required: ${layerPath}.surfaces must be prepared before rendering.`);
|
|
3785
|
+
if (node.kind === "laptop" || node.kind === "phone") {
|
|
3786
|
+
out.set(node.id, sceneImageHandle(assets, { slot: binding.assetSlot, layerPath, layerId: node.id, field: "screen", what: "screenshot" }));
|
|
3787
|
+
} else if (node.kind === "page") {
|
|
3788
|
+
out.set(node.id, sceneImageHandle(assets, { slot: binding.assetSlot, layerPath, layerId: node.id, field: "image", what: "page image" }));
|
|
3789
|
+
} else if (node.kind === "slab") {
|
|
3790
|
+
out.set(node.id, sceneImageHandle(assets, { slot: binding.assetSlot, layerPath, layerId: node.id, field: "front", what: "page image" }));
|
|
3791
|
+
}
|
|
3792
|
+
});
|
|
3793
|
+
};
|
|
3794
|
+
walk(layers);
|
|
3795
|
+
return out;
|
|
3796
|
+
}
|
|
3797
|
+
function assertNoObjectLightFields(nodes, parentPath = "layers") {
|
|
3798
|
+
for (let index = 0; index < nodes.length; index += 1) {
|
|
3799
|
+
const node = nodes[index];
|
|
3800
|
+
const path = `${parentPath}.${index}`;
|
|
3801
|
+
assertNoObjectLightField(node, path);
|
|
3802
|
+
if (node.kind === "group") assertNoObjectLightFields(node.children, `${path}.children`);
|
|
3803
|
+
}
|
|
3804
|
+
}
|
|
3805
|
+
function ObjectNode({ node, index, scale, referenceWidth, handles, mountEarly, sealedBodyTriangles, sealedSurfaceColors, preparedSurfaceVisuals, surfaceOwners }) {
|
|
3806
|
+
switch (node.kind) {
|
|
3807
|
+
case "group":
|
|
3808
|
+
return /* @__PURE__ */ React26.createElement(PosedObject, { transform: node.transform, scale, opacity: node.opacity }, node.children.filter((c) => !isScreenText(c)).map((child, i) => /* @__PURE__ */ React26.createElement(ObjectNode, { key: child.id, node: child, index: i, scale, referenceWidth, handles, mountEarly, sealedBodyTriangles, sealedSurfaceColors, preparedSurfaceVisuals, surfaceOwners })));
|
|
3809
|
+
case "laptop":
|
|
3810
|
+
return /* @__PURE__ */ React26.createElement(LaptopObject, { node, src: handles.get(node.id) ?? "", screenColor: sealedSurfaceColors[node.id], preparedSurface: preparedSurfaceVisuals[node.id], surfaceResourceOwner: surfaceOwners[node.id], scale, mountEarly });
|
|
3811
|
+
case "phone":
|
|
3812
|
+
return /* @__PURE__ */ React26.createElement(PhoneObject, { node, src: handles.get(node.id) ?? "", screenColor: sealedSurfaceColors[node.id], preparedSurface: preparedSurfaceVisuals[node.id], surfaceResourceOwner: surfaceOwners[node.id], scale, mountEarly });
|
|
3813
|
+
case "slab":
|
|
3814
|
+
return /* @__PURE__ */ React26.createElement(SlabObject, { node, src: handles.get(node.id), frontColor: sealedSurfaceColors[node.id], preparedSurface: preparedSurfaceVisuals[node.id], surfaceResourceOwner: surfaceOwners[node.id], scale, mountEarly, expectedBodyTriangles: sealedBodyTriangles[node.id] });
|
|
3815
|
+
case "page":
|
|
3816
|
+
return /* @__PURE__ */ React26.createElement(PageObject, { node, src: handles.get(node.id) ?? "", contentColor: sealedSurfaceColors[node.id], preparedSurface: preparedSurfaceVisuals[node.id], surfaceResourceOwner: surfaceOwners[node.id], scale, mountEarly });
|
|
3817
|
+
case "text":
|
|
3818
|
+
return /* @__PURE__ */ React26.createElement(WorldTextObject, { node, index, scale, referenceWidth });
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
function SceneShotV2({ spec: spec2, assets, render, mountSurfacesEarly = false, preparedPlan, sealedBodyTriangles = {}, sealedSurfaceColors = {}, preparedSurfaceVisuals = {}, videoTextureBindings = [], sealedSurfaceHandles, sealedShadowBounds: sealedShadowBounds2, sealedCameraPlanes }) {
|
|
3822
|
+
const scale = referenceScale(render, spec2.referenceSize);
|
|
3823
|
+
const frame = { width: render.width, height: render.height };
|
|
3824
|
+
const photographic = admitSceneRigV2(spec2.environment) === PHOTOGRAPHIC_STUDIO_RIG_ID;
|
|
3825
|
+
const studioRig = photographic ? null : spec2.environment;
|
|
3826
|
+
const lightingProfile = studioRig ? admitLightingProfile(studioRig.lightingProfile) : null;
|
|
3827
|
+
assertNoObjectLightFields(spec2.layers);
|
|
3828
|
+
if (!preparedPlan) assertSceneSurfaceResolution(spec2, frame);
|
|
3829
|
+
const handles = sealedSurfaceHandles ? new Map(Object.entries(sealedSurfaceHandles)) : resolveSceneAssetsV2(spec2.layers, assets);
|
|
3830
|
+
const surfaceOwners = Object.fromEntries(preparedPlan?.surfaces.map((surface) => [surface.authoredObjectId, surface.path]) ?? []);
|
|
3831
|
+
const world = spec2.layers.filter((node) => !isScreenText(node));
|
|
3832
|
+
const screenText = spec2.layers.filter(isScreenText);
|
|
3833
|
+
const filterId = postFilterId(render.seed);
|
|
3834
|
+
const filter = postFilterStyle(filterId, spec2.post);
|
|
3835
|
+
const layerBox = { position: "absolute", inset: 0 };
|
|
3836
|
+
const canDrawWorld = typeof document !== "undefined";
|
|
3837
|
+
const camera = sceneCameraPose(spec2.camera, spec2.referenceSize.height, scale, frame);
|
|
3838
|
+
if (sealedCameraPlanes) {
|
|
3839
|
+
camera.near = sealedCameraPlanes.near;
|
|
3840
|
+
camera.far = sealedCameraPlanes.far;
|
|
3841
|
+
}
|
|
3842
|
+
return /* @__PURE__ */ React26.createElement("div", { style: { ...layerBox, overflow: "hidden" }, "data-scene-shot": render.seed, "data-scene-contract": "2" }, /* @__PURE__ */ React26.createElement("div", { style: { ...layerBox, ...backdropStyleV2(spec2.backdrop), ...filter }, "data-scene-backdrop": "" }), world.length > 0 ? /* @__PURE__ */ React26.createElement("div", { style: layerBox, "data-scene-world": "" }, canDrawWorld ? /* @__PURE__ */ React26.createElement(ThreeCanvas, { width: frame.width, height: frame.height, sceneCamera: camera, shadows: !photographic, style: { position: "absolute", inset: 0 } }, /* @__PURE__ */ React26.createElement(SceneFrameCommitV2, { frame: render.frame }, photographic ? /* @__PURE__ */ React26.createElement(PhotographicStudioRig, { worldScale: scale }) : /* @__PURE__ */ React26.createElement(
|
|
3843
|
+
StudioRig,
|
|
3844
|
+
{
|
|
3845
|
+
lightingProfile,
|
|
3846
|
+
preset: studioRig.preset,
|
|
3847
|
+
intensity: studioRig.intensity,
|
|
3848
|
+
floorY: studioRig.floorY * scale,
|
|
3849
|
+
shadowOpacity: studioRig.shadowOpacity,
|
|
3850
|
+
worldScale: scale,
|
|
3851
|
+
shadowBounds: sealedShadowBounds2 ? scaleBounds(sealedShadowBounds2, scale) : void 0
|
|
3852
|
+
}
|
|
3853
|
+
), world.map((node, index) => /* @__PURE__ */ React26.createElement(ObjectNode, { key: node.id, node, index, scale, referenceWidth: spec2.referenceSize.width, handles, mountEarly: mountSurfacesEarly, sealedBodyTriangles, sealedSurfaceColors, preparedSurfaceVisuals, surfaceOwners })), videoTextureBindings.map((binding) => /* @__PURE__ */ React26.createElement(SceneVideoTextureCommitV1, { key: binding.texture.uuid, binding })), /* @__PURE__ */ React26.createElement(
|
|
3854
|
+
FocusPass,
|
|
3855
|
+
{
|
|
3856
|
+
focus: spec2.post.focus,
|
|
3857
|
+
finishing: sceneFinishingUniforms(spec2.post, render.seed, render.frame, frame, scale),
|
|
3858
|
+
scale,
|
|
3859
|
+
frame
|
|
3860
|
+
}
|
|
3861
|
+
))) : null) : null, screenText.length > 0 ? /* @__PURE__ */ React26.createElement("div", { style: { ...layerBox, ...filter }, "data-scene-screen-text": "" }, screenText.map((node, index) => /* @__PURE__ */ React26.createElement(
|
|
3862
|
+
ScreenText,
|
|
3863
|
+
{
|
|
3864
|
+
key: node.id,
|
|
3865
|
+
layer: node,
|
|
3866
|
+
index,
|
|
3867
|
+
evaluated: { x: node.x, y: node.y, rotation: node.rotation, scale: node.scale, opacity: node.opacity },
|
|
3868
|
+
scale,
|
|
3869
|
+
frame
|
|
3870
|
+
}
|
|
3871
|
+
))) : null, /* @__PURE__ */ React26.createElement(PostFilter, { id: filterId, post: spec2.post, seed: render.seed, frame: render.frame, size: frame, scale }));
|
|
3872
|
+
}
|
|
3873
|
+
|
|
3874
|
+
// ../execution/animate/src/scene/v2/shadow.ts
|
|
3875
|
+
import { Matrix4 as Matrix43, Vector3 as Vector33 } from "three";
|
|
3876
|
+
|
|
3877
|
+
// ../execution/animate/src/scene/worldBounds.ts
|
|
3878
|
+
var EMPTY_BOUNDS = {
|
|
3879
|
+
minX: Number.POSITIVE_INFINITY,
|
|
3880
|
+
maxX: Number.NEGATIVE_INFINITY,
|
|
3881
|
+
minY: Number.POSITIVE_INFINITY,
|
|
3882
|
+
maxY: Number.NEGATIVE_INFINITY,
|
|
3883
|
+
minZ: Number.POSITIVE_INFINITY,
|
|
3884
|
+
maxZ: Number.NEGATIVE_INFINITY
|
|
3885
|
+
};
|
|
3886
|
+
function pointsBounds(points) {
|
|
3887
|
+
const b = { ...EMPTY_BOUNDS };
|
|
3888
|
+
for (const [x, y, z] of points) {
|
|
3889
|
+
b.minX = Math.min(b.minX, x);
|
|
3890
|
+
b.maxX = Math.max(b.maxX, x);
|
|
3891
|
+
b.minY = Math.min(b.minY, y);
|
|
3892
|
+
b.maxY = Math.max(b.maxY, y);
|
|
3893
|
+
b.minZ = Math.min(b.minZ, z);
|
|
3894
|
+
b.maxZ = Math.max(b.maxZ, z);
|
|
3895
|
+
}
|
|
3896
|
+
return b;
|
|
3897
|
+
}
|
|
3898
|
+
function unionBounds(a, b) {
|
|
3899
|
+
return {
|
|
3900
|
+
minX: Math.min(a.minX, b.minX),
|
|
3901
|
+
maxX: Math.max(a.maxX, b.maxX),
|
|
3902
|
+
minY: Math.min(a.minY, b.minY),
|
|
3903
|
+
maxY: Math.max(a.maxY, b.maxY),
|
|
3904
|
+
minZ: Math.min(a.minZ, b.minZ),
|
|
3905
|
+
maxZ: Math.max(a.maxZ, b.maxZ)
|
|
3906
|
+
};
|
|
3907
|
+
}
|
|
3908
|
+
function boxCorners(cx, cy, cz, hx, hy, hz) {
|
|
3909
|
+
const out = [];
|
|
3910
|
+
for (const sx of [-1, 1]) for (const sy of [-1, 1]) for (const sz of [-1, 1]) out.push([cx + sx * hx, cy + sy * hy, cz + sz * hz]);
|
|
3911
|
+
return out;
|
|
3912
|
+
}
|
|
3913
|
+
function deviceShellCorners(kind, width, openAngle) {
|
|
3914
|
+
const dim = deviceDimensions(kind, width);
|
|
3915
|
+
if (kind === "phone") return boxCorners(0, 0, 0, dim.w / 2, dim.h / 2, dim.t / 2);
|
|
3916
|
+
const layout = laptopLayout(dim);
|
|
3917
|
+
const corners = boxCorners(0, layout.baseY, 0, dim.w / 2, dim.t / 2, dim.d / 2);
|
|
3918
|
+
const hinge = [0, layout.hingeY, layout.hingeZ];
|
|
3919
|
+
const theta = lidRotationX(openAngle);
|
|
3920
|
+
const cos = Math.cos(theta), sin = Math.sin(theta);
|
|
3921
|
+
for (const sx of [-1, 1]) for (const y of [0, dim.h]) for (const sz of [-1, 1]) {
|
|
3922
|
+
const z = sz * dim.t / 2;
|
|
3923
|
+
corners.push([sx * dim.w / 2, hinge[1] + y * cos - z * sin, hinge[2] + y * sin + z * cos]);
|
|
3924
|
+
}
|
|
3925
|
+
return corners;
|
|
3926
|
+
}
|
|
3927
|
+
|
|
3928
|
+
// ../execution/animate/src/scene/v2/shadow.ts
|
|
3929
|
+
function sceneShadowBoundsV2(samples, referenceSize, floorY) {
|
|
3930
|
+
let bounds = {
|
|
3931
|
+
minX: -referenceSize.width / 2,
|
|
3932
|
+
maxX: referenceSize.width / 2,
|
|
3933
|
+
minY: Math.min(-referenceSize.height / 2, floorY),
|
|
3934
|
+
maxY: referenceSize.height / 2,
|
|
3935
|
+
minZ: 0,
|
|
3936
|
+
maxZ: 0
|
|
3937
|
+
};
|
|
3938
|
+
for (const objects of samples) bounds = unionBounds(bounds, treeBounds(objects, new Matrix43(), referenceSize.width));
|
|
3939
|
+
return bounds;
|
|
3940
|
+
}
|
|
3941
|
+
function treeBounds(objects, parent, fallbackTextWidth) {
|
|
3942
|
+
let bounds = {
|
|
3943
|
+
minX: Number.POSITIVE_INFINITY,
|
|
3944
|
+
maxX: Number.NEGATIVE_INFINITY,
|
|
3945
|
+
minY: Number.POSITIVE_INFINITY,
|
|
3946
|
+
maxY: Number.NEGATIVE_INFINITY,
|
|
3947
|
+
minZ: Number.POSITIVE_INFINITY,
|
|
3948
|
+
maxZ: Number.NEGATIVE_INFINITY
|
|
3949
|
+
};
|
|
3950
|
+
for (const node of objects) {
|
|
3951
|
+
if (node.kind === "text" && node.space === "screen") continue;
|
|
3952
|
+
const world = parent.clone().multiply(sceneWorldMatrix(node.transform));
|
|
3953
|
+
if (node.kind === "group") {
|
|
3954
|
+
bounds = unionBounds(bounds, treeBounds(node.children, world, fallbackTextWidth));
|
|
3955
|
+
continue;
|
|
3956
|
+
}
|
|
3957
|
+
bounds = unionBounds(bounds, pointsBounds(placed(localCorners(node, fallbackTextWidth), world)));
|
|
3958
|
+
}
|
|
3959
|
+
return bounds;
|
|
3960
|
+
}
|
|
3961
|
+
function localCorners(node, fallbackTextWidth) {
|
|
3962
|
+
switch (node.kind) {
|
|
3963
|
+
case "laptop":
|
|
3964
|
+
return deviceShellCorners("laptop", node.width, node.openAngle * 180 / Math.PI);
|
|
3965
|
+
case "phone":
|
|
3966
|
+
return deviceShellCorners("phone", node.width, 0);
|
|
3967
|
+
case "page":
|
|
3968
|
+
return plane(node.width, node.height);
|
|
3969
|
+
case "slab":
|
|
3970
|
+
return box(node.width, node.height, node.thickness);
|
|
3971
|
+
case "text":
|
|
3972
|
+
return plane(node.maxWidth ?? fallbackTextWidth, textBlockLayout({ ...node, width: node.maxWidth ?? fallbackTextWidth }, 1).height);
|
|
3973
|
+
}
|
|
3974
|
+
}
|
|
3975
|
+
function box(width, height, thickness) {
|
|
3976
|
+
const hx = width / 2, hy = height / 2, hz = thickness / 2;
|
|
3977
|
+
const out = [];
|
|
3978
|
+
for (const x of [-hx, hx]) for (const y of [-hy, hy]) for (const z of [-hz, hz]) out.push([x, y, z]);
|
|
3979
|
+
return out;
|
|
3980
|
+
}
|
|
3981
|
+
function plane(width, height) {
|
|
3982
|
+
const hx = width / 2, hy = height / 2;
|
|
3983
|
+
return [[-hx, -hy, 0], [hx, -hy, 0], [-hx, hy, 0], [hx, hy, 0]];
|
|
3984
|
+
}
|
|
3985
|
+
function placed(local, world) {
|
|
3986
|
+
const v = new Vector33();
|
|
3987
|
+
return local.map((p) => {
|
|
3988
|
+
v.set(...p).applyMatrix4(world);
|
|
3989
|
+
return [v.x, v.y, v.z];
|
|
3990
|
+
});
|
|
3991
|
+
}
|
|
3992
|
+
|
|
3993
|
+
// ../execution/animate/src/scene/v2/PreparedSceneShotV1.tsx
|
|
3994
|
+
var shadowBoundsByPlan = /* @__PURE__ */ new WeakMap();
|
|
3995
|
+
function sealedShadowBounds(plan) {
|
|
3996
|
+
const cached = shadowBoundsByPlan.get(plan);
|
|
3997
|
+
if (cached) return cached;
|
|
3998
|
+
const samples = Array.from({ length: plan.output.durationInFrames }, (_, frame) => evaluateScene(plan.scene, frame, plan.output.durationInFrames).layers.map((node) => runtimeObject(node, plan, {}, {})));
|
|
3999
|
+
const floorY = plan.scene.environment.kind === "photographic-studio-v1" ? -plan.scene.referenceSize.height / 2 : plan.scene.environment.floorY;
|
|
4000
|
+
const bounds = sceneShadowBoundsV2(samples, plan.scene.referenceSize, floorY);
|
|
4001
|
+
shadowBoundsByPlan.set(plan, bounds);
|
|
4002
|
+
return bounds;
|
|
4003
|
+
}
|
|
4004
|
+
var PreparedSceneShotError = class extends Error {
|
|
4005
|
+
constructor(code, message) {
|
|
4006
|
+
super(`${code}: ${message}`);
|
|
4007
|
+
this.code = code;
|
|
4008
|
+
this.name = "PreparedSceneShotError";
|
|
4009
|
+
}
|
|
4010
|
+
code;
|
|
4011
|
+
};
|
|
4012
|
+
function runtimeObject(node, plan, handles, colors) {
|
|
4013
|
+
if (node.kind === "group") return { ...node, opacity: 1, children: (node.children ?? []).map((child) => runtimeObject(child, plan, handles, colors)) };
|
|
4014
|
+
if (node.kind === "text") return { ...node, opacity: node.worldOpacity };
|
|
4015
|
+
if (!["slab", "laptop", "phone", "page"].includes(node.kind)) throw new PreparedSceneShotError("scene_builder_descriptor_unavailable", `Prepared renderer has no ${node.kind} builder yet.`);
|
|
4016
|
+
const prepared = plan.objects.find((object) => object.authoredId === node.id);
|
|
4017
|
+
if (!prepared?.builder || prepared.builder.kind !== node.kind) throw new PreparedSceneShotError("scene_builder_descriptor_mismatch", `${node.kind} '${node.id}' has no matching sealed descriptor.`);
|
|
4018
|
+
const slot = node.kind === "slab" ? "front" : node.kind === "page" ? "content" : "screen";
|
|
4019
|
+
const surface = plan.surfaces.find((candidate) => candidate.authoredObjectId === node.id && candidate.slot === slot);
|
|
4020
|
+
if (!surface) return { ...node, opacity: node.worldOpacity };
|
|
4021
|
+
if (surface.realized.source === "color") {
|
|
4022
|
+
colors[node.id] = surface.realized.color;
|
|
4023
|
+
return { ...node, opacity: node.worldOpacity };
|
|
4024
|
+
}
|
|
4025
|
+
if (surface.realized.source === "video") return { ...node, opacity: node.worldOpacity };
|
|
4026
|
+
handles[node.id] = surface.realized.image.handle;
|
|
4027
|
+
return { ...node, opacity: node.worldOpacity };
|
|
4028
|
+
}
|
|
4029
|
+
function nestedScreenText(nodes) {
|
|
4030
|
+
const screens = [];
|
|
4031
|
+
for (const node of nodes) {
|
|
4032
|
+
if (node.kind === "text" && node.space === "screen") screens.push({ ...node, opacity: node.worldOpacity });
|
|
4033
|
+
if (node.kind === "group" && node.children) screens.push(...nestedScreenText(node.children));
|
|
4034
|
+
}
|
|
4035
|
+
return screens;
|
|
4036
|
+
}
|
|
4037
|
+
function VideoBindingStack({ surfaces, index, contentFrame, visuals, bindings, children }) {
|
|
4038
|
+
const surface = surfaces[index];
|
|
4039
|
+
if (!surface) return /* @__PURE__ */ React.createElement(React.Fragment, null, children(visuals, bindings));
|
|
4040
|
+
const schedule = surface.realized.schedule;
|
|
4041
|
+
const ownerKey = `${surface.authoredObjectId}:${surface.slot}:${surface.realized.video.encodedSha256}:${surface.realized.video.width}x${surface.realized.video.height}:${schedule.sourceRate.num}/${schedule.sourceRate.den}:${schedule.shotRate.num}/${schedule.shotRate.den}:${schedule.contentDuration}:${schedule.startFrame}:${schedule.endFrame}:${schedule.addressing}`;
|
|
4042
|
+
return /* @__PURE__ */ React.createElement(SceneVideoBindingV1, { key: ownerKey, src: surface.realized.video.handle, schedule: surface.realized.schedule, contentFrame, width: surface.realized.video.width, height: surface.realized.video.height, resourceOwner: surface.path }, (binding) => /* @__PURE__ */ React.createElement(VideoBindingStack, { surfaces, index: index + 1, contentFrame, visuals: binding ? { ...visuals, [surface.authoredObjectId]: binding.visual } : visuals, bindings: binding ? [...bindings, binding] : bindings, children }));
|
|
4043
|
+
}
|
|
4044
|
+
function PreparedSceneShotV1({ plan, render }) {
|
|
4045
|
+
return /* @__PURE__ */ React.createElement(SceneRuntimeAllocationBoundaryV1, { plan }, /* @__PURE__ */ React.createElement(PreparedSceneShotContentsV1, { plan, render }));
|
|
4046
|
+
}
|
|
4047
|
+
function PreparedSceneShotContentsV1({ plan, render }) {
|
|
4048
|
+
if (render.width !== plan.output.width || render.height !== plan.output.height || render.fps !== plan.output.fps.num / plan.output.fps.den || render.frame < 0) {
|
|
4049
|
+
throw new PreparedSceneShotError("scene_plan_output_mismatch", "Render frame/output does not match the sealed plan.");
|
|
4050
|
+
}
|
|
4051
|
+
const evaluated = evaluateScene(plan.scene, render.frame, plan.output.durationInFrames);
|
|
4052
|
+
const handles = {};
|
|
4053
|
+
const colors = {};
|
|
4054
|
+
const layers = [
|
|
4055
|
+
...evaluated.layers.map((node) => runtimeObject(node, plan, handles, colors)),
|
|
4056
|
+
...nestedScreenText(evaluated.layers).filter((screen) => !evaluated.layers.some((top) => top.id === screen.id))
|
|
4057
|
+
];
|
|
4058
|
+
const bodyTriangles = Object.fromEntries(plan.objects.filter((object) => object.kind === "slab").map((object) => {
|
|
4059
|
+
const body = object.parts.find((part) => part.partId === "body" && part.mounted);
|
|
4060
|
+
if (!body) throw new PreparedSceneShotError("scene_builder_descriptor_mismatch", `Slab '${object.authoredId}' has no mounted body part.`);
|
|
4061
|
+
return [object.authoredId, body.triangles];
|
|
4062
|
+
}));
|
|
4063
|
+
const shadowBounds = sealedShadowBounds(plan);
|
|
4064
|
+
const spec2 = {
|
|
4065
|
+
...plan.scene,
|
|
4066
|
+
camera: evaluated.camera,
|
|
4067
|
+
environment: evaluated.environment,
|
|
4068
|
+
layers,
|
|
4069
|
+
post: { ...plan.scene.post, focus: evaluated.focus }
|
|
4070
|
+
};
|
|
4071
|
+
const heldRender = { ...render, frame: evaluated.contentFrame };
|
|
4072
|
+
const videos = plan.surfaces.filter((surface) => surface.realized.source === "video");
|
|
4073
|
+
const shot = (preparedSurfaceVisuals, videoTextureBindings) => /* @__PURE__ */ React.createElement(SceneShotV2, { spec: spec2, assets: {}, render: heldRender, preparedPlan: plan, sealedBodyTriangles: bodyTriangles, sealedSurfaceColors: colors, sealedSurfaceHandles: handles, sealedShadowBounds: shadowBounds, preparedSurfaceVisuals, videoTextureBindings, sealedCameraPlanes: plan.motion.cameraClipPlanes[evaluated.contentFrame] });
|
|
4074
|
+
if (!videos.length) return shot({}, []);
|
|
4075
|
+
return /* @__PURE__ */ React.createElement(VideoBindingStack, { surfaces: videos, index: 0, contentFrame: evaluated.contentFrame, visuals: {}, bindings: [] }, shot);
|
|
4076
|
+
}
|
|
4077
|
+
|
|
4078
|
+
// ../execution/animate/src/scene/v2/preparedSurface.ts
|
|
4079
|
+
function preparedSurfaceDeviceProps(surface) {
|
|
4080
|
+
if (!surface) return { screen: null };
|
|
4081
|
+
return surface.kind === "texture" ? { screen: surface.texture } : { screen: null, screenColor: surface.color };
|
|
4082
|
+
}
|
|
4083
|
+
|
|
4084
|
+
// ../execution/animate/src/media/recipes.ts
|
|
4085
|
+
function finite(name, value, minimum = 0) {
|
|
4086
|
+
if (!Number.isFinite(value) || value < minimum) throw new Error(`${name} must be at least ${minimum}.`);
|
|
4087
|
+
return value;
|
|
4088
|
+
}
|
|
4089
|
+
function progress(value) {
|
|
4090
|
+
finite("progress", value);
|
|
4091
|
+
return Math.min(1, value);
|
|
4092
|
+
}
|
|
4093
|
+
function stream(streamIds, index) {
|
|
4094
|
+
if (streamIds.length === 0 || streamIds.some((id) => !id)) throw new Error("A media tile recipe requires stream IDs.");
|
|
4095
|
+
return streamIds[index % streamIds.length];
|
|
4096
|
+
}
|
|
4097
|
+
function driftWallRecipe(input) {
|
|
4098
|
+
const columns = Math.floor(finite("columns", input.columns, 1));
|
|
4099
|
+
const rows = Math.floor(finite("rows", input.rows, 1));
|
|
4100
|
+
const width = finite("tileWidth", input.tileWidth, Number.EPSILON);
|
|
4101
|
+
const height = finite("tileHeight", input.tileHeight, Number.EPSILON);
|
|
4102
|
+
const gap = finite("gap", input.gap);
|
|
4103
|
+
const t = progress(input.progress);
|
|
4104
|
+
const strideX = width + gap;
|
|
4105
|
+
const strideY = height + gap;
|
|
4106
|
+
const wallWidth = columns * strideX;
|
|
4107
|
+
const wallHeight = rows * strideY;
|
|
4108
|
+
const dx = (input.driftX ?? strideX) * t;
|
|
4109
|
+
const dy = (input.driftY ?? strideY * 0.35) * t;
|
|
4110
|
+
const tiles = [];
|
|
4111
|
+
for (let row = 0; row < rows; row++) {
|
|
4112
|
+
for (let column = 0; column < columns; column++) {
|
|
4113
|
+
const stagger = row % 2 === 0 ? 0 : strideX * 0.5;
|
|
4114
|
+
const x = (column * strideX + stagger + dx + wallWidth * 0.5) % wallWidth - wallWidth * 0.5;
|
|
4115
|
+
const y = (row * strideY + dy + wallHeight * 0.5) % wallHeight - wallHeight * 0.5;
|
|
4116
|
+
tiles.push({ stream: stream(input.streamIds, row * columns + column), x, y, width, height });
|
|
4117
|
+
}
|
|
4118
|
+
}
|
|
4119
|
+
return { tiles };
|
|
4120
|
+
}
|
|
4121
|
+
function infiniteSpiralRecipe(input) {
|
|
4122
|
+
const count = Math.floor(finite("count", input.count, 1));
|
|
4123
|
+
const t = progress(input.progress);
|
|
4124
|
+
const turns = finite("turns", input.turns, Number.EPSILON);
|
|
4125
|
+
const tiles = Array.from({ length: count }, (_, index) => {
|
|
4126
|
+
const unit = count === 1 ? 0 : index / (count - 1);
|
|
4127
|
+
const angle = unit * Math.PI * 2 * turns + t * Math.PI * 2;
|
|
4128
|
+
const radius = finite("radiusStep", input.radiusStep) * (index + 1);
|
|
4129
|
+
return {
|
|
4130
|
+
stream: stream(input.streamIds, index),
|
|
4131
|
+
x: Math.cos(angle) * radius,
|
|
4132
|
+
y: Math.sin(angle) * radius,
|
|
4133
|
+
z: unit * 900,
|
|
4134
|
+
width: finite("tileWidth", input.tileWidth, Number.EPSILON),
|
|
4135
|
+
height: finite("tileHeight", input.tileHeight, Number.EPSILON),
|
|
4136
|
+
rotation: angle * 180 / Math.PI + 90,
|
|
4137
|
+
opacity: Math.max(0.08, 1 - unit * unit * 0.82)
|
|
4138
|
+
};
|
|
4139
|
+
});
|
|
4140
|
+
return { tiles, camera: { z: t * 480, zoom: 1 + t * 0.12 }, fog: { color: "#08090d", near: 300, far: 1200 } };
|
|
4141
|
+
}
|
|
4142
|
+
function depthJourneyRecipe(input) {
|
|
4143
|
+
const count = Math.floor(finite("count", input.count, 1));
|
|
4144
|
+
const depth = finite("depth", input.depth, Number.EPSILON);
|
|
4145
|
+
const t = progress(input.progress);
|
|
4146
|
+
const tiles = Array.from({ length: count }, (_, index) => {
|
|
4147
|
+
const layer = index / count;
|
|
4148
|
+
const z = (layer * depth - t * depth + depth) % depth;
|
|
4149
|
+
const angle = index * 2.399963229728653;
|
|
4150
|
+
const radius = 110 + index * 83 % 520;
|
|
4151
|
+
const fog = z / depth;
|
|
4152
|
+
return {
|
|
4153
|
+
stream: stream(input.streamIds, index),
|
|
4154
|
+
x: Math.cos(angle) * radius,
|
|
4155
|
+
y: Math.sin(angle) * radius * 0.62,
|
|
4156
|
+
z,
|
|
4157
|
+
width: finite("tileWidth", input.tileWidth, Number.EPSILON),
|
|
4158
|
+
height: finite("tileHeight", input.tileHeight, Number.EPSILON),
|
|
4159
|
+
rotation: Math.sin(angle) * 8,
|
|
4160
|
+
opacity: Math.max(0.06, (1 - fog) * (1 - fog))
|
|
4161
|
+
};
|
|
4162
|
+
});
|
|
4163
|
+
return { tiles, camera: { x: Math.sin(t * Math.PI * 2) * 45, y: Math.cos(t * Math.PI * 2) * 24 }, fog: { color: "#050609", near: depth * 0.28, far: depth } };
|
|
4164
|
+
}
|
|
4165
|
+
function hashString(value) {
|
|
4166
|
+
let hash = 0;
|
|
4167
|
+
for (let index = 0; index < value.length; index++) {
|
|
4168
|
+
hash = (hash << 5) - hash + value.charCodeAt(index) | 0;
|
|
4169
|
+
}
|
|
4170
|
+
return Math.abs(hash);
|
|
4171
|
+
}
|
|
4172
|
+
function seededRandom(seed) {
|
|
4173
|
+
const value = Math.sin(seed * 9999) * 1e4;
|
|
4174
|
+
return value - Math.floor(value);
|
|
4175
|
+
}
|
|
4176
|
+
function infiniteCanvasRecipe(input) {
|
|
4177
|
+
if (input.streamIds.length === 0 || input.streamIds.some((id) => !id)) {
|
|
4178
|
+
throw new Error("An infinite canvas recipe requires stream IDs.");
|
|
4179
|
+
}
|
|
4180
|
+
const viewportHeight = finite("viewportHeight", input.viewportHeight, Number.EPSILON);
|
|
4181
|
+
const aspectRatio = finite("aspectRatio", input.aspectRatio ?? 16 / 9, Number.EPSILON);
|
|
4182
|
+
const fovDegrees = finite("fovDegrees", input.fovDegrees ?? 60, Number.EPSILON);
|
|
4183
|
+
if (fovDegrees >= 180) throw new Error("fovDegrees must be less than 180.");
|
|
4184
|
+
const t = progress(input.progress);
|
|
4185
|
+
const eased = t * t * (3 - 2 * t);
|
|
4186
|
+
const perspective = viewportHeight / (2 * Math.tan(fovDegrees * Math.PI / 360));
|
|
4187
|
+
const worldScale = perspective / 50;
|
|
4188
|
+
const camera = {
|
|
4189
|
+
x: (input.driftX ?? 6) * eased,
|
|
4190
|
+
y: (input.driftY ?? -3) * eased,
|
|
4191
|
+
z: 50 - (input.forwardTravel ?? 35) * eased
|
|
4192
|
+
};
|
|
4193
|
+
const tiles = [];
|
|
4194
|
+
const chunkSize = 110;
|
|
4195
|
+
const depthFadeStart = 140;
|
|
4196
|
+
const depthFadeEnd = 260;
|
|
4197
|
+
for (let cx = -1; cx <= 1; cx++) {
|
|
4198
|
+
for (let cy = -1; cy <= 1; cy++) {
|
|
4199
|
+
for (let cz = -2; cz <= 0; cz++) {
|
|
4200
|
+
const seed = hashString(`${cx},${cy},${cz}`);
|
|
4201
|
+
for (let item = 0; item < 5; item++) {
|
|
4202
|
+
const itemSeed = seed + item * 1e3;
|
|
4203
|
+
const random = (offset) => seededRandom(itemSeed + offset);
|
|
4204
|
+
const size = 12 + random(4) * 8;
|
|
4205
|
+
const planeX = cx * chunkSize + random(0) * chunkSize;
|
|
4206
|
+
const planeY = cy * chunkSize + random(1) * chunkSize;
|
|
4207
|
+
const planeZ = cz * chunkSize + random(2) * chunkSize;
|
|
4208
|
+
const depthDistance = Math.abs(planeZ - camera.z);
|
|
4209
|
+
const depthFade = depthDistance <= depthFadeStart ? 1 : Math.max(0, 1 - (depthDistance - depthFadeStart) / (depthFadeEnd - depthFadeStart));
|
|
4210
|
+
const mediaIndex = Math.floor(random(5) * 1e6);
|
|
4211
|
+
tiles.push({
|
|
4212
|
+
stream: input.streamIds[mediaIndex % input.streamIds.length],
|
|
4213
|
+
x: (planeX - camera.x) * worldScale,
|
|
4214
|
+
y: (camera.y - planeY) * worldScale,
|
|
4215
|
+
z: (camera.z - planeZ) * worldScale - perspective,
|
|
4216
|
+
width: size * aspectRatio * worldScale,
|
|
4217
|
+
height: size * worldScale,
|
|
4218
|
+
opacity: depthFade * depthFade
|
|
4219
|
+
});
|
|
4220
|
+
}
|
|
4221
|
+
}
|
|
4222
|
+
}
|
|
4223
|
+
}
|
|
4224
|
+
return { tiles, camera: { perspective } };
|
|
4225
|
+
}
|
|
4226
|
+
function gridToHeroRecipe(input) {
|
|
4227
|
+
const columns = Math.floor(finite("columns", input.columns, 1));
|
|
4228
|
+
const rows = Math.floor(finite("rows", input.rows, 1));
|
|
4229
|
+
const count = columns * rows;
|
|
4230
|
+
if (!Number.isSafeInteger(input.heroIndex) || input.heroIndex < 0 || input.heroIndex >= count) {
|
|
4231
|
+
throw new Error("heroIndex must reference a tile in the grid.");
|
|
4232
|
+
}
|
|
4233
|
+
const t = progress(input.progress);
|
|
4234
|
+
const eased = t * t * (3 - 2 * t);
|
|
4235
|
+
const strideX = input.tileWidth + finite("gap", input.gap);
|
|
4236
|
+
const strideY = input.tileHeight + input.gap;
|
|
4237
|
+
const tiles = Array.from({ length: count }, (_, index) => {
|
|
4238
|
+
const x = (index % columns - (columns - 1) / 2) * strideX;
|
|
4239
|
+
const y = (Math.floor(index / columns) - (rows - 1) / 2) * strideY;
|
|
4240
|
+
const hero = index === input.heroIndex;
|
|
4241
|
+
return {
|
|
4242
|
+
stream: stream(input.streamIds, index),
|
|
4243
|
+
x: hero ? x * (1 - eased) : x * (1 + eased * 0.35),
|
|
4244
|
+
y: hero ? y * (1 - eased) : y * (1 + eased * 0.35),
|
|
4245
|
+
z: hero ? -eased * 80 : eased * 180,
|
|
4246
|
+
width: hero ? input.tileWidth + (input.heroWidth - input.tileWidth) * eased : input.tileWidth,
|
|
4247
|
+
height: hero ? input.tileHeight + (input.heroHeight - input.tileHeight) * eased : input.tileHeight,
|
|
4248
|
+
opacity: hero ? 1 : 1 - eased
|
|
4249
|
+
};
|
|
4250
|
+
});
|
|
4251
|
+
return { tiles };
|
|
4252
|
+
}
|
|
4253
|
+
|
|
4254
|
+
// ../execution/animate/src/index.ts
|
|
4255
|
+
var sandboxScope = {
|
|
4256
|
+
smooth,
|
|
4257
|
+
smootherstep,
|
|
4258
|
+
rushInto,
|
|
4259
|
+
rushFrom,
|
|
4260
|
+
Create,
|
|
4261
|
+
GrowFromCenter,
|
|
4262
|
+
FadeIn,
|
|
4263
|
+
Write,
|
|
4264
|
+
Indicate,
|
|
4265
|
+
Wiggle,
|
|
4266
|
+
LaggedStart,
|
|
4267
|
+
AnimationGroup,
|
|
4268
|
+
Succession,
|
|
4269
|
+
Transform,
|
|
4270
|
+
MoveAlongPath,
|
|
4271
|
+
GrowArrow,
|
|
4272
|
+
Arrow,
|
|
4273
|
+
makeArrowPath,
|
|
4274
|
+
BrandBox,
|
|
4275
|
+
Graph,
|
|
4276
|
+
DiGraph,
|
|
4277
|
+
ThreeCanvas,
|
|
4278
|
+
StageCameraRig,
|
|
4279
|
+
useImageTexture,
|
|
4280
|
+
StudioRig,
|
|
4281
|
+
DeviceMesh,
|
|
4282
|
+
deviceDimensions,
|
|
4283
|
+
lidRotationX,
|
|
4284
|
+
makeDefaultScreenTexture,
|
|
4285
|
+
defaultScreenLayout,
|
|
4286
|
+
solveFlex,
|
|
4287
|
+
flexReady,
|
|
4288
|
+
isFlexReady,
|
|
4289
|
+
leafIds,
|
|
4290
|
+
flexBoxToThree,
|
|
4291
|
+
fitBox,
|
|
4292
|
+
FlexLayout,
|
|
4293
|
+
useFlexReady,
|
|
4294
|
+
PerspectiveStage,
|
|
4295
|
+
StageLayer,
|
|
4296
|
+
ContactShadow,
|
|
4297
|
+
useStage,
|
|
4298
|
+
resolveCamera,
|
|
4299
|
+
cameraToThree,
|
|
4300
|
+
perspectiveFor,
|
|
4301
|
+
worldTransform,
|
|
4302
|
+
dofBlur,
|
|
4303
|
+
CAMERA_PRESETS,
|
|
4304
|
+
dollyIn,
|
|
4305
|
+
dollyOut,
|
|
4306
|
+
drift,
|
|
4307
|
+
tiltReveal,
|
|
4308
|
+
orbit,
|
|
4309
|
+
DEFAULT_CAMERA,
|
|
4310
|
+
MediaTileScene,
|
|
4311
|
+
ImageTileScene,
|
|
4312
|
+
driftWallRecipe,
|
|
4313
|
+
infiniteSpiralRecipe,
|
|
4314
|
+
depthJourneyRecipe,
|
|
4315
|
+
infiniteCanvasRecipe,
|
|
4316
|
+
gridToHeroRecipe,
|
|
4317
|
+
SceneShotV2
|
|
4318
|
+
};
|
|
4319
|
+
var sandboxScopeNames = Object.keys(sandboxScope);
|
|
4320
|
+
|
|
4321
|
+
export {
|
|
4322
|
+
smooth,
|
|
4323
|
+
smootherstep,
|
|
4324
|
+
rushInto,
|
|
4325
|
+
rushFrom,
|
|
4326
|
+
Create,
|
|
4327
|
+
GrowFromCenter,
|
|
4328
|
+
FadeIn,
|
|
4329
|
+
Write,
|
|
4330
|
+
Indicate,
|
|
4331
|
+
Wiggle,
|
|
4332
|
+
LaggedStart,
|
|
4333
|
+
AnimationGroup,
|
|
4334
|
+
Succession,
|
|
4335
|
+
Transform,
|
|
4336
|
+
MoveAlongPath,
|
|
4337
|
+
GrowArrow,
|
|
4338
|
+
Arrow,
|
|
4339
|
+
makeArrowPath,
|
|
4340
|
+
BrandBox,
|
|
4341
|
+
Graph,
|
|
4342
|
+
DiGraph,
|
|
4343
|
+
DEFAULT_CAMERA,
|
|
4344
|
+
perspectiveFor,
|
|
4345
|
+
cameraOps,
|
|
4346
|
+
worldTransform,
|
|
4347
|
+
resolveCamera,
|
|
4348
|
+
cameraOpsMatrix,
|
|
4349
|
+
cameraToThree,
|
|
4350
|
+
SCENE_DEFAULT_FOV,
|
|
4351
|
+
SCENE_FOV_MIN,
|
|
4352
|
+
SCENE_FOV_MAX,
|
|
4353
|
+
sceneEyeDistance,
|
|
4354
|
+
defaultSceneCamera,
|
|
4355
|
+
sceneCameraPlanes,
|
|
4356
|
+
sceneCameraPose,
|
|
4357
|
+
sceneCameraPoseFromV1,
|
|
4358
|
+
StageCameraRig,
|
|
4359
|
+
ThreeCanvas,
|
|
4360
|
+
useImageTexture,
|
|
4361
|
+
defaultScreenLayout,
|
|
4362
|
+
makeDefaultScreenTexture,
|
|
4363
|
+
flexReady,
|
|
4364
|
+
isFlexReady,
|
|
4365
|
+
leafIds,
|
|
4366
|
+
solveFlex,
|
|
4367
|
+
flexBoxToThree,
|
|
4368
|
+
fitBox,
|
|
4369
|
+
unionTracks,
|
|
4370
|
+
weightsAt,
|
|
4371
|
+
buildTree,
|
|
4372
|
+
useFlexReady,
|
|
4373
|
+
FlexLayout,
|
|
4374
|
+
dollyIn,
|
|
4375
|
+
dollyOut,
|
|
4376
|
+
drift,
|
|
4377
|
+
tiltReveal,
|
|
4378
|
+
orbit,
|
|
4379
|
+
CAMERA_PRESETS,
|
|
4380
|
+
dofBlur,
|
|
4381
|
+
useStage,
|
|
4382
|
+
PerspectiveStage,
|
|
4383
|
+
StageLayer,
|
|
4384
|
+
ContactShadow,
|
|
4385
|
+
MEDIA_TILE_SCENE_LIMITS,
|
|
4386
|
+
mediaTileFramesReady,
|
|
4387
|
+
assertMediaTileScene,
|
|
4388
|
+
mediaTileCropUvs,
|
|
4389
|
+
mediaTileFogDistances,
|
|
4390
|
+
MediaTileScene,
|
|
4391
|
+
ImageTileScene,
|
|
4392
|
+
SceneShotError,
|
|
4393
|
+
referenceScale,
|
|
4394
|
+
conjugateF,
|
|
4395
|
+
sceneWorldMatrix,
|
|
4396
|
+
sceneCssMatrix,
|
|
4397
|
+
sceneLayerPose,
|
|
4398
|
+
scaleSceneTransform,
|
|
4399
|
+
PosedObject,
|
|
4400
|
+
LaptopObject,
|
|
4401
|
+
SLAB_CONTENT_OFFSET,
|
|
4402
|
+
SlabObject,
|
|
4403
|
+
PageObject,
|
|
4404
|
+
WorldTextObject,
|
|
4405
|
+
sceneSlotsFor,
|
|
4406
|
+
sceneBoundSurfaces,
|
|
4407
|
+
assertSceneSurfaceResolution,
|
|
4408
|
+
SceneVideoBindingV1,
|
|
4409
|
+
SceneVideoTextureCommitV1,
|
|
4410
|
+
backdropStyleV2,
|
|
4411
|
+
resolveSceneAssetsV2,
|
|
4412
|
+
SceneShotV2,
|
|
4413
|
+
sceneShadowBoundsV2,
|
|
4414
|
+
PreparedSceneShotError,
|
|
4415
|
+
PreparedSceneShotV1,
|
|
4416
|
+
preparedSurfaceDeviceProps,
|
|
4417
|
+
driftWallRecipe,
|
|
4418
|
+
infiniteSpiralRecipe,
|
|
4419
|
+
depthJourneyRecipe,
|
|
4420
|
+
infiniteCanvasRecipe,
|
|
4421
|
+
gridToHeroRecipe,
|
|
4422
|
+
sandboxScope,
|
|
4423
|
+
sandboxScopeNames
|
|
4424
|
+
};
|