@3driseai/3drise-viewer 0.1.28 → 0.1.29
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/animationsV2/ClipPlayer.d.ts.map +1 -1
- package/dist/animationsV2/ClipPlayer.js +13 -9
- package/dist/animationsV2/ClipsRuntime.d.ts +44 -3
- package/dist/animationsV2/ClipsRuntime.d.ts.map +1 -1
- package/dist/animationsV2/ClipsRuntime.js +173 -55
- package/dist/animationsV2/appliers.d.ts.map +1 -1
- package/dist/animationsV2/appliers.js +21 -5
- package/dist/animationsV2/index.d.ts +1 -1
- package/dist/animationsV2/index.d.ts.map +1 -1
- package/dist/animationsV2/normalize.d.ts.map +1 -1
- package/dist/animationsV2/normalize.js +7 -3
- package/dist/animationsV2/sequenceUtils.d.ts +44 -6
- package/dist/animationsV2/sequenceUtils.d.ts.map +1 -1
- package/dist/animationsV2/sequenceUtils.js +58 -12
- package/dist/animationsV2/types.d.ts +22 -12
- package/dist/animationsV2/types.d.ts.map +1 -1
- package/dist/api/sceneHandle.d.ts +35 -1
- package/dist/api/sceneHandle.d.ts.map +1 -1
- package/dist/api/sceneHandle.js +88 -17
- package/dist/components/AdvancedGrid.d.ts +1 -5
- package/dist/components/AdvancedGrid.d.ts.map +1 -1
- package/dist/components/AdvancedGrid.js +6 -35
- package/dist/components/AnimatedObject.d.ts.map +1 -1
- package/dist/components/AnimatedObject.js +9 -4
- package/dist/components/ApollonianGrid.d.ts +1 -1
- package/dist/components/ApollonianGrid.d.ts.map +1 -1
- package/dist/components/ApollonianGrid.js +3 -28
- package/dist/components/ChladniGrid.d.ts +1 -1
- package/dist/components/ChladniGrid.d.ts.map +1 -1
- package/dist/components/ChladniGrid.js +6 -35
- package/dist/components/CircuitGrid.d.ts +1 -1
- package/dist/components/CircuitGrid.d.ts.map +1 -1
- package/dist/components/CircuitGrid.js +6 -34
- package/dist/components/ConformalGrid.d.ts +1 -1
- package/dist/components/ConformalGrid.d.ts.map +1 -1
- package/dist/components/ConformalGrid.js +3 -34
- package/dist/components/ContourGrid.d.ts +1 -1
- package/dist/components/ContourGrid.d.ts.map +1 -1
- package/dist/components/ContourGrid.js +6 -34
- package/dist/components/CustomPrimitive.js +1 -1
- package/dist/components/EnvironmentObject.d.ts.map +1 -1
- package/dist/components/EnvironmentObject.js +9 -7
- package/dist/components/FlowNetGrid.d.ts +1 -1
- package/dist/components/FlowNetGrid.d.ts.map +1 -1
- package/dist/components/FlowNetGrid.js +6 -34
- package/dist/components/FractalGrid.d.ts +1 -1
- package/dist/components/FractalGrid.d.ts.map +1 -1
- package/dist/components/FractalGrid.js +6 -37
- package/dist/components/Galaxy.d.ts.map +1 -1
- package/dist/components/Galaxy.js +9 -23
- package/dist/components/GirihGrid.d.ts +1 -1
- package/dist/components/GirihGrid.d.ts.map +1 -1
- package/dist/components/GirihGrid.js +6 -35
- package/dist/components/GravWaveGrid.d.ts +1 -1
- package/dist/components/GravWaveGrid.d.ts.map +1 -1
- package/dist/components/GravWaveGrid.js +6 -35
- package/dist/components/HexGrid.d.ts +1 -5
- package/dist/components/HexGrid.d.ts.map +1 -1
- package/dist/components/HexGrid.js +6 -36
- package/dist/components/HilbertGrid.d.ts +1 -1
- package/dist/components/HilbertGrid.d.ts.map +1 -1
- package/dist/components/HilbertGrid.js +3 -30
- package/dist/components/HyperbolicGrid.d.ts +1 -1
- package/dist/components/HyperbolicGrid.d.ts.map +1 -1
- package/dist/components/HyperbolicGrid.js +6 -34
- package/dist/components/LandObject.d.ts +9 -0
- package/dist/components/LandObject.d.ts.map +1 -0
- package/dist/components/LandObject.js +15 -0
- package/dist/components/LensingGrid.d.ts +1 -1
- package/dist/components/LensingGrid.d.ts.map +1 -1
- package/dist/components/LensingGrid.js +3 -29
- package/dist/components/LightsManager.d.ts.map +1 -1
- package/dist/components/LightsManager.js +8 -0
- package/dist/components/ModelBoundary.d.ts +2 -0
- package/dist/components/ModelBoundary.d.ts.map +1 -1
- package/dist/components/ModelBoundary.js +3 -0
- package/dist/components/ModelPrimitive.d.ts.map +1 -1
- package/dist/components/ModelPrimitive.js +6 -0
- package/dist/components/MoireGrid.d.ts +1 -1
- package/dist/components/MoireGrid.d.ts.map +1 -1
- package/dist/components/MoireGrid.js +6 -35
- package/dist/components/MoonDisc.d.ts +11 -0
- package/dist/components/MoonDisc.d.ts.map +1 -0
- package/dist/components/MoonDisc.js +128 -0
- package/dist/components/ObjectNode.d.ts.map +1 -1
- package/dist/components/ObjectNode.js +15 -4
- package/dist/components/ObjectsRenderer.d.ts.map +1 -1
- package/dist/components/ObjectsRenderer.js +7 -5
- package/dist/components/OceanBuilder.d.ts.map +1 -1
- package/dist/components/OceanBuilder.js +2 -0
- package/dist/components/ParastichyGrid.d.ts +1 -1
- package/dist/components/ParastichyGrid.d.ts.map +1 -1
- package/dist/components/ParastichyGrid.js +3 -30
- package/dist/components/PhyllotaxisGrid.d.ts +1 -1
- package/dist/components/PhyllotaxisGrid.d.ts.map +1 -1
- package/dist/components/PhyllotaxisGrid.js +3 -32
- package/dist/components/ProjectLoader.d.ts +5 -3
- package/dist/components/ProjectLoader.d.ts.map +1 -1
- package/dist/components/ProjectLoader.js +6 -3
- package/dist/components/QuasiGrid.d.ts +1 -1
- package/dist/components/QuasiGrid.d.ts.map +1 -1
- package/dist/components/QuasiGrid.js +6 -33
- package/dist/components/RadarGrid.d.ts +1 -1
- package/dist/components/RadarGrid.d.ts.map +1 -1
- package/dist/components/RadarGrid.js +6 -34
- package/dist/components/ReactionDiffusionGrid.d.ts +1 -1
- package/dist/components/ReactionDiffusionGrid.d.ts.map +1 -1
- package/dist/components/ReactionDiffusionGrid.js +6 -35
- package/dist/components/SceneBuilder.d.ts +25 -3
- package/dist/components/SceneBuilder.d.ts.map +1 -1
- package/dist/components/SceneBuilder.js +68 -38
- package/dist/components/SkyController.d.ts +25 -1
- package/dist/components/SkyController.d.ts.map +1 -1
- package/dist/components/SkyController.js +189 -130
- package/dist/components/SkyMesh.d.ts.map +1 -1
- package/dist/components/SkyMesh.js +26 -1
- package/dist/components/SkyStars.d.ts +11 -0
- package/dist/components/SkyStars.d.ts.map +1 -0
- package/dist/components/SkyStars.js +187 -0
- package/dist/components/SkySystem.d.ts +3 -3
- package/dist/components/SkySystem.d.ts.map +1 -1
- package/dist/components/SkySystem.js +8 -2
- package/dist/components/Sun.d.ts +15 -1
- package/dist/components/Sun.d.ts.map +1 -1
- package/dist/components/Sun.js +64 -3
- package/dist/components/SunLight.d.ts +6 -1
- package/dist/components/SunLight.d.ts.map +1 -1
- package/dist/components/SunLight.js +96 -44
- package/dist/components/TerrainBuilder.d.ts.map +1 -1
- package/dist/components/TerrainBuilder.js +2 -0
- package/dist/components/TextGenerator.d.ts +9 -0
- package/dist/components/TextGenerator.d.ts.map +1 -0
- package/dist/components/TextGenerator.js +29 -0
- package/dist/components/TruchetGrid.d.ts +1 -1
- package/dist/components/TruchetGrid.d.ts.map +1 -1
- package/dist/components/TruchetGrid.js +3 -30
- package/dist/components/VoronoiGrid.d.ts +1 -1
- package/dist/components/VoronoiGrid.d.ts.map +1 -1
- package/dist/components/VoronoiGrid.js +6 -33
- package/dist/components/WallpaperGrid.d.ts +1 -1
- package/dist/components/WallpaperGrid.d.ts.map +1 -1
- package/dist/components/WallpaperGrid.js +6 -35
- package/dist/components/environment/Rain.d.ts +15 -0
- package/dist/components/environment/Rain.d.ts.map +1 -0
- package/dist/components/environment/Rain.js +110 -0
- package/dist/components/environment/Rainbow.d.ts +20 -0
- package/dist/components/environment/Rainbow.d.ts.map +1 -0
- package/dist/components/environment/Rainbow.js +974 -0
- package/dist/components/environment/Sandstorm.d.ts +20 -0
- package/dist/components/environment/Sandstorm.d.ts.map +1 -0
- package/dist/components/environment/Sandstorm.js +776 -0
- package/dist/components/environment/Snow.d.ts +20 -0
- package/dist/components/environment/Snow.d.ts.map +1 -0
- package/dist/components/environment/Snow.js +609 -0
- package/dist/components/environment/Thunderstorm.d.ts +20 -0
- package/dist/components/environment/Thunderstorm.d.ts.map +1 -0
- package/dist/components/environment/Thunderstorm.js +731 -0
- package/dist/components/environment/Tornado.d.ts +20 -0
- package/dist/components/environment/Tornado.d.ts.map +1 -0
- package/dist/components/environment/Tornado.js +762 -0
- package/dist/components/environment/index.d.ts +13 -0
- package/dist/components/environment/index.d.ts.map +1 -0
- package/dist/components/environment/index.js +7 -0
- package/dist/components/index.d.ts +10 -10
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +8 -6
- package/dist/components/land/LandPatch.d.ts +15 -0
- package/dist/components/land/LandPatch.d.ts.map +1 -0
- package/dist/components/land/LandPatch.js +170 -0
- package/dist/components/land/index.d.ts +3 -0
- package/dist/components/land/index.d.ts.map +1 -0
- package/dist/components/land/index.js +1 -0
- package/dist/components/space/Earth.d.ts +16 -0
- package/dist/components/space/Earth.d.ts.map +1 -0
- package/dist/components/space/Earth.js +75 -0
- package/dist/components/space/ShootingStar.d.ts +21 -0
- package/dist/components/space/ShootingStar.d.ts.map +1 -0
- package/dist/components/space/ShootingStar.js +101 -0
- package/dist/components/space/ShootingStars.d.ts +16 -0
- package/dist/components/space/ShootingStars.d.ts.map +1 -0
- package/dist/components/space/ShootingStars.js +71 -0
- package/dist/components/space/SolarSystem.d.ts +16 -0
- package/dist/components/space/SolarSystem.d.ts.map +1 -0
- package/dist/components/space/SolarSystem.js +141 -0
- package/dist/components/space/Stars.d.ts +20 -0
- package/dist/components/space/Stars.d.ts.map +1 -0
- package/dist/components/space/Stars.js +160 -0
- package/dist/components/space/index.d.ts +11 -0
- package/dist/components/space/index.d.ts.map +1 -0
- package/dist/components/space/index.js +8 -0
- package/dist/components/terrain/TerrainSurface.d.ts.map +1 -1
- package/dist/components/terrain/TerrainSurface.js +27 -3
- package/dist/components/terrain/types.d.ts +5 -1
- package/dist/components/terrain/types.d.ts.map +1 -1
- package/dist/components/text/BurnAwayText.d.ts +15 -0
- package/dist/components/text/BurnAwayText.d.ts.map +1 -0
- package/dist/components/text/BurnAwayText.js +4 -0
- package/dist/components/text/ChalkboardText.d.ts +15 -0
- package/dist/components/text/ChalkboardText.d.ts.map +1 -0
- package/dist/components/text/ChalkboardText.js +4 -0
- package/dist/components/text/ConstellationText.d.ts +15 -0
- package/dist/components/text/ConstellationText.d.ts.map +1 -0
- package/dist/components/text/ConstellationText.js +4 -0
- package/dist/components/text/EmbroideryText.d.ts +15 -0
- package/dist/components/text/EmbroideryText.d.ts.map +1 -0
- package/dist/components/text/EmbroideryText.js +4 -0
- package/dist/components/text/FourierSketchText.d.ts +15 -0
- package/dist/components/text/FourierSketchText.d.ts.map +1 -0
- package/dist/components/text/FourierSketchText.js +4 -0
- package/dist/components/text/FrostGrowthText.d.ts +15 -0
- package/dist/components/text/FrostGrowthText.d.ts.map +1 -0
- package/dist/components/text/FrostGrowthText.js +4 -0
- package/dist/components/text/HandwritingText.d.ts +15 -0
- package/dist/components/text/HandwritingText.d.ts.map +1 -0
- package/dist/components/text/HandwritingText.js +4 -0
- package/dist/components/text/InkBleedText.d.ts +15 -0
- package/dist/components/text/InkBleedText.d.ts.map +1 -0
- package/dist/components/text/InkBleedText.js +4 -0
- package/dist/components/text/LightPaintingText.d.ts +15 -0
- package/dist/components/text/LightPaintingText.d.ts.map +1 -0
- package/dist/components/text/LightPaintingText.js +4 -0
- package/dist/components/text/LiquidMetalText.d.ts +15 -0
- package/dist/components/text/LiquidMetalText.d.ts.map +1 -0
- package/dist/components/text/LiquidMetalText.js +4 -0
- package/dist/components/text/NeonTubeText.d.ts +15 -0
- package/dist/components/text/NeonTubeText.d.ts.map +1 -0
- package/dist/components/text/NeonTubeText.js +4 -0
- package/dist/components/text/PlasmaDischargeText.d.ts +15 -0
- package/dist/components/text/PlasmaDischargeText.d.ts.map +1 -0
- package/dist/components/text/PlasmaDischargeText.js +4 -0
- package/dist/components/text/TextObjectView.d.ts +12 -0
- package/dist/components/text/TextObjectView.d.ts.map +1 -0
- package/dist/components/text/TextObjectView.js +11 -0
- package/dist/components/text/engine/fieldkit.d.ts +24 -0
- package/dist/components/text/engine/fieldkit.d.ts.map +1 -0
- package/dist/components/text/engine/fieldkit.js +201 -0
- package/dist/components/text/engine/glyphs.d.ts +19 -0
- package/dist/components/text/engine/glyphs.d.ts.map +1 -0
- package/dist/components/text/engine/glyphs.js +269 -0
- package/dist/components/text/engine/looks/burnAway.d.ts +144 -0
- package/dist/components/text/engine/looks/burnAway.d.ts.map +1 -0
- package/dist/components/text/engine/looks/burnAway.js +593 -0
- package/dist/components/text/engine/looks/chalkboard.d.ts +135 -0
- package/dist/components/text/engine/looks/chalkboard.d.ts.map +1 -0
- package/dist/components/text/engine/looks/chalkboard.js +426 -0
- package/dist/components/text/engine/looks/constellation.d.ts +111 -0
- package/dist/components/text/engine/looks/constellation.d.ts.map +1 -0
- package/dist/components/text/engine/looks/constellation.js +496 -0
- package/dist/components/text/engine/looks/embroidery.d.ts +165 -0
- package/dist/components/text/engine/looks/embroidery.d.ts.map +1 -0
- package/dist/components/text/engine/looks/embroidery.js +645 -0
- package/dist/components/text/engine/looks/frostGrowth.d.ts +109 -0
- package/dist/components/text/engine/looks/frostGrowth.d.ts.map +1 -0
- package/dist/components/text/engine/looks/frostGrowth.js +727 -0
- package/dist/components/text/engine/looks/index.d.ts +2 -0
- package/dist/components/text/engine/looks/index.d.ts.map +1 -0
- package/dist/components/text/engine/looks/index.js +48 -0
- package/dist/components/text/engine/looks/inkBleed.d.ts +103 -0
- package/dist/components/text/engine/looks/inkBleed.d.ts.map +1 -0
- package/dist/components/text/engine/looks/inkBleed.js +590 -0
- package/dist/components/text/engine/looks/lightPainting.d.ts +132 -0
- package/dist/components/text/engine/looks/lightPainting.d.ts.map +1 -0
- package/dist/components/text/engine/looks/lightPainting.js +567 -0
- package/dist/components/text/engine/looks/liquidMetal.d.ts +135 -0
- package/dist/components/text/engine/looks/liquidMetal.d.ts.map +1 -0
- package/dist/components/text/engine/looks/liquidMetal.js +655 -0
- package/dist/components/text/engine/looks/plasmaDischarge.d.ts +126 -0
- package/dist/components/text/engine/looks/plasmaDischarge.d.ts.map +1 -0
- package/dist/components/text/engine/looks/plasmaDischarge.js +763 -0
- package/dist/components/text/engine/methods.d.ts +19 -0
- package/dist/components/text/engine/methods.d.ts.map +1 -0
- package/dist/components/text/engine/methods.js +126 -0
- package/dist/components/text/engine/playback.d.ts +40 -0
- package/dist/components/text/engine/playback.d.ts.map +1 -0
- package/dist/components/text/engine/playback.js +114 -0
- package/dist/components/text/engine/ribbon.d.ts +58 -0
- package/dist/components/text/engine/ribbon.d.ts.map +1 -0
- package/dist/components/text/engine/ribbon.js +250 -0
- package/dist/components/text/engine/variants.d.ts +159 -0
- package/dist/components/text/engine/variants.d.ts.map +1 -0
- package/dist/components/text/engine/variants.js +378 -0
- package/dist/components/text/fonts/architects-daughter.outline.d.ts +3 -0
- package/dist/components/text/fonts/architects-daughter.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/architects-daughter.outline.js +4 -0
- package/dist/components/text/fonts/architects-daughter.strokes.d.ts +3 -0
- package/dist/components/text/fonts/architects-daughter.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/architects-daughter.strokes.js +4 -0
- package/dist/components/text/fonts/caveat.outline.d.ts +3 -0
- package/dist/components/text/fonts/caveat.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/caveat.outline.js +4 -0
- package/dist/components/text/fonts/caveat.strokes.d.ts +3 -0
- package/dist/components/text/fonts/caveat.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/caveat.strokes.js +4 -0
- package/dist/components/text/fonts/courgette.outline.d.ts +3 -0
- package/dist/components/text/fonts/courgette.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/courgette.outline.js +4 -0
- package/dist/components/text/fonts/courgette.strokes.d.ts +3 -0
- package/dist/components/text/fonts/courgette.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/courgette.strokes.js +4 -0
- package/dist/components/text/fonts/dancing-script.outline.d.ts +3 -0
- package/dist/components/text/fonts/dancing-script.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/dancing-script.outline.js +4 -0
- package/dist/components/text/fonts/dancing-script.strokes.d.ts +3 -0
- package/dist/components/text/fonts/dancing-script.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/dancing-script.strokes.js +4 -0
- package/dist/components/text/fonts/gochi-hand.outline.d.ts +3 -0
- package/dist/components/text/fonts/gochi-hand.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/gochi-hand.outline.js +4 -0
- package/dist/components/text/fonts/gochi-hand.strokes.d.ts +3 -0
- package/dist/components/text/fonts/gochi-hand.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/gochi-hand.strokes.js +4 -0
- package/dist/components/text/fonts/handlee.outline.d.ts +3 -0
- package/dist/components/text/fonts/handlee.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/handlee.outline.js +4 -0
- package/dist/components/text/fonts/handlee.strokes.d.ts +3 -0
- package/dist/components/text/fonts/handlee.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/handlee.strokes.js +4 -0
- package/dist/components/text/fonts/index.d.ts +5 -0
- package/dist/components/text/fonts/index.d.ts.map +1 -0
- package/dist/components/text/fonts/index.js +44 -0
- package/dist/components/text/fonts/indie-flower.outline.d.ts +3 -0
- package/dist/components/text/fonts/indie-flower.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/indie-flower.outline.js +4 -0
- package/dist/components/text/fonts/indie-flower.strokes.d.ts +3 -0
- package/dist/components/text/fonts/indie-flower.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/indie-flower.strokes.js +4 -0
- package/dist/components/text/fonts/kalam.outline.d.ts +3 -0
- package/dist/components/text/fonts/kalam.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/kalam.outline.js +4 -0
- package/dist/components/text/fonts/kalam.strokes.d.ts +3 -0
- package/dist/components/text/fonts/kalam.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/kalam.strokes.js +4 -0
- package/dist/components/text/fonts/kaushan-script.outline.d.ts +3 -0
- package/dist/components/text/fonts/kaushan-script.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/kaushan-script.outline.js +4 -0
- package/dist/components/text/fonts/kaushan-script.strokes.d.ts +3 -0
- package/dist/components/text/fonts/kaushan-script.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/kaushan-script.strokes.js +4 -0
- package/dist/components/text/fonts/mynerve.outline.d.ts +3 -0
- package/dist/components/text/fonts/mynerve.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/mynerve.outline.js +4 -0
- package/dist/components/text/fonts/mynerve.strokes.d.ts +3 -0
- package/dist/components/text/fonts/mynerve.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/mynerve.strokes.js +4 -0
- package/dist/components/text/fonts/nanum-pen-script.outline.d.ts +3 -0
- package/dist/components/text/fonts/nanum-pen-script.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/nanum-pen-script.outline.js +4 -0
- package/dist/components/text/fonts/nanum-pen-script.strokes.d.ts +3 -0
- package/dist/components/text/fonts/nanum-pen-script.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/nanum-pen-script.strokes.js +4 -0
- package/dist/components/text/fonts/pacifico.outline.d.ts +3 -0
- package/dist/components/text/fonts/pacifico.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/pacifico.outline.js +4 -0
- package/dist/components/text/fonts/pacifico.strokes.d.ts +3 -0
- package/dist/components/text/fonts/pacifico.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/pacifico.strokes.js +4 -0
- package/dist/components/text/fonts/patrick-hand.outline.d.ts +3 -0
- package/dist/components/text/fonts/patrick-hand.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/patrick-hand.outline.js +4 -0
- package/dist/components/text/fonts/patrick-hand.strokes.d.ts +3 -0
- package/dist/components/text/fonts/patrick-hand.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/patrick-hand.strokes.js +4 -0
- package/dist/components/text/fonts/poppins.outline.d.ts +3 -0
- package/dist/components/text/fonts/poppins.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/poppins.outline.js +4 -0
- package/dist/components/text/fonts/poppins.strokes.d.ts +3 -0
- package/dist/components/text/fonts/poppins.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/poppins.strokes.js +4 -0
- package/dist/components/text/fonts/satisfy.outline.d.ts +3 -0
- package/dist/components/text/fonts/satisfy.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/satisfy.outline.js +4 -0
- package/dist/components/text/fonts/satisfy.strokes.d.ts +3 -0
- package/dist/components/text/fonts/satisfy.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/satisfy.strokes.js +4 -0
- package/dist/components/text/fonts/sriracha.outline.d.ts +3 -0
- package/dist/components/text/fonts/sriracha.outline.d.ts.map +1 -0
- package/dist/components/text/fonts/sriracha.outline.js +4 -0
- package/dist/components/text/fonts/sriracha.strokes.d.ts +3 -0
- package/dist/components/text/fonts/sriracha.strokes.d.ts.map +1 -0
- package/dist/components/text/fonts/sriracha.strokes.js +4 -0
- package/dist/components/text/index.d.ts +27 -0
- package/dist/components/text/index.d.ts.map +1 -0
- package/dist/components/text/index.js +13 -0
- package/dist/components/text/useTextObject.d.ts +21 -0
- package/dist/components/text/useTextObject.d.ts.map +1 -0
- package/dist/components/text/useTextObject.js +118 -0
- package/dist/components/water/OceanSurface.d.ts.map +1 -1
- package/dist/components/water/OceanSurface.js +3 -1
- package/dist/components/water/WaterBody.d.ts.map +1 -1
- package/dist/components/water/WaterBody.js +3 -1
- package/dist/components/water/types.d.ts +5 -1
- package/dist/components/water/types.d.ts.map +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +4 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useCloudSun.d.ts +9 -4
- package/dist/hooks/useCloudSun.d.ts.map +1 -1
- package/dist/hooks/useCloudSun.js +17 -7
- package/dist/hooks/useConfigLive.d.ts +3 -2
- package/dist/hooks/useConfigLive.d.ts.map +1 -1
- package/dist/hooks/useContinuousEffects.d.ts.map +1 -1
- package/dist/hooks/useContinuousEffects.js +4 -10
- package/dist/hooks/useEnvironmentProbe.d.ts +3 -22
- package/dist/hooks/useEnvironmentProbe.d.ts.map +1 -1
- package/dist/hooks/useEnvironmentProbe.js +47 -8
- package/dist/hooks/useGridSurface.d.ts +3 -10
- package/dist/hooks/useGridSurface.d.ts.map +1 -1
- package/dist/hooks/useGridSurface.js +5 -31
- package/dist/hooks/useInteraction.d.ts.map +1 -1
- package/dist/hooks/useInteraction.js +19 -72
- package/dist/hooks/useLightConfig.d.ts +2 -1
- package/dist/hooks/useLightConfig.d.ts.map +1 -1
- package/dist/hooks/useOceanMaterial.d.ts +6 -2
- package/dist/hooks/useOceanMaterial.d.ts.map +1 -1
- package/dist/hooks/useOceanMaterial.js +37 -2
- package/dist/hooks/useSkyLive.d.ts +23 -0
- package/dist/hooks/useSkyLive.d.ts.map +1 -0
- package/dist/hooks/useSkyLive.js +30 -0
- package/dist/hooks/useSkyUniforms.d.ts.map +1 -1
- package/dist/hooks/useSkyUniforms.js +2 -10
- package/dist/hooks/useTerrainLive.d.ts +3 -1
- package/dist/hooks/useTerrainLive.d.ts.map +1 -1
- package/dist/hooks/useTerrainTextures.d.ts +38 -0
- package/dist/hooks/useTerrainTextures.d.ts.map +1 -0
- package/dist/hooks/useTerrainTextures.js +149 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/operations/catalogue/blastOff.d.ts +3 -0
- package/dist/operations/catalogue/blastOff.d.ts.map +1 -0
- package/dist/operations/catalogue/blastOff.js +118 -0
- package/dist/operations/catalogue/bounce.d.ts +3 -0
- package/dist/operations/catalogue/bounce.d.ts.map +1 -0
- package/dist/operations/catalogue/bounce.js +34 -0
- package/dist/operations/catalogue/curlSmoke.d.ts.map +1 -1
- package/dist/operations/catalogue/curlSmoke.js +3 -1
- package/dist/operations/catalogue/dissolve.d.ts.map +1 -1
- package/dist/operations/catalogue/dissolve.js +2 -1
- package/dist/operations/catalogue/driftUp.d.ts +3 -0
- package/dist/operations/catalogue/driftUp.d.ts.map +1 -0
- package/dist/operations/catalogue/driftUp.js +57 -0
- package/dist/operations/catalogue/emberAsh.d.ts.map +1 -1
- package/dist/operations/catalogue/emberAsh.js +2 -1
- package/dist/operations/catalogue/flip.d.ts.map +1 -1
- package/dist/operations/catalogue/flip.js +19 -9
- package/dist/operations/catalogue/float.d.ts +3 -0
- package/dist/operations/catalogue/float.d.ts.map +1 -0
- package/dist/operations/catalogue/float.js +39 -0
- package/dist/operations/catalogue/flyBy.d.ts +3 -0
- package/dist/operations/catalogue/flyBy.d.ts.map +1 -0
- package/dist/operations/catalogue/flyBy.js +79 -0
- package/dist/operations/catalogue/frost.d.ts.map +1 -1
- package/dist/operations/catalogue/frost.js +10 -3
- package/dist/operations/catalogue/grow.d.ts +3 -0
- package/dist/operations/catalogue/grow.d.ts.map +1 -0
- package/dist/operations/catalogue/grow.js +19 -0
- package/dist/operations/catalogue/hologram.d.ts.map +1 -1
- package/dist/operations/catalogue/hologram.js +11 -5
- package/dist/operations/catalogue/jelly.d.ts.map +1 -1
- package/dist/operations/catalogue/jelly.js +18 -8
- package/dist/operations/catalogue/knockAway.d.ts +3 -0
- package/dist/operations/catalogue/knockAway.d.ts.map +1 -0
- package/dist/operations/catalogue/knockAway.js +74 -0
- package/dist/operations/catalogue/leafFall.d.ts +3 -0
- package/dist/operations/catalogue/leafFall.d.ts.map +1 -0
- package/dist/operations/catalogue/leafFall.js +74 -0
- package/dist/operations/catalogue/lidarScan.d.ts.map +1 -1
- package/dist/operations/catalogue/lidarScan.js +4 -1
- package/dist/operations/catalogue/metalize.d.ts.map +1 -1
- package/dist/operations/catalogue/metalize.js +8 -2
- package/dist/operations/catalogue/motionTrail.d.ts +6 -0
- package/dist/operations/catalogue/motionTrail.d.ts.map +1 -0
- package/dist/operations/catalogue/motionTrail.js +221 -0
- package/dist/operations/catalogue/petrify.d.ts.map +1 -1
- package/dist/operations/catalogue/petrify.js +9 -3
- package/dist/operations/catalogue/physicalExit.d.ts +55 -0
- package/dist/operations/catalogue/physicalExit.d.ts.map +1 -0
- package/dist/operations/catalogue/physicalExit.js +165 -0
- package/dist/operations/catalogue/physicalHeld.d.ts +41 -0
- package/dist/operations/catalogue/physicalHeld.d.ts.map +1 -0
- package/dist/operations/catalogue/physicalHeld.js +78 -0
- package/dist/operations/catalogue/physicalMix.d.ts +45 -0
- package/dist/operations/catalogue/physicalMix.d.ts.map +1 -0
- package/dist/operations/catalogue/physicalMix.js +144 -0
- package/dist/operations/catalogue/pop.d.ts +3 -0
- package/dist/operations/catalogue/pop.d.ts.map +1 -0
- package/dist/operations/catalogue/pop.js +44 -0
- package/dist/operations/catalogue/print3d.d.ts.map +1 -1
- package/dist/operations/catalogue/print3d.js +5 -1
- package/dist/operations/catalogue/pulse.d.ts +3 -0
- package/dist/operations/catalogue/pulse.d.ts.map +1 -0
- package/dist/operations/catalogue/pulse.js +29 -0
- package/dist/operations/catalogue/restPose.d.ts +5 -7
- package/dist/operations/catalogue/restPose.d.ts.map +1 -1
- package/dist/operations/catalogue/restPose.js +18 -48
- package/dist/operations/catalogue/rotate.d.ts +3 -0
- package/dist/operations/catalogue/rotate.d.ts.map +1 -0
- package/dist/operations/catalogue/rotate.js +49 -0
- package/dist/operations/catalogue/shake.d.ts +3 -0
- package/dist/operations/catalogue/shake.d.ts.map +1 -0
- package/dist/operations/catalogue/shake.js +31 -0
- package/dist/operations/catalogue/shatter.d.ts.map +1 -1
- package/dist/operations/catalogue/shatter.js +5 -1
- package/dist/operations/catalogue/slam.d.ts +3 -0
- package/dist/operations/catalogue/slam.d.ts.map +1 -0
- package/dist/operations/catalogue/slam.js +89 -0
- package/dist/operations/catalogue/slingshot.d.ts +3 -0
- package/dist/operations/catalogue/slingshot.d.ts.map +1 -0
- package/dist/operations/catalogue/slingshot.js +88 -0
- package/dist/operations/catalogue/spin.d.ts.map +1 -1
- package/dist/operations/catalogue/spin.js +24 -13
- package/dist/operations/catalogue/sway.d.ts +3 -0
- package/dist/operations/catalogue/sway.d.ts.map +1 -0
- package/dist/operations/catalogue/sway.js +23 -0
- package/dist/operations/catalogue/swirl.d.ts.map +1 -1
- package/dist/operations/catalogue/swirl.js +6 -5
- package/dist/operations/catalogue/trailCore.d.ts +89 -0
- package/dist/operations/catalogue/trailCore.d.ts.map +1 -0
- package/dist/operations/catalogue/trailCore.js +190 -0
- package/dist/operations/catalogue/trailGhosts.d.ts +5 -0
- package/dist/operations/catalogue/trailGhosts.d.ts.map +1 -0
- package/dist/operations/catalogue/trailGhosts.js +179 -0
- package/dist/operations/catalogue/trailStampStyles.d.ts +11 -0
- package/dist/operations/catalogue/trailStampStyles.d.ts.map +1 -0
- package/dist/operations/catalogue/trailStampStyles.js +479 -0
- package/dist/operations/catalogue/trailStamps.d.ts +57 -0
- package/dist/operations/catalogue/trailStamps.d.ts.map +1 -0
- package/dist/operations/catalogue/trailStamps.js +349 -0
- package/dist/operations/catalogue/trailStreaks.d.ts +3 -0
- package/dist/operations/catalogue/trailStreaks.d.ts.map +1 -0
- package/dist/operations/catalogue/trailStreaks.js +147 -0
- package/dist/operations/catalogue/transitionField.d.ts +30 -0
- package/dist/operations/catalogue/transitionField.d.ts.map +1 -1
- package/dist/operations/catalogue/transitionField.js +21 -0
- package/dist/operations/catalogue/turnAway.d.ts +3 -0
- package/dist/operations/catalogue/turnAway.d.ts.map +1 -0
- package/dist/operations/catalogue/turnAway.js +54 -0
- package/dist/operations/catalogue/vortexDrain.d.ts +3 -0
- package/dist/operations/catalogue/vortexDrain.d.ts.map +1 -0
- package/dist/operations/catalogue/vortexDrain.js +68 -0
- package/dist/operations/catalogue/warp.d.ts +3 -0
- package/dist/operations/catalogue/warp.d.ts.map +1 -0
- package/dist/operations/catalogue/warp.js +73 -0
- package/dist/operations/catalogue/whoosh.d.ts +3 -0
- package/dist/operations/catalogue/whoosh.d.ts.map +1 -0
- package/dist/operations/catalogue/whoosh.js +84 -0
- package/dist/operations/catalogue/wobble.d.ts +3 -0
- package/dist/operations/catalogue/wobble.d.ts.map +1 -0
- package/dist/operations/catalogue/wobble.js +23 -0
- package/dist/operations/clipPreview.d.ts +3 -0
- package/dist/operations/clipPreview.d.ts.map +1 -0
- package/dist/operations/clipPreview.js +20 -0
- package/dist/operations/groupFanout.d.ts +96 -0
- package/dist/operations/groupFanout.d.ts.map +1 -0
- package/dist/operations/groupFanout.js +365 -0
- package/dist/operations/groups.d.ts +20 -0
- package/dist/operations/groups.d.ts.map +1 -0
- package/dist/operations/groups.js +66 -0
- package/dist/operations/index.d.ts +5 -2
- package/dist/operations/index.d.ts.map +1 -1
- package/dist/operations/index.js +5 -2
- package/dist/operations/objectEffects.d.ts +161 -6
- package/dist/operations/objectEffects.d.ts.map +1 -1
- package/dist/operations/objectEffects.js +1091 -17
- package/dist/operations/registry.d.ts.map +1 -1
- package/dist/operations/registry.js +24 -2
- package/dist/operations/runtime.d.ts +57 -2
- package/dist/operations/runtime.d.ts.map +1 -1
- package/dist/operations/runtime.js +161 -18
- package/dist/operations/types.d.ts +60 -3
- package/dist/operations/types.d.ts.map +1 -1
- package/dist/operations/types.js +5 -1
- package/dist/operations/useObjectEffectLayers.d.ts +2 -2
- package/dist/operations/useObjectEffectLayers.d.ts.map +1 -1
- package/dist/operations/useObjectEffectLayers.js +31 -10
- package/dist/operations/usePresentedVisibility.d.ts +10 -0
- package/dist/operations/usePresentedVisibility.d.ts.map +1 -0
- package/dist/operations/usePresentedVisibility.js +53 -0
- package/dist/presets/terrainBiomes.d.ts +67 -0
- package/dist/presets/terrainBiomes.d.ts.map +1 -0
- package/dist/presets/terrainBiomes.js +294 -0
- package/dist/presets/terrainPresets.d.ts +6 -0
- package/dist/presets/terrainPresets.d.ts.map +1 -1
- package/dist/presets/terrainPresets.js +26 -38
- package/dist/shaders/glsl/oceanCore.glsl.d.ts +2 -2
- package/dist/shaders/glsl/oceanCore.glsl.d.ts.map +1 -1
- package/dist/shaders/glsl/oceanCore.glsl.js +17 -0
- package/dist/shaders/glsl/surfaceCore.glsl.d.ts +21 -0
- package/dist/shaders/glsl/surfaceCore.glsl.d.ts.map +1 -0
- package/dist/shaders/glsl/surfaceCore.glsl.js +120 -0
- package/dist/shaders/glsl/terrainCore.glsl.d.ts +16 -3
- package/dist/shaders/glsl/terrainCore.glsl.d.ts.map +1 -1
- package/dist/shaders/glsl/terrainCore.glsl.js +266 -20
- package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts +2 -0
- package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts.map +1 -1
- package/dist/shaders/ocean/OceanSurfaceMaterial.js +3 -0
- package/dist/shaders/terrain/TerrainMaterial.d.ts +17 -0
- package/dist/shaders/terrain/TerrainMaterial.d.ts.map +1 -1
- package/dist/shaders/terrain/TerrainMaterial.js +107 -8
- package/dist/triggers/engine.d.ts +44 -0
- package/dist/triggers/engine.d.ts.map +1 -0
- package/dist/triggers/engine.js +165 -0
- package/dist/triggers/hosts/actions.d.ts +8 -0
- package/dist/triggers/hosts/actions.d.ts.map +1 -0
- package/dist/triggers/hosts/actions.js +22 -0
- package/dist/triggers/hosts/interactions.d.ts +6 -0
- package/dist/triggers/hosts/interactions.d.ts.map +1 -0
- package/dist/triggers/hosts/interactions.js +4 -0
- package/dist/triggers/hosts/timelineCues.d.ts +2 -0
- package/dist/triggers/hosts/timelineCues.d.ts.map +1 -0
- package/dist/triggers/hosts/timelineCues.js +22 -0
- package/dist/triggers/index.d.ts +13 -0
- package/dist/triggers/index.d.ts.map +1 -0
- package/dist/triggers/index.js +9 -0
- package/dist/triggers/kinds/action.d.ts +2 -0
- package/dist/triggers/kinds/action.d.ts.map +1 -0
- package/dist/triggers/kinds/action.js +31 -0
- package/dist/triggers/kinds/animations.d.ts +2 -0
- package/dist/triggers/kinds/animations.d.ts.map +1 -0
- package/dist/triggers/kinds/animations.js +75 -0
- package/dist/triggers/kinds/effects.d.ts +2 -0
- package/dist/triggers/kinds/effects.d.ts.map +1 -0
- package/dist/triggers/kinds/effects.js +27 -0
- package/dist/triggers/kinds/index.d.ts +4 -0
- package/dist/triggers/kinds/index.d.ts.map +1 -0
- package/dist/triggers/kinds/index.js +4 -0
- package/dist/triggers/log.d.ts +21 -0
- package/dist/triggers/log.d.ts.map +1 -0
- package/dist/triggers/log.js +43 -0
- package/dist/triggers/readiness.d.ts +40 -0
- package/dist/triggers/readiness.d.ts.map +1 -0
- package/dist/triggers/readiness.js +158 -0
- package/dist/triggers/registry.d.ts +41 -0
- package/dist/triggers/registry.d.ts.map +1 -0
- package/dist/triggers/registry.js +7 -0
- package/dist/types/gridConfigs.d.ts +18 -23
- package/dist/types/gridConfigs.d.ts.map +1 -1
- package/dist/ui/UiAnchorUpdater.d.ts +10 -0
- package/dist/ui/UiAnchorUpdater.d.ts.map +1 -0
- package/dist/ui/UiAnchorUpdater.js +111 -0
- package/dist/ui/UiLayers.d.ts +20 -0
- package/dist/ui/UiLayers.d.ts.map +1 -0
- package/dist/ui/UiLayers.js +57 -0
- package/dist/ui/index.d.ts +9 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +6 -0
- package/dist/ui/uiAnchors.d.ts +21 -0
- package/dist/ui/uiAnchors.d.ts.map +1 -0
- package/dist/ui/uiAnchors.js +22 -0
- package/dist/ui/uiBaseStyles.d.ts +2 -0
- package/dist/ui/uiBaseStyles.d.ts.map +1 -0
- package/dist/ui/uiBaseStyles.js +100 -0
- package/dist/ui/uiBinder.d.ts +30 -0
- package/dist/ui/uiBinder.d.ts.map +1 -0
- package/dist/ui/uiBinder.js +344 -0
- package/dist/utils/configAnimations.d.ts.map +1 -1
- package/dist/utils/configAnimations.js +5 -1
- package/dist/utils/gridConfig.d.ts +1 -1
- package/dist/utils/gridConfig.d.ts.map +1 -1
- package/dist/utils/gridConfig.js +1 -1
- package/dist/utils/landPatch.d.ts +33 -0
- package/dist/utils/landPatch.d.ts.map +1 -0
- package/dist/utils/landPatch.js +114 -0
- package/dist/utils/renderedSky.d.ts +32 -0
- package/dist/utils/renderedSky.d.ts.map +1 -0
- package/dist/utils/renderedSky.js +57 -0
- package/dist/utils/skyMoon.d.ts +35 -0
- package/dist/utils/skyMoon.d.ts.map +1 -0
- package/dist/utils/skyMoon.js +41 -0
- package/dist/utils/terrainHeight.d.ts +4 -0
- package/dist/utils/terrainHeight.d.ts.map +1 -0
- package/dist/utils/terrainHeight.js +150 -0
- package/dist/utils/terrainTextureResolver.d.ts +18 -0
- package/dist/utils/terrainTextureResolver.d.ts.map +1 -0
- package/dist/utils/terrainTextureResolver.js +17 -0
- package/dist/utils/terrainUniforms.d.ts +17 -0
- package/dist/utils/terrainUniforms.d.ts.map +1 -1
- package/dist/utils/terrainUniforms.js +84 -0
- package/dist/utils/textureArrays.d.ts +29 -0
- package/dist/utils/textureArrays.d.ts.map +1 -0
- package/dist/utils/textureArrays.js +140 -0
- package/package.json +2 -2
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { findNodesByName } from '@3driseai/3drise-core';
|
|
2
|
+
import { GroupFanout, isFanRow } from './groupFanout.js';
|
|
2
3
|
import { getOperation, resolveParams } from './registry.js';
|
|
3
|
-
import { applyOperation, forceRevert, runOf } from './runtime.js';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import { applyOperation, forceRevert, registerAddedEffects, runOf, warmOperation } from './runtime.js';
|
|
5
|
+
import { periodicEase } from './catalogue/physicalHeld.js';
|
|
6
|
+
/** An operation can be an object effect (one-shots too: they have no way back, and play with loop). */
|
|
7
|
+
export const isObjectOperation = (def) => !!def && def.usableIn.includes('object');
|
|
6
8
|
/**
|
|
7
9
|
* The effects that actually run: on, known, usable on objects, one per operation,
|
|
8
10
|
* and one of each stack (the first wins).
|
|
@@ -27,17 +29,133 @@ export function runningObjectEffects(effects) {
|
|
|
27
29
|
}
|
|
28
30
|
return out;
|
|
29
31
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
export function effectPresence(def, effect, follows, inStep = false) {
|
|
33
|
+
if (!follows)
|
|
34
|
+
return 'decorate';
|
|
35
|
+
// a step's effect is a look that takes turns: only Base effects are entrances / exits
|
|
36
|
+
if (def.presence === 'vanish')
|
|
37
|
+
return inStep ? 'decorate' : 'vanish';
|
|
38
|
+
// Disappear is the user's choice: on, the effect takes the object away — an entrance and an exit
|
|
39
|
+
const spec = def.params?.disappear;
|
|
40
|
+
if (spec) {
|
|
41
|
+
const v = { ...(def.objectParams ?? {}), ...(effect.params ?? {}) }.disappear ?? spec.default;
|
|
42
|
+
if (v === true)
|
|
43
|
+
return inStep ? 'decorate' : 'vanish';
|
|
44
|
+
}
|
|
45
|
+
return def.presence === 'paint' ? 'paint' : 'decorate';
|
|
46
|
+
}
|
|
47
|
+
/** An object effect's parameters: the operation's defaults, the object defaults, then its own values. */
|
|
48
|
+
export const objectEffectParams = (def, effect, follows = false, inStep = false) => ({
|
|
49
|
+
// an object effect starts from the operation's object defaults (objectParams: a hologram that stays),
|
|
50
|
+
// and the user's own values go on top — so `disappear` is theirs to switch on
|
|
51
|
+
...resolveParams(def, { ...(def.objectParams ?? {}), ...(effect.params ?? {}) }),
|
|
52
|
+
// a take-over that follows visibility draws the object only where it has painted it
|
|
53
|
+
...(effectPresence(def, effect, follows, inStep) === 'paint' ? { __reveal: true } : {}),
|
|
54
|
+
});
|
|
55
|
+
/** An effect's playback with the defaults filled in. */
|
|
56
|
+
export const playbackOf = (effect) => ({
|
|
57
|
+
autoplay: effect.playback?.autoplay !== false,
|
|
58
|
+
reverse: !!effect.playback?.reverse,
|
|
59
|
+
loop: !!effect.playback?.loop,
|
|
60
|
+
yoyo: !!effect.playback?.yoyo,
|
|
61
|
+
});
|
|
62
|
+
const playbackKey = (pb) => `${+pb.autoplay}${+pb.reverse}${+pb.loop}${+pb.yoyo}`;
|
|
63
|
+
/** What makes a row "another effect" when it changes: its playback, and how it follows visibility. */
|
|
64
|
+
const rowKey = (def, e, follows, inStep) => playbackKey(playbackOf(e)) + (follows ? 'v' : '') + (def ? effectPresence(def, e, follows, inStep) : '');
|
|
65
|
+
/** An object's effects controller; `create` makes one for an object that has no effects of its own yet. */
|
|
66
|
+
export function objectEffectsControllerFor(root, create = false) {
|
|
67
|
+
return controllers.get(root) ?? (create ? new ObjectEffectsController(root) : undefined);
|
|
68
|
+
}
|
|
69
|
+
// effects added by interactions and actions are run by the object's controller (see runtime.runEffect)
|
|
70
|
+
registerAddedEffects({
|
|
71
|
+
add: (root, key, effect) => !!objectEffectsControllerFor(root, true)?.addEffect(key, effect),
|
|
72
|
+
remove: (root, key) => !!controllers.get(root)?.removeEffect(key),
|
|
73
|
+
has: (root, key) => !!controllers.get(root)?.hasEffect(key),
|
|
74
|
+
applyClip: (root, key, clip, parts) => !!objectEffectsControllerFor(root, true)?.applyClip(key, clip, parts),
|
|
75
|
+
removeClip: (root, key) => !!controllers.get(root)?.removeClip(key),
|
|
76
|
+
hasClip: (root, key) => !!controllers.get(root)?.hasClip(key),
|
|
77
|
+
});
|
|
78
|
+
/** The step of an object's effect steps that is on now (-1: none) — for the editor. */
|
|
79
|
+
export function currentEffectStep(root) {
|
|
80
|
+
return (root && controllers.get(root)?.step) ?? -1;
|
|
81
|
+
}
|
|
82
|
+
/** An object's own effect clip follows its visibility (`visible`) and has an effect that is on. */
|
|
83
|
+
export const clipFollowsVisibility = (clip) => !!clip?.visible && (!!clip.effects?.some(e => e?.enabled) || !!clip.steps?.some(s => s?.effects?.some(e => e && e.enabled !== false)));
|
|
84
|
+
/**
|
|
85
|
+
* The object was shown or hidden: its visibility effects play in, or play out.
|
|
86
|
+
* Returns a promise (null = nothing to wait for) that resolves
|
|
87
|
+
* shown when the effects are ready and the object is drawn (its entrance is starting)
|
|
88
|
+
* hidden when they have played out and the object is no longer drawn
|
|
89
|
+
* The controller sets the group's `visible` itself at those two moments.
|
|
90
|
+
*/
|
|
91
|
+
export function setObjectEffectsVisible(root, visible) {
|
|
92
|
+
return (root && controllers.get(root)?.setVisible(visible)) || null;
|
|
93
|
+
}
|
|
94
|
+
/** Plays in once and holds — what an object effect does with no playback set. */
|
|
95
|
+
const isPlain = (pb) => !pb.reverse && !pb.loop && !pb.yoyo;
|
|
96
|
+
/** The controller of each object that has effects, by its group — for playing an effect from outside. */
|
|
97
|
+
const controllers = new WeakMap();
|
|
98
|
+
/**
|
|
99
|
+
* Play one of an object's effects from its start, with its playback settings
|
|
100
|
+
* (the editor's ▶; an effect with autoplay off starts this way). False when the
|
|
101
|
+
* object or the effect is not there.
|
|
102
|
+
*/
|
|
103
|
+
export function playObjectEffect(root, effectId) {
|
|
104
|
+
return !!root && !!controllers.get(root)?.play(effectId);
|
|
105
|
+
}
|
|
32
106
|
const namesKey = (e) => (e.meshNames ?? []).join('|');
|
|
107
|
+
const seconds = (v, fallback) => (Number.isFinite(Number(v)) && Number(v) >= 0 ? Number(v) : fallback);
|
|
108
|
+
export const STEP_IN = 1;
|
|
109
|
+
export const STEP_HOLD = 1;
|
|
110
|
+
/** What makes a step sequence "another sequence" (it restarts): its structure and timing — not the effects' own values. */
|
|
111
|
+
const stepsKeyOf = (cfg) => (cfg?.steps?.length
|
|
112
|
+
? JSON.stringify([!!cfg.loop, !!cfg.yoyo, cfg.steps.map(s => [s.id, s.in, s.hold, !!s.playOut, (s.effects ?? []).map(e => [e.id, e.operation, e.enabled !== false, namesKey(e)])])])
|
|
113
|
+
: '');
|
|
114
|
+
/** A step's effect as a row of the running list: a look takes the step's `in` as its duration, a motion runs while the step is on. */
|
|
115
|
+
function stepRow(step, e, on, prefix = '', parts) {
|
|
116
|
+
const def = getOperation(e.operation);
|
|
117
|
+
const look = !!def?.revert && !def.periodic;
|
|
118
|
+
return {
|
|
119
|
+
id: `${prefix}${step.id}:${e.id}`, operation: e.operation, enabled: on && e.enabled !== false, meshNames: parts?.length ? parts : e.meshNames,
|
|
120
|
+
params: look ? { ...(e.params ?? {}), duration: seconds(step.in, STEP_IN) } : e.params,
|
|
121
|
+
...(look ? {} : { playback: { loop: true } }),
|
|
122
|
+
...(e.scope ? { scope: e.scope } : {}),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
33
125
|
export class ObjectEffectsController {
|
|
34
126
|
root;
|
|
35
127
|
running = new Map(); // effect id →
|
|
128
|
+
/** Effects playing out (removed / switched off): their op → when they are gone. */
|
|
129
|
+
leaving = new Set();
|
|
36
130
|
effects = [];
|
|
37
131
|
refreshing = null;
|
|
38
132
|
disposed = false;
|
|
133
|
+
/** The object is shown — visibility effects wait while it is not. */
|
|
134
|
+
shown = true;
|
|
135
|
+
/** The object is on screen: it stays drawn while its effects play out, and is not yet drawn while they get ready. */
|
|
136
|
+
drawn = true;
|
|
137
|
+
visRun = 0;
|
|
138
|
+
/** The object's own list (always on) and its steps; `effects` is what runs: the two laid together. */
|
|
139
|
+
own = { key: '', prefix: '', effects: [], cfg: null, stepsKey: '', index: 0, dir: 1, run: 0 };
|
|
140
|
+
/** Clips applied from outside (key → run), in the order they were applied. */
|
|
141
|
+
clips = new Map();
|
|
142
|
+
/** The object's own steps wait while an applied clip has steps. */
|
|
143
|
+
ownPaused = false;
|
|
144
|
+
/** Effects added by interactions / actions (key → row; disabled while it plays out). */
|
|
145
|
+
added = new Map();
|
|
146
|
+
/** The object's own rows (Base and steps) as last composed: id → it is a step's. */
|
|
147
|
+
ownRows = new Map();
|
|
148
|
+
/** A group: its visual effects and physical 'each' effects go to the children (see ./groupFanout.ts). */
|
|
149
|
+
fan = null;
|
|
150
|
+
spread = {};
|
|
151
|
+
/** Added effects that follow visibility: a group's effects on this child, when the group's follow it. */
|
|
152
|
+
addedFollows = new Set();
|
|
39
153
|
constructor(root) {
|
|
40
154
|
this.root = root;
|
|
155
|
+
controllers.set(root, this);
|
|
156
|
+
// a group never draws an effect itself: its visual / 'each' effects — its own, and those triggered on it — go to its children
|
|
157
|
+
if (root.userData?.objectType === 'group')
|
|
158
|
+
this.fan = new GroupFanout(root, (r, create) => objectEffectsControllerFor(r, create));
|
|
41
159
|
}
|
|
42
160
|
/** The object's targets for an effect: the object, or its named nodes. */
|
|
43
161
|
targetsOf(e) {
|
|
@@ -53,11 +171,29 @@ export class ObjectEffectsController {
|
|
|
53
171
|
applyOperation(def, t, params, this.root, { bare: true });
|
|
54
172
|
}
|
|
55
173
|
off(r, instant) {
|
|
174
|
+
if (r.cycle) {
|
|
175
|
+
r.cycle.cancelled = true;
|
|
176
|
+
r.cycle.wake?.();
|
|
177
|
+
}
|
|
178
|
+
r.cycle = undefined;
|
|
179
|
+
r.phase = undefined;
|
|
180
|
+
if (r.wipe) {
|
|
181
|
+
r.wipe.cancelled = true;
|
|
182
|
+
r.wipe = undefined;
|
|
183
|
+
}
|
|
56
184
|
const def = getOperation(r.op);
|
|
57
|
-
if (!def)
|
|
185
|
+
if (!def || !r.started)
|
|
58
186
|
return;
|
|
187
|
+
// a one-shot has no way back: at once = stop its move where it is and put the object back
|
|
188
|
+
if (!def.revert) {
|
|
189
|
+
if (instant)
|
|
190
|
+
for (const t of r.targets)
|
|
191
|
+
def.cancel?.(t);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
59
194
|
// with its own parameters — it may have gone on at once (load / edit), but goes off with its transition
|
|
60
|
-
|
|
195
|
+
// (a take-over switched off on an object that stays: it gives the object back, it does not take it away)
|
|
196
|
+
const params = instant ? { ...r.params, duration: 0 } : r.kind === 'paint' ? { ...r.params, __reveal: false } : r.params;
|
|
61
197
|
for (const t of r.targets)
|
|
62
198
|
forceRevert(def, t, params);
|
|
63
199
|
}
|
|
@@ -65,34 +201,955 @@ export class ObjectEffectsController {
|
|
|
65
201
|
* Bring what runs in line with `effects`.
|
|
66
202
|
* animate switching an effect on / off plays its transition (studio, actions)
|
|
67
203
|
* instant everything lands in its end state at once (scene load)
|
|
68
|
-
* A changed parameter always lands at once.
|
|
204
|
+
* A changed parameter always lands at once. A row switched to another
|
|
205
|
+
* operation clears the old one at once, then plays the new one in from the
|
|
206
|
+
* original object.
|
|
69
207
|
*/
|
|
70
|
-
sync(effects, mode) {
|
|
208
|
+
sync(effects, mode, steps, parts, follows = false, group) {
|
|
71
209
|
if (this.disposed)
|
|
72
210
|
return;
|
|
211
|
+
// a group (`group` = its spread): the rows that go to the children are handed out by syncList
|
|
212
|
+
if (group) {
|
|
213
|
+
this.fan ??= new GroupFanout(this.root, (r, create) => objectEffectsControllerFor(r, create));
|
|
214
|
+
this.spread = group;
|
|
215
|
+
}
|
|
216
|
+
else if (this.fan && this.root.userData?.objectType !== 'group') {
|
|
217
|
+
this.fan.dispose();
|
|
218
|
+
this.fan = null;
|
|
219
|
+
}
|
|
220
|
+
const c = this.own;
|
|
221
|
+
c.effects = effects ?? [];
|
|
222
|
+
c.follows = follows;
|
|
223
|
+
c.parts = parts?.length ? parts : undefined;
|
|
224
|
+
const key = stepsKeyOf(steps);
|
|
225
|
+
c.cfg = key ? steps : null;
|
|
226
|
+
if (key !== c.stepsKey) { // another sequence: from its first step
|
|
227
|
+
c.stepsKey = key;
|
|
228
|
+
c.index = 0;
|
|
229
|
+
c.dir = 1;
|
|
230
|
+
if (!this.ownPaused)
|
|
231
|
+
this.scheduleStep(c);
|
|
232
|
+
}
|
|
233
|
+
this.syncList(this.compose(), mode);
|
|
234
|
+
}
|
|
235
|
+
/** A clip's rows: the step that is on, its always-on effects, and the steps that wait (listed, off). */
|
|
236
|
+
rowsOf(c) {
|
|
237
|
+
const on = [], waiting = [];
|
|
238
|
+
const stepsOn = !c.off && !(c === this.own && this.ownPaused);
|
|
239
|
+
c.cfg?.steps.forEach((s, i) => {
|
|
240
|
+
for (const e of s.effects ?? []) {
|
|
241
|
+
const row = stepRow(s, e, stepsOn && i === c.index, c.prefix, c.parts);
|
|
242
|
+
(row.enabled ? on : waiting).push(row);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
const base = c.prefix || c.parts || c.off
|
|
246
|
+
? c.effects.map(e => ({ ...e, id: `${c.prefix}${e.id}`, enabled: !!e.enabled && !c.off, ...(c.parts ? { meshNames: c.parts } : {}) }))
|
|
247
|
+
: c.effects;
|
|
248
|
+
if (c === this.own) {
|
|
249
|
+
this.ownRows = new Map();
|
|
250
|
+
for (const e of [...on, ...waiting])
|
|
251
|
+
this.ownRows.set(e.id, true);
|
|
252
|
+
for (const e of base)
|
|
253
|
+
this.ownRows.set(e.id, false);
|
|
254
|
+
}
|
|
255
|
+
return { on, base, waiting };
|
|
256
|
+
}
|
|
257
|
+
/** A row follows the object's visibility (one of its own, with `visible` on) · it is a step's. */
|
|
258
|
+
visOf(id) {
|
|
259
|
+
// a group's effect on this child, following the group's visibility (see fanLeave / fanEnter)
|
|
260
|
+
if (this.addedFollows.has(id))
|
|
261
|
+
return [true, false];
|
|
262
|
+
const inStep = this.ownRows.get(id);
|
|
263
|
+
return [!!this.own.follows && inStep !== undefined, !!inStep];
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* The running list, top first (the first of two that clash wins): added effects, applied clips
|
|
267
|
+
* (newest first; in each, the step that is on, then its always-on effects), the object's own clip,
|
|
268
|
+
* then everything that waits or is playing out.
|
|
269
|
+
*/
|
|
270
|
+
compose() {
|
|
271
|
+
const own = this.rowsOf(this.own);
|
|
272
|
+
if (!this.added.size && !this.clips.size)
|
|
273
|
+
return own.on.length || own.waiting.length ? [...own.on, ...own.base, ...own.waiting] : own.base;
|
|
274
|
+
const top = [], rest = [];
|
|
275
|
+
for (const e of [...this.added.values()].reverse())
|
|
276
|
+
(e.enabled ? top : rest).push(e);
|
|
277
|
+
for (const c of [...this.clips.values()].reverse()) {
|
|
278
|
+
const r = this.rowsOf(c);
|
|
279
|
+
if (c.off)
|
|
280
|
+
rest.push(...r.on, ...r.base, ...r.waiting);
|
|
281
|
+
else {
|
|
282
|
+
top.push(...r.on, ...r.base);
|
|
283
|
+
rest.push(...r.waiting);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return [...top, ...own.on, ...own.base, ...own.waiting, ...rest];
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Put an effect on the object on top of its own (an interaction, an action). `key` names it for
|
|
290
|
+
* removeEffect. Already on: a one-shot plays again, anything else is left as it is.
|
|
291
|
+
*/
|
|
292
|
+
addEffect(key, effect, opts) {
|
|
293
|
+
const def = getOperation(effect.operation);
|
|
294
|
+
if (this.disposed || !isObjectOperation(def))
|
|
295
|
+
return false;
|
|
296
|
+
// a group: an effect triggered on it that goes to the children is handed out (staggered)
|
|
297
|
+
if (this.fan && isFanRow(effect))
|
|
298
|
+
return this.fan.addTriggered(key, effect);
|
|
299
|
+
const id = `+${key}`;
|
|
300
|
+
const follows = !!opts?.follows;
|
|
301
|
+
if (follows !== this.addedFollows.has(id)) {
|
|
302
|
+
if (follows)
|
|
303
|
+
this.addedFollows.add(id);
|
|
304
|
+
else
|
|
305
|
+
this.addedFollows.delete(id);
|
|
306
|
+
this.added.delete(key); // following visibility or not makes it another effect
|
|
307
|
+
}
|
|
308
|
+
const cur = this.added.get(key);
|
|
309
|
+
const { autoplay: _a, ...pb } = effect.playback ?? {};
|
|
310
|
+
// a motion added with no playback runs until it is reverted
|
|
311
|
+
const playback = Object.keys(pb).length ? pb : def.periodic ? { loop: true } : undefined;
|
|
312
|
+
const row = { id, operation: effect.operation, enabled: true, meshNames: effect.meshNames, params: effect.params, ...(playback ? { playback } : {}) };
|
|
313
|
+
if (cur?.enabled && cur.operation === effect.operation) {
|
|
314
|
+
// the same values: a one-shot plays again, anything else is left as it is; new values land at once
|
|
315
|
+
if (JSON.stringify([cur.params ?? null, cur.playback ?? null, cur.meshNames ?? null]) === JSON.stringify([row.params ?? null, row.playback ?? null, row.meshNames ?? null])) {
|
|
316
|
+
if (!def.revert && this.running.has(id))
|
|
317
|
+
this.play(id);
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
this.added.set(key, row);
|
|
322
|
+
// instant: put on in its held state (a group's effects reaching a child on scene load / as it joins)
|
|
323
|
+
this.syncList(this.compose(), opts?.instant ? 'instant' : 'direct');
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
/** Take an added effect off: it plays out (or what is below it takes over again). */
|
|
327
|
+
removeEffect(key) {
|
|
328
|
+
if (this.fan?.hasTriggered(key))
|
|
329
|
+
return this.fan.removeTriggered(key);
|
|
330
|
+
const cur = this.added.get(key);
|
|
331
|
+
if (this.disposed || !cur?.enabled)
|
|
332
|
+
return false;
|
|
333
|
+
const off = { ...cur, enabled: false };
|
|
334
|
+
this.added.set(key, off);
|
|
335
|
+
this.syncList(this.compose(), 'direct');
|
|
336
|
+
// it stays listed (off) until it has really gone, so a later sync does not cut its out short
|
|
337
|
+
const l = [...this.leaving].find(x => x.id === cur.id);
|
|
338
|
+
void (l?.done ?? Promise.resolve()).then(() => { if (this.added.get(key) === off)
|
|
339
|
+
this.added.delete(key); });
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
hasEffect(key) { return !!this.added.get(key)?.enabled || !!this.fan?.hasTriggered(key); }
|
|
343
|
+
/** The object's own steps wait while an applied clip has steps; afterwards they start again from the first. */
|
|
344
|
+
refreshPause() {
|
|
345
|
+
const paused = [...this.clips.values()].some(c => !c.off && !!c.cfg);
|
|
346
|
+
if (paused === this.ownPaused)
|
|
347
|
+
return;
|
|
348
|
+
this.ownPaused = paused;
|
|
349
|
+
const c = this.own;
|
|
350
|
+
clearTimeout(c.timer);
|
|
351
|
+
c.run++;
|
|
352
|
+
if (!paused) {
|
|
353
|
+
c.index = 0;
|
|
354
|
+
c.dir = 1;
|
|
355
|
+
this.scheduleStep(c);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Apply a whole effect clip over the object's own (an interaction, an action). `key` names this
|
|
360
|
+
* application for removeClip; `parts` narrows it to nodes of the model. Already on: left as it is.
|
|
361
|
+
*/
|
|
362
|
+
applyClip(key, clip, parts) {
|
|
363
|
+
if (this.disposed)
|
|
364
|
+
return false;
|
|
365
|
+
if (this.fan) {
|
|
366
|
+
// a group: the clip's visual / 'each' effects go to the children (staggered), the rest runs on the group
|
|
367
|
+
const pick = (fan) => {
|
|
368
|
+
const keep = (e) => !!e && isFanRow(e) === fan;
|
|
369
|
+
const steps = (clip.steps ?? []).map(s => ({ ...s, effects: (s.effects ?? []).filter(keep) })).filter(s => s.effects.length);
|
|
370
|
+
return { ...clip, effects: (clip.effects ?? []).filter(keep), steps };
|
|
371
|
+
};
|
|
372
|
+
const kids = pick(true), mine = pick(false);
|
|
373
|
+
const handed = kids.effects.length || kids.steps.length ? this.fan.applyClip(key, kids) : false;
|
|
374
|
+
if (!mine.effects.length && !mine.steps.length)
|
|
375
|
+
return handed;
|
|
376
|
+
clip = mine;
|
|
377
|
+
}
|
|
378
|
+
const cur = this.clips.get(key);
|
|
379
|
+
if (cur && !cur.off)
|
|
380
|
+
return true;
|
|
381
|
+
if (cur) {
|
|
382
|
+
clearTimeout(cur.timer);
|
|
383
|
+
cur.run++;
|
|
384
|
+
}
|
|
385
|
+
// a triggered clip has no autoplay of its own and never follows visibility: it plays when it is applied
|
|
386
|
+
const effects = (clip.effects ?? []).filter(e => e && isObjectOperation(getOperation(e.operation))).map(e => {
|
|
387
|
+
const { autoplay: _a, ...pb } = e.playback ?? {};
|
|
388
|
+
const { playback: _p, meshNames: _m, ...row } = e;
|
|
389
|
+
return { ...row, ...(Object.keys(pb).length ? { playback: pb } : {}) };
|
|
390
|
+
});
|
|
391
|
+
const steps = (clip.steps ?? []).filter(s => s?.effects?.length);
|
|
392
|
+
const cfg = steps.length ? { steps, loop: clip.loop, yoyo: clip.yoyo } : null;
|
|
393
|
+
const c = { key, prefix: `~${key}:`, effects, cfg, stepsKey: stepsKeyOf(cfg), index: 0, dir: 1, run: (cur?.run ?? 0) + 1, parts: parts?.length ? parts : undefined };
|
|
394
|
+
this.clips.delete(key); // newest last
|
|
395
|
+
this.clips.set(key, c);
|
|
396
|
+
this.refreshPause();
|
|
397
|
+
this.scheduleStep(c);
|
|
398
|
+
this.syncList(this.compose(), 'direct');
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
/** Take an applied clip off: its effects play out, and what it had taken over comes back. */
|
|
402
|
+
removeClip(key) {
|
|
403
|
+
const handed = !this.disposed && !!this.fan?.removeClip(key);
|
|
404
|
+
const c = this.clips.get(key);
|
|
405
|
+
if (this.disposed || !c || c.off)
|
|
406
|
+
return handed;
|
|
407
|
+
c.off = true;
|
|
408
|
+
clearTimeout(c.timer);
|
|
409
|
+
c.run++;
|
|
410
|
+
this.refreshPause();
|
|
411
|
+
this.syncList(this.compose(), 'direct');
|
|
412
|
+
const gone = [...this.leaving].filter(x => x.id.startsWith(c.prefix)).map(x => x.done);
|
|
413
|
+
void Promise.all(gone).then(() => { if (this.clips.get(key) === c && c.off)
|
|
414
|
+
this.clips.delete(key); });
|
|
415
|
+
return true;
|
|
416
|
+
}
|
|
417
|
+
hasClip(key) { const c = this.clips.get(key); return (!!c && !c.off) || !!this.fan?.hasClip(key); }
|
|
418
|
+
/**
|
|
419
|
+
* A clip's current step's clock: its hold starts when its looks have really played in (they first
|
|
420
|
+
* wait for the outgoing step, and the first time for their shaders), so a slow start never eats a step.
|
|
421
|
+
*/
|
|
422
|
+
scheduleStep(c) {
|
|
423
|
+
clearTimeout(c.timer);
|
|
424
|
+
const run = ++c.run;
|
|
425
|
+
const s = c.cfg?.steps[c.index];
|
|
426
|
+
if (!s)
|
|
427
|
+
return;
|
|
428
|
+
if (!this.shown)
|
|
429
|
+
return; // hidden: the steps wait for the object to be shown
|
|
430
|
+
const pause = (ms) => new Promise(res => { c.timer = setTimeout(res, ms); });
|
|
431
|
+
const live = () => !this.disposed && run === c.run;
|
|
432
|
+
void (async () => {
|
|
433
|
+
await pause(0); // after the sync that put the step on
|
|
434
|
+
const ids = (s.effects ?? []).map(e => `${c.prefix}${s.id}:${e.id}`);
|
|
435
|
+
const looks = () => ids.map(id => this.running.get(id)).filter((r) => { const d = r && getOperation(r.op); return !!r && !!d?.revert && !d.periodic; });
|
|
436
|
+
for (let waited = 0; live() && waited < 15000 && looks().some(r => !r.started); waited += 50)
|
|
437
|
+
await pause(50);
|
|
438
|
+
if (!live())
|
|
439
|
+
return;
|
|
440
|
+
await Promise.all(looks().map(r => this.done(r)));
|
|
441
|
+
if (!live())
|
|
442
|
+
return;
|
|
443
|
+
// a group: the step's effects reach the children one after another — the hold starts when the last child's looks are on
|
|
444
|
+
const fan = c === this.own ? this.fan : null;
|
|
445
|
+
if (fan && (s.effects ?? []).some(e => e && isFanRow(e))) {
|
|
446
|
+
// wait until the last child has been given the step's effects, then for its looks to play in
|
|
447
|
+
for (let waited = 0; live() && waited < 30000 && fan.pending(ids); waited += 50)
|
|
448
|
+
await pause(50);
|
|
449
|
+
if (!live())
|
|
450
|
+
return;
|
|
451
|
+
await pause(seconds(s.in, STEP_IN) * 1000);
|
|
452
|
+
if (!live())
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
await pause(seconds(s.hold, STEP_HOLD) * 1000);
|
|
456
|
+
if (live())
|
|
457
|
+
this.nextStep(c);
|
|
458
|
+
})();
|
|
459
|
+
}
|
|
460
|
+
nextStep(c) {
|
|
461
|
+
const cfg = c.cfg;
|
|
462
|
+
if (!cfg || this.disposed || c.off)
|
|
463
|
+
return;
|
|
464
|
+
const n = cfg.steps.length;
|
|
465
|
+
let i = c.index + c.dir;
|
|
466
|
+
if (cfg.yoyo) { // there and back through the steps
|
|
467
|
+
if (n < 2)
|
|
468
|
+
return;
|
|
469
|
+
if (i >= n) {
|
|
470
|
+
c.dir = -1;
|
|
471
|
+
i = n - 2;
|
|
472
|
+
}
|
|
473
|
+
else if (i < 0) {
|
|
474
|
+
if (!cfg.loop)
|
|
475
|
+
return;
|
|
476
|
+
c.dir = 1;
|
|
477
|
+
i = 1;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
else if (i >= n) {
|
|
481
|
+
if (!cfg.loop || n < 2)
|
|
482
|
+
return; // stays on its last step
|
|
483
|
+
i = 0;
|
|
484
|
+
}
|
|
485
|
+
const leaving = cfg.steps[c.index];
|
|
486
|
+
c.index = i;
|
|
487
|
+
// direct: the next step plays in over the outgoing one; a step that plays out goes first, and the next waits for it
|
|
488
|
+
this.syncList(this.compose(), leaving?.playOut ? 'animate' : 'direct');
|
|
489
|
+
this.scheduleStep(c);
|
|
490
|
+
}
|
|
491
|
+
/** The step of the object's own clip that is on (-1: no steps, or they wait for an applied clip). */
|
|
492
|
+
get step() { return this.own.cfg && !this.ownPaused ? this.own.index : -1; }
|
|
493
|
+
syncList(effects, mode) {
|
|
494
|
+
if (this.disposed)
|
|
495
|
+
return;
|
|
496
|
+
if (this.fan) {
|
|
497
|
+
// a group: its own rows that go to the children (visual, physical 'each' — Base and steps) are handed out
|
|
498
|
+
const fanRows = [], rest = [];
|
|
499
|
+
for (const e of effects ?? [])
|
|
500
|
+
(e && this.ownRows.has(e.id) && isFanRow(e) ? fanRows : rest).push(e);
|
|
501
|
+
effects = rest;
|
|
502
|
+
this.fan.sync(fanRows, this.spread, mode === 'instant' ? 'instant' : 'animate', !!this.own.follows);
|
|
503
|
+
}
|
|
73
504
|
this.effects = effects ?? [];
|
|
74
505
|
if (this.refreshing)
|
|
75
506
|
return; // the refresh puts the latest list back when it is done
|
|
76
507
|
const next = runningObjectEffects(effects);
|
|
77
508
|
const byId = new Map(next.map(e => [e.id, e]));
|
|
509
|
+
const clearing = new Map(); // switched row → its old effect gone
|
|
510
|
+
const wiped = []; // direct handover: outgoing take-overs
|
|
511
|
+
// an effect that goes on under another row (the same effect, from above or below it): op → its targets
|
|
512
|
+
const comingOn = new Map();
|
|
513
|
+
for (const e of next)
|
|
514
|
+
if (!this.running.has(e.id))
|
|
515
|
+
comingOn.set(e.operation, namesKey(e));
|
|
516
|
+
const incoming = [];
|
|
517
|
+
const listed = new Set(this.effects.map(e => e?.id));
|
|
518
|
+
// removed while it was playing out: finish it at once
|
|
519
|
+
for (const l of this.leaving) {
|
|
520
|
+
if (listed.has(l.id))
|
|
521
|
+
continue;
|
|
522
|
+
this.off(l.r, true);
|
|
523
|
+
l.done = Promise.all(l.r.targets.map(t => runOf(l.r.op, t)));
|
|
524
|
+
void l.done.then(() => this.leaving.delete(l));
|
|
525
|
+
}
|
|
78
526
|
for (const [id, r] of this.running) {
|
|
79
527
|
const e = byId.get(id);
|
|
80
|
-
if (e && e.operation === r.op && namesKey(e) === r.targetsKey)
|
|
528
|
+
if (e && e.operation === r.op && namesKey(e) === r.targetsKey && rowKey(getOperation(e.operation), e, ...this.visOf(e.id)) === r.playbackKey)
|
|
81
529
|
continue;
|
|
82
|
-
|
|
530
|
+
if (e) {
|
|
531
|
+
// switched (another operation, or another playback): the old effect goes at once (no out transition under the new one's in)
|
|
532
|
+
if (r.started) {
|
|
533
|
+
this.off(r, true);
|
|
534
|
+
clearing.set(id, Promise.all(r.targets.map(t => runOf(r.op, t))));
|
|
535
|
+
}
|
|
536
|
+
else if (r.waitFor) {
|
|
537
|
+
clearing.set(id, r.waitFor); // switched again before it started: still wait for the first
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
// switched off plays out; a row removed from the list is cleared at once
|
|
542
|
+
const gone = mode === 'instant' || !listed.has(id);
|
|
543
|
+
if (mode !== 'instant' && r.started && comingOn.get(r.op) === r.targetsKey) {
|
|
544
|
+
// the same effect carries on under another row: it is handed over as it stands (the new row's values take over)
|
|
545
|
+
this.cancelCycle(r);
|
|
546
|
+
r.phase = undefined;
|
|
547
|
+
if (r.wipe) {
|
|
548
|
+
r.wipe.cancelled = true;
|
|
549
|
+
r.wipe = undefined;
|
|
550
|
+
}
|
|
551
|
+
this.running.delete(id);
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
// a direct handover: a held take-over stays on until the incoming one has wiped it (paired below)
|
|
555
|
+
if (!gone && mode === 'direct' && r.started && !r.cycle && !r.stopping && getOperation(r.op)?.field)
|
|
556
|
+
wiped.push([id, r]);
|
|
557
|
+
else
|
|
558
|
+
this.playOut(id, r, gone, mode === 'instant');
|
|
559
|
+
}
|
|
83
560
|
this.running.delete(id);
|
|
84
561
|
}
|
|
85
562
|
for (const e of next) {
|
|
86
563
|
const def = getOperation(e.operation);
|
|
87
|
-
const
|
|
564
|
+
const [follows, inStep] = this.visOf(e.id);
|
|
565
|
+
const params = objectEffectParams(def, e, follows, inStep);
|
|
88
566
|
const paramsKey = JSON.stringify(params);
|
|
89
567
|
const r = this.running.get(e.id);
|
|
90
568
|
if (r && r.paramsKey === paramsKey)
|
|
91
569
|
continue;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
570
|
+
if (r && !r.started) {
|
|
571
|
+
r.params = params;
|
|
572
|
+
r.paramsKey = paramsKey;
|
|
573
|
+
continue;
|
|
574
|
+
} // starts with the latest
|
|
575
|
+
const playback = playbackOf(e);
|
|
576
|
+
if (r?.cycle) {
|
|
577
|
+
// a parameter changed under a running cycle: its next pass picks it up;
|
|
578
|
+
// a periodic motion is on the whole time, so it takes it now
|
|
579
|
+
r.params = params;
|
|
580
|
+
r.paramsKey = paramsKey;
|
|
581
|
+
if (def.periodic)
|
|
582
|
+
this.on(def, r.targets, { ...params, __backward: !!r.cycle.back, duration: 0 });
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
const entry = { op: def.value, targets: r?.targets ?? this.targetsOf(e), targetsKey: namesKey(e), params, paramsKey, started: false, playback, playbackKey: rowKey(def, e, follows, inStep), kind: effectPresence(def, e, follows, inStep), follows, inStep };
|
|
586
|
+
this.running.set(e.id, entry);
|
|
587
|
+
const instant = !!r || mode === 'instant';
|
|
588
|
+
if (!r)
|
|
589
|
+
incoming.push([def, entry]);
|
|
590
|
+
// start from the original: after the effect this row replaces, and after others still playing out
|
|
591
|
+
// (the same operation coming back on just turns its own out transition around).
|
|
592
|
+
// A direct handover does not wait: the new look plays in over the old one.
|
|
593
|
+
const waits = mode === 'direct' ? [] : [...this.leaving].filter(l => l.op !== def.value).map(l => l.done);
|
|
594
|
+
const cleared = clearing.get(e.id);
|
|
595
|
+
if (cleared)
|
|
596
|
+
waits.push(cleared);
|
|
597
|
+
const wait = waits.length && !instant ? Promise.all(waits) : cleared;
|
|
598
|
+
if (!wait) {
|
|
599
|
+
this.start(def, entry, instant);
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
entry.waitFor = wait;
|
|
603
|
+
void wait.then(() => {
|
|
604
|
+
if (this.disposed || this.running.get(e.id) !== entry || entry.waitFor !== wait)
|
|
605
|
+
return; // removed, switched or played meanwhile
|
|
606
|
+
this.start(def, entry, instant);
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
// pair each outgoing take-over with the incoming one that wipes it (a surface take-over first)
|
|
610
|
+
const by = incoming.find(([d]) => d.field && d.stack) ?? incoming.find(([d]) => d.field);
|
|
611
|
+
for (const [id, r] of wiped) {
|
|
612
|
+
if (by && by[0].value !== r.op)
|
|
613
|
+
this.wipe(id, r, by[0], by[1]);
|
|
614
|
+
else
|
|
615
|
+
this.playOut(id, r, false, false);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
/** Take a row that left the list off: at once (`gone`), or with its out transition — then it is tracked until it has gone. */
|
|
619
|
+
playOut(id, r, gone, untracked) {
|
|
620
|
+
this.off(r, gone);
|
|
621
|
+
if (!r.started || untracked)
|
|
622
|
+
return;
|
|
623
|
+
const l = { id, r, op: r.op, done: Promise.all(r.targets.map(t => runOf(r.op, t))) };
|
|
624
|
+
this.leaving.add(l);
|
|
625
|
+
void l.done.then(() => this.leaving.delete(l));
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* A direct handover: `r` (a held take-over) stays on while `inc` plays in, and is wiped by
|
|
629
|
+
* inc's front — its field takes inc's direction / scale / sweep, its `clear` follows inc's
|
|
630
|
+
* progress every frame. When inc is fully on, r is taken off at once (nothing of it shows any more).
|
|
631
|
+
*/
|
|
632
|
+
wipe(id, r, incDef, inc) {
|
|
633
|
+
const def = getOperation(r.op);
|
|
634
|
+
const token = (r.wipe = { cancelled: false });
|
|
635
|
+
const saved = new Map();
|
|
636
|
+
let resolve;
|
|
637
|
+
const l = { id, r, op: r.op, done: new Promise(res => { resolve = res; }) };
|
|
638
|
+
this.leaving.add(l);
|
|
639
|
+
void l.done.then(() => this.leaving.delete(l));
|
|
640
|
+
const restore = () => saved.forEach((v, f) => { f.direction.value = v.direction; f.scale.value = v.scale; f.sweep.value.copy(v.sweep); f.clear.value = 0; });
|
|
641
|
+
const next = (fn) => (typeof requestAnimationFrame === 'function' ? requestAnimationFrame(() => fn()) : setTimeout(fn, 16));
|
|
642
|
+
const t0 = Date.now();
|
|
643
|
+
const tick = () => {
|
|
644
|
+
if (token.cancelled || this.disposed) {
|
|
645
|
+
resolve();
|
|
646
|
+
return;
|
|
647
|
+
} // taken off some other way (off() did it)
|
|
648
|
+
const live = [...this.running.values()].includes(inc);
|
|
649
|
+
if (!live) { // the incoming look left first: play out the old way
|
|
650
|
+
r.wipe = undefined;
|
|
651
|
+
restore();
|
|
652
|
+
for (const t of r.targets)
|
|
653
|
+
forceRevert(def, t, r.params);
|
|
654
|
+
void Promise.all(r.targets.map(t => runOf(r.op, t))).then(resolve);
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
let done = inc.started;
|
|
658
|
+
r.targets.forEach((t, i) => {
|
|
659
|
+
const fo = def.field(t), fi = incDef.field(inc.targets[i] ?? inc.targets[0]);
|
|
660
|
+
if (!fo || !fi) {
|
|
661
|
+
if (!fo)
|
|
662
|
+
return;
|
|
663
|
+
done = done && !!fi;
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
if (!saved.has(fo))
|
|
667
|
+
saved.set(fo, { direction: fo.direction.value, scale: fo.scale.value, sweep: fo.sweep.value.clone() });
|
|
668
|
+
fo.direction.value = fi.direction.value;
|
|
669
|
+
fo.scale.value = fi.scale.value;
|
|
670
|
+
fo.sweep.value.copy(fi.sweep.value);
|
|
671
|
+
fo.clearEdge.value = fi.edgeWidth.value;
|
|
672
|
+
fo.clear.value = Math.min(1, Math.max(0, fi.progress.value));
|
|
673
|
+
if (fi.progress.value < 0.999)
|
|
674
|
+
done = false;
|
|
675
|
+
});
|
|
676
|
+
if (!done && Date.now() - t0 < 60000) {
|
|
677
|
+
next(tick);
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
r.wipe = undefined; // all of it is wiped: off, at once
|
|
681
|
+
for (const t of r.targets)
|
|
682
|
+
forceRevert(def, t, { ...r.params, duration: 0 });
|
|
683
|
+
void Promise.all(r.targets.map(t => runOf(r.op, t))).then(resolve);
|
|
684
|
+
};
|
|
685
|
+
tick();
|
|
686
|
+
}
|
|
687
|
+
/** Whether the object is shown when the controller starts (before the first sync). */
|
|
688
|
+
setShown(shown) { this.shown = shown; this.drawn = shown; }
|
|
689
|
+
/** See setObjectEffectsVisible. */
|
|
690
|
+
setVisible(visible) {
|
|
691
|
+
if (this.disposed || visible === this.shown)
|
|
692
|
+
return null;
|
|
693
|
+
const c = this.own;
|
|
694
|
+
const steps = !!c.follows && !!c.cfg;
|
|
695
|
+
if (steps && !visible) {
|
|
696
|
+
clearTimeout(c.timer);
|
|
697
|
+
c.run++;
|
|
698
|
+
} // hidden: the steps stop (the step that is on plays out below)
|
|
699
|
+
if (steps && visible && !this.drawn) {
|
|
700
|
+
// shown from hidden: the steps start again from the first, staged while the object is still hidden
|
|
701
|
+
c.index = 0;
|
|
702
|
+
c.dir = 1;
|
|
703
|
+
this.syncList(this.compose(), 'instant');
|
|
704
|
+
}
|
|
705
|
+
// Effects that don't follow visibility (an own clip without it, added effects, applied clips) stop
|
|
706
|
+
// at once while the object is hidden — nothing runs on a hidden object, and nothing may show it
|
|
707
|
+
// again (a physical exit's way back puts the object on) — and come back on at once when it is shown.
|
|
708
|
+
const loose = [...this.running].filter(([, r]) => !r.follows && getOperation(r.op));
|
|
709
|
+
const looseClips = [c, ...this.clips.values()].filter(x => !!x.cfg && !x.off && !(x === c && steps));
|
|
710
|
+
const following = [...this.running].some(([, r]) => r.follows && getOperation(r.op));
|
|
711
|
+
if (!visible) {
|
|
712
|
+
for (const x of looseClips) {
|
|
713
|
+
clearTimeout(x.timer);
|
|
714
|
+
x.run++;
|
|
715
|
+
}
|
|
716
|
+
for (const [, r] of loose)
|
|
717
|
+
this.clear(r);
|
|
718
|
+
if (loose.length && !following)
|
|
719
|
+
this.root.visible = false; // a cleared exit put the object back on
|
|
95
720
|
}
|
|
721
|
+
this.shown = visible;
|
|
722
|
+
if (visible && (loose.length || looseClips.length)) {
|
|
723
|
+
for (const x of looseClips) {
|
|
724
|
+
x.index = 0;
|
|
725
|
+
x.dir = 1;
|
|
726
|
+
}
|
|
727
|
+
if (looseClips.length)
|
|
728
|
+
this.syncList(this.compose(), 'instant');
|
|
729
|
+
for (const [id, r] of loose) {
|
|
730
|
+
const def = getOperation(r.op);
|
|
731
|
+
if (def && this.running.get(id) === r && !r.started && !r.waitFor)
|
|
732
|
+
this.start(def, r, true);
|
|
733
|
+
}
|
|
734
|
+
for (const x of looseClips)
|
|
735
|
+
if (!(x === c && this.ownPaused))
|
|
736
|
+
this.scheduleStep(x);
|
|
737
|
+
}
|
|
738
|
+
const run = ++this.visRun;
|
|
739
|
+
const rows = [...this.running].filter(([, r]) => r.follows && getOperation(r.op));
|
|
740
|
+
// shown: the step that is on gets its clock once its effects are playing in (from the first step, or where it turned round)
|
|
741
|
+
const clock = () => { if (steps && visible && !this.ownPaused && !this.disposed && run === this.visRun)
|
|
742
|
+
this.scheduleStep(c); };
|
|
743
|
+
// a group whose effects follow visibility: hidden → its children play them out one after another and the
|
|
744
|
+
// group goes after the last; shown → the children start from nothing and play them in one after another
|
|
745
|
+
const fan = this.fan && c.follows ? this.fan : null;
|
|
746
|
+
if (fan && !visible) {
|
|
747
|
+
const outs = [fan.leave()];
|
|
748
|
+
if (rows.length) {
|
|
749
|
+
const p = this.leaveAll(rows, run, false);
|
|
750
|
+
if (p)
|
|
751
|
+
outs.push(p);
|
|
752
|
+
}
|
|
753
|
+
return Promise.all(outs).then(() => {
|
|
754
|
+
if (this.disposed || run !== this.visRun)
|
|
755
|
+
return; // shown again meanwhile
|
|
756
|
+
this.root.visible = false;
|
|
757
|
+
this.drawn = false;
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
if (fan && visible)
|
|
761
|
+
fan.park();
|
|
762
|
+
if (!rows.length) {
|
|
763
|
+
this.drawn = visible;
|
|
764
|
+
clock();
|
|
765
|
+
if (fan && visible)
|
|
766
|
+
fan.enter();
|
|
767
|
+
return null;
|
|
768
|
+
} // nothing follows it on the root: the renderer shows / hides
|
|
769
|
+
if (!visible)
|
|
770
|
+
return this.leaveAll(rows, run);
|
|
771
|
+
const entering = this.enterAll(rows, run);
|
|
772
|
+
void entering.then(() => { clock(); if (fan && !this.disposed && run === this.visRun)
|
|
773
|
+
fan.enter(); });
|
|
774
|
+
return entering;
|
|
775
|
+
}
|
|
776
|
+
// ---- a group's effects on this child, following the group's visibility (driven by the group's GroupFanout) ----
|
|
777
|
+
addedRows(keys) {
|
|
778
|
+
return keys.map(k => [`+${k}`, this.running.get(`+${k}`)])
|
|
779
|
+
.filter((x) => !!x[1] && !!getOperation(x[1].op));
|
|
780
|
+
}
|
|
781
|
+
/** The group is being hidden: this child plays the group's effects out, then is no longer drawn. */
|
|
782
|
+
fanLeave(keys) {
|
|
783
|
+
const rows = this.addedRows(keys);
|
|
784
|
+
if (this.disposed || !rows.length)
|
|
785
|
+
return Promise.resolve();
|
|
786
|
+
return this.leaveAll(rows, ++this.visRun) ?? Promise.resolve();
|
|
787
|
+
}
|
|
788
|
+
/** The group is about to be shown: this child starts from nothing (undrawn, the group's effects at their start). */
|
|
789
|
+
fanPark(keys) {
|
|
790
|
+
const rows = this.addedRows(keys);
|
|
791
|
+
if (this.disposed || !rows.length)
|
|
792
|
+
return;
|
|
793
|
+
++this.visRun;
|
|
794
|
+
for (const [, r] of rows)
|
|
795
|
+
this.clear(r);
|
|
796
|
+
this.root.visible = false;
|
|
797
|
+
this.drawn = false;
|
|
798
|
+
}
|
|
799
|
+
/** Its turn after the group was shown: the group's effects get ready, the child is drawn, they play in. */
|
|
800
|
+
fanEnter(keys) {
|
|
801
|
+
const rows = this.addedRows(keys);
|
|
802
|
+
if (this.disposed || !rows.length) {
|
|
803
|
+
if (!this.disposed && !this.drawn) {
|
|
804
|
+
this.root.visible = true;
|
|
805
|
+
this.drawn = true;
|
|
806
|
+
}
|
|
807
|
+
return Promise.resolve();
|
|
808
|
+
}
|
|
809
|
+
return this.enterAll(rows, ++this.visRun);
|
|
810
|
+
}
|
|
811
|
+
cancelCycle(r) {
|
|
812
|
+
if (r.cycle) {
|
|
813
|
+
r.cycle.cancelled = true;
|
|
814
|
+
r.cycle.wake?.();
|
|
815
|
+
r.cycle = undefined;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
/** Take an effect off at once and leave its row waiting. */
|
|
819
|
+
clear(r) {
|
|
820
|
+
this.off(r, true);
|
|
821
|
+
r.started = false;
|
|
822
|
+
r.stopping = undefined;
|
|
823
|
+
r.waitFor = undefined;
|
|
824
|
+
}
|
|
825
|
+
/** The object is shown: get every effect ready while it is still undrawn, draw it, play them in. */
|
|
826
|
+
async enterAll(rows, run) {
|
|
827
|
+
// shown again while its effects were still playing out: it is still drawn, they turn round where they are
|
|
828
|
+
const turn = this.drawn;
|
|
829
|
+
if (!turn) {
|
|
830
|
+
await Promise.all(rows.map(([, r]) => this.prepare(r)));
|
|
831
|
+
if (this.disposed || run !== this.visRun)
|
|
832
|
+
return; // hidden again meanwhile (leaveAll cleared it)
|
|
833
|
+
}
|
|
834
|
+
this.root.visible = true;
|
|
835
|
+
this.drawn = true;
|
|
836
|
+
// add-ons (trails) first: they are fully on when the entrances start moving the object
|
|
837
|
+
const first = [...rows].sort(([, a], [, b]) => Number(!!getOperation(b.op)?.addOn) - Number(!!getOperation(a.op)?.addOn));
|
|
838
|
+
for (const [id, r] of first)
|
|
839
|
+
if (this.running.get(id) === r)
|
|
840
|
+
this.enter(id, r, turn);
|
|
841
|
+
}
|
|
842
|
+
/** Before the object is drawn: compile the effect and put its start state on. */
|
|
843
|
+
prepare(r) {
|
|
844
|
+
const def = getOperation(r.op);
|
|
845
|
+
r.waitFor = undefined;
|
|
846
|
+
r.stopping = undefined;
|
|
847
|
+
if (r.kind === 'vanish') { // it starts gone
|
|
848
|
+
r.started = true;
|
|
849
|
+
r.phase = {};
|
|
850
|
+
this.on(def, r.targets, { ...r.params, duration: 0 });
|
|
851
|
+
return this.done(r);
|
|
852
|
+
}
|
|
853
|
+
if (def.channel !== 'visual' || !def.revert)
|
|
854
|
+
return Promise.resolve();
|
|
855
|
+
r.started = true; // staged at its start (a paint effect: nothing drawn yet)
|
|
856
|
+
return Promise.all(r.targets.map(t => warmOperation(def, t, r.params, this.root, { bare: true })));
|
|
857
|
+
}
|
|
858
|
+
enter(id, r, turn) {
|
|
859
|
+
const def = getOperation(r.op);
|
|
860
|
+
r.stopping = undefined;
|
|
861
|
+
if (def.addOn && def.revert) { // on at once: it draws the entrance from its first frame
|
|
862
|
+
this.cancelCycle(r);
|
|
863
|
+
r.started = true;
|
|
864
|
+
this.on(def, r.targets, { ...r.params, duration: 0 });
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
if (r.kind === 'paint') {
|
|
868
|
+
this.cancelCycle(r);
|
|
869
|
+
r.started = true;
|
|
870
|
+
this.on(def, r.targets, r.params); // from where it stands: its start, or part-way out
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
if (r.kind === 'vanish') {
|
|
874
|
+
if (r.started)
|
|
875
|
+
this.comeBack(def, r);
|
|
876
|
+
else
|
|
877
|
+
this.entrance(def, r);
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
if (turn) {
|
|
881
|
+
// a plain look turns round from where it is; anything else plays again from its start
|
|
882
|
+
if (r.started && def.revert && !def.periodic && isPlain(r.playback))
|
|
883
|
+
this.on(def, r.targets, r.params);
|
|
884
|
+
else
|
|
885
|
+
this.play(id);
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
r.started = false; // staged at its start: it plays from there
|
|
889
|
+
this.start(def, r, false, true);
|
|
890
|
+
}
|
|
891
|
+
/** A paint / vanish effect's entrance on an object that is already drawn (added, switched on, ▶). */
|
|
892
|
+
entrance(def, r) {
|
|
893
|
+
r.started = true;
|
|
894
|
+
// the object is drawn: a take-over plays in over it (it paints the object in only when the object is being shown)
|
|
895
|
+
if (r.kind === 'paint') {
|
|
896
|
+
this.on(def, r.targets, { ...r.params, __reveal: false });
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
const phase = (r.phase = {});
|
|
900
|
+
this.on(def, r.targets, { ...r.params, duration: 0 }); // gone…
|
|
901
|
+
void this.done(r).then(() => { if (!this.disposed && r.phase === phase)
|
|
902
|
+
this.comeBack(def, r); }); // …and back
|
|
903
|
+
}
|
|
904
|
+
/** A vanish effect plays back from gone (or from part-way); then the object is at rest, with nothing on it. */
|
|
905
|
+
comeBack(def, r) {
|
|
906
|
+
const phase = (r.phase = {});
|
|
907
|
+
r.started = true;
|
|
908
|
+
for (const t of r.targets)
|
|
909
|
+
forceRevert(def, t, r.params);
|
|
910
|
+
void this.done(r).then(() => { if (r.phase === phase) {
|
|
911
|
+
r.phase = undefined;
|
|
912
|
+
r.started = false;
|
|
913
|
+
} });
|
|
914
|
+
}
|
|
915
|
+
/** The object is hidden: play every effect out, then stop drawing it. */
|
|
916
|
+
/** `hide`: stop drawing the object at the end (a group hides itself after its children instead). */
|
|
917
|
+
leaveAll(rows, run, hide = true) {
|
|
918
|
+
if (!this.drawn) { // it was still getting ready to be shown
|
|
919
|
+
for (const [, r] of rows)
|
|
920
|
+
this.clear(r);
|
|
921
|
+
if (hide)
|
|
922
|
+
this.root.visible = false;
|
|
923
|
+
return null;
|
|
924
|
+
}
|
|
925
|
+
// add-ons (trails) stay on through the exits and go off once the object is gone
|
|
926
|
+
const isAddOn = (r) => !!getOperation(r.op)?.addOn;
|
|
927
|
+
const outs = rows.filter(([, r]) => !isAddOn(r)).map(([id, r]) => this.leave(id, r));
|
|
928
|
+
return Promise.all(outs).then(() => {
|
|
929
|
+
if (this.disposed || run !== this.visRun)
|
|
930
|
+
return; // shown again meanwhile
|
|
931
|
+
// while hidden nothing is on, so the next show starts clean — and in the same tick the object goes
|
|
932
|
+
for (const [id, r] of rows)
|
|
933
|
+
if (this.running.get(id) === r && !isAddOn(r))
|
|
934
|
+
this.clear(r);
|
|
935
|
+
if (hide) {
|
|
936
|
+
this.root.visible = false;
|
|
937
|
+
this.drawn = false;
|
|
938
|
+
}
|
|
939
|
+
for (const [id, r] of rows) {
|
|
940
|
+
if (this.running.get(id) !== r || !isAddOn(r))
|
|
941
|
+
continue;
|
|
942
|
+
// it fades out and lets what is in flight finish (it lives in the scene, not on the hidden object)
|
|
943
|
+
const out = this.leave(id, r);
|
|
944
|
+
void Promise.resolve(out).then(() => {
|
|
945
|
+
if (!this.disposed && run === this.visRun && this.running.get(id) === r)
|
|
946
|
+
this.clear(r);
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
leave(id, r) {
|
|
952
|
+
const def = getOperation(r.op);
|
|
953
|
+
r.waitFor = undefined;
|
|
954
|
+
if (r.kind === 'vanish') { // from rest, or from part-way in: it plays to gone
|
|
955
|
+
r.started = true;
|
|
956
|
+
r.phase = {};
|
|
957
|
+
this.on(def, r.targets, r.params);
|
|
958
|
+
return this.done(r);
|
|
959
|
+
}
|
|
960
|
+
if (!r.started)
|
|
961
|
+
return null;
|
|
962
|
+
if (r.kind === 'paint') { // retreats with the reveal on: nothing is left behind it
|
|
963
|
+
this.cancelCycle(r);
|
|
964
|
+
for (const t of r.targets)
|
|
965
|
+
forceRevert(def, t, r.params);
|
|
966
|
+
return this.done(r);
|
|
967
|
+
}
|
|
968
|
+
if (!def.revert) { // a one-shot: its move once more, the other way
|
|
969
|
+
this.cancelCycle(r);
|
|
970
|
+
this.on(def, r.targets, { ...r.params, __backward: !r.playback.reverse });
|
|
971
|
+
return this.done(r);
|
|
972
|
+
}
|
|
973
|
+
this.stop(id);
|
|
974
|
+
return r.stopping ?? null;
|
|
975
|
+
}
|
|
976
|
+
/** `force`: play it even with autoplay off (it was asked for). */
|
|
977
|
+
start(def, r, instant, force = false) {
|
|
978
|
+
r.waitFor = undefined;
|
|
979
|
+
if (!this.shown)
|
|
980
|
+
return; // the object is hidden: nothing runs until it is shown
|
|
981
|
+
if (r.follows && r.kind !== 'decorate') {
|
|
982
|
+
// shown at load / a changed value: a take-over is simply on, a vanish effect has nothing on
|
|
983
|
+
if (instant) {
|
|
984
|
+
if (r.kind === 'paint') {
|
|
985
|
+
r.started = true;
|
|
986
|
+
this.on(def, r.targets, { ...r.params, duration: 0 });
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
else
|
|
990
|
+
this.entrance(def, r); // added, switched on, ▶: its entrance
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
if (!r.playback.autoplay && !force)
|
|
994
|
+
return; // waits at its start for play()
|
|
995
|
+
r.started = true;
|
|
996
|
+
if (def.periodic) {
|
|
997
|
+
void this.periodic(def, r, instant);
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
if (isPlain(r.playback)) {
|
|
1001
|
+
this.on(def, r.targets, instant ? { ...r.params, duration: 0 } : r.params);
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
void this.cycle(def, r);
|
|
1005
|
+
}
|
|
1006
|
+
done(r) { return Promise.all(r.targets.map(t => runOf(r.op, t))); }
|
|
1007
|
+
/**
|
|
1008
|
+
* A periodic motion (float, sway…): on for one pass, then it settles — or on for good with Loop.
|
|
1009
|
+
* Reverse runs its clock backwards; yoyo turns the clock round after each pass.
|
|
1010
|
+
*/
|
|
1011
|
+
async periodic(def, r, instant) {
|
|
1012
|
+
const token = { cancelled: false, back: r.playback.reverse };
|
|
1013
|
+
r.cycle = token;
|
|
1014
|
+
const { loop, yoyo } = r.playback;
|
|
1015
|
+
const wait = (seconds) => new Promise((resolve) => {
|
|
1016
|
+
const end = () => { clearTimeout(id); token.wake = undefined; resolve(); };
|
|
1017
|
+
const id = setTimeout(end, Math.max(16, seconds * 1000));
|
|
1018
|
+
token.wake = end;
|
|
1019
|
+
});
|
|
1020
|
+
/** The part of a pass at full strength (the rest is building up and settling). */
|
|
1021
|
+
const moving = () => { const d = Number(r.params.duration); return Math.max(0, d - 2 * periodicEase(d)); };
|
|
1022
|
+
const turnOn = (atOnce) => this.on(def, r.targets, { ...r.params, __backward: !!token.back, ...(atOnce ? { duration: 0 } : {}) });
|
|
1023
|
+
turnOn(instant);
|
|
1024
|
+
await this.done(r);
|
|
1025
|
+
if (token.cancelled)
|
|
1026
|
+
return;
|
|
1027
|
+
if (loop && !yoyo)
|
|
1028
|
+
return; // stays on until it is switched off (r.cycle stays: it is running)
|
|
1029
|
+
for (;;) {
|
|
1030
|
+
await wait(moving());
|
|
1031
|
+
if (token.cancelled)
|
|
1032
|
+
return;
|
|
1033
|
+
if (!yoyo && !loop)
|
|
1034
|
+
break;
|
|
1035
|
+
token.back = !token.back; // yoyo: the same motion, backwards
|
|
1036
|
+
turnOn(true);
|
|
1037
|
+
if (!loop) {
|
|
1038
|
+
await wait(moving());
|
|
1039
|
+
if (token.cancelled)
|
|
1040
|
+
return;
|
|
1041
|
+
break;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
for (const t of r.targets)
|
|
1045
|
+
forceRevert(def, t, r.params);
|
|
1046
|
+
await this.done(r);
|
|
1047
|
+
if (r.cycle === token)
|
|
1048
|
+
r.cycle = undefined;
|
|
1049
|
+
}
|
|
1050
|
+
/** Loop / yoyo / reverse, sequenced from apply (forward) and revert (backward). Reads r.params each pass. */
|
|
1051
|
+
async cycle(def, r) {
|
|
1052
|
+
const token = { cancelled: false };
|
|
1053
|
+
r.cycle = token;
|
|
1054
|
+
const { reverse, loop, yoyo } = r.playback;
|
|
1055
|
+
const at = (dur0) => (dur0 ? { ...r.params, duration: 0 } : r.params);
|
|
1056
|
+
// A one-shot (no revert: jelly, flip, spin) starts and ends at rest, so standing at either end is
|
|
1057
|
+
// nothing to do, and its way back is the same move played backwards in time (`__backward`).
|
|
1058
|
+
const oneShot = !def.revert;
|
|
1059
|
+
const forward = async (dur0 = false) => {
|
|
1060
|
+
if (oneShot && dur0)
|
|
1061
|
+
return;
|
|
1062
|
+
this.on(def, r.targets, at(dur0));
|
|
1063
|
+
await this.done(r);
|
|
1064
|
+
};
|
|
1065
|
+
const backward = async (dur0 = false) => {
|
|
1066
|
+
if (oneShot && dur0)
|
|
1067
|
+
return;
|
|
1068
|
+
if (oneShot)
|
|
1069
|
+
this.on(def, r.targets, { ...r.params, __backward: true });
|
|
1070
|
+
else
|
|
1071
|
+
for (const t of r.targets)
|
|
1072
|
+
forceRevert(def, t, at(dur0));
|
|
1073
|
+
await this.done(r);
|
|
1074
|
+
};
|
|
1075
|
+
// a pass: start → end (or end → start when reversed); `first` is the direction of its first leg
|
|
1076
|
+
const first = reverse ? backward : forward;
|
|
1077
|
+
const second = reverse ? forward : backward;
|
|
1078
|
+
if (reverse) {
|
|
1079
|
+
await forward(true);
|
|
1080
|
+
if (token.cancelled)
|
|
1081
|
+
return;
|
|
1082
|
+
} // stand at the end
|
|
1083
|
+
for (;;) {
|
|
1084
|
+
// a pass never takes less than a frame (a zero duration must not spin)
|
|
1085
|
+
const frame = new Promise(res => setTimeout(res, 16));
|
|
1086
|
+
await first();
|
|
1087
|
+
await frame;
|
|
1088
|
+
if (token.cancelled)
|
|
1089
|
+
return;
|
|
1090
|
+
if (yoyo) {
|
|
1091
|
+
await second();
|
|
1092
|
+
if (token.cancelled)
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
if (!loop)
|
|
1096
|
+
break;
|
|
1097
|
+
if (!yoyo) {
|
|
1098
|
+
await second(true);
|
|
1099
|
+
if (token.cancelled)
|
|
1100
|
+
return;
|
|
1101
|
+
} // jump back to the pass's start
|
|
1102
|
+
}
|
|
1103
|
+
if (r.cycle === token)
|
|
1104
|
+
r.cycle = undefined;
|
|
1105
|
+
}
|
|
1106
|
+
/** Play an effect out and leave it waiting (it stays in the list, ready to play again). */
|
|
1107
|
+
stop(effectId) {
|
|
1108
|
+
const r = this.running.get(effectId);
|
|
1109
|
+
const def = r && getOperation(r.op);
|
|
1110
|
+
if (!r || !def || this.disposed || this.refreshing)
|
|
1111
|
+
return false;
|
|
1112
|
+
r.waitFor = undefined; // a play that was about to start is called off
|
|
1113
|
+
if (!r.started || r.stopping)
|
|
1114
|
+
return true;
|
|
1115
|
+
if (!def.revert) { // a one-shot: stop its move, back at once
|
|
1116
|
+
if (r.cycle) {
|
|
1117
|
+
r.cycle.cancelled = true;
|
|
1118
|
+
r.cycle.wake?.();
|
|
1119
|
+
r.cycle = undefined;
|
|
1120
|
+
}
|
|
1121
|
+
for (const t of r.targets)
|
|
1122
|
+
def.cancel?.(t);
|
|
1123
|
+
r.started = false;
|
|
1124
|
+
return true;
|
|
1125
|
+
}
|
|
1126
|
+
this.off(r, false);
|
|
1127
|
+
const done = this.done(r);
|
|
1128
|
+
r.stopping = done;
|
|
1129
|
+
void done.then(() => { if (r.stopping === done) {
|
|
1130
|
+
r.stopping = undefined;
|
|
1131
|
+
r.started = false;
|
|
1132
|
+
} });
|
|
1133
|
+
return true;
|
|
1134
|
+
}
|
|
1135
|
+
/** Play an effect from its start (see playObjectEffect). */
|
|
1136
|
+
play(effectId) {
|
|
1137
|
+
const r = this.running.get(effectId);
|
|
1138
|
+
const def = r && getOperation(r.op);
|
|
1139
|
+
if (!r || !def || this.disposed || this.refreshing)
|
|
1140
|
+
return false;
|
|
1141
|
+
r.stopping = undefined;
|
|
1142
|
+
const wasOn = r.started;
|
|
1143
|
+
this.off(r, true); // cancels a running cycle, clears at once
|
|
1144
|
+
const cleared = wasOn ? this.done(r) : Promise.resolve();
|
|
1145
|
+
r.started = false;
|
|
1146
|
+
r.waitFor = cleared;
|
|
1147
|
+
void cleared.then(() => {
|
|
1148
|
+
if (this.disposed || this.running.get(effectId) !== r || r.waitFor !== cleared)
|
|
1149
|
+
return;
|
|
1150
|
+
this.start(def, r, false, true);
|
|
1151
|
+
});
|
|
1152
|
+
return true;
|
|
96
1153
|
}
|
|
97
1154
|
/**
|
|
98
1155
|
* The object's meshes or materials were replaced: take every effect off the
|
|
@@ -107,14 +1164,29 @@ export class ObjectEffectsController {
|
|
|
107
1164
|
const done = Promise.all(list.flatMap(r => r.targets.map(t => runOf(r.op, t))));
|
|
108
1165
|
this.refreshing = done.then(() => {
|
|
109
1166
|
this.refreshing = null;
|
|
110
|
-
this.
|
|
1167
|
+
this.syncList(this.compose(), 'instant');
|
|
111
1168
|
});
|
|
112
1169
|
return this.refreshing;
|
|
113
1170
|
}
|
|
114
1171
|
/** Take everything off at once (the object is going away). */
|
|
1172
|
+
/** A group: children joined or left (the effects hook checks every few frames). */
|
|
1173
|
+
checkFanout() { this.fan?.check(); }
|
|
1174
|
+
/** Ids of a group's children in cascade order (tests / studio). */
|
|
1175
|
+
get fanChildren() { return this.fan?.childIds ?? []; }
|
|
115
1176
|
dispose() {
|
|
1177
|
+
this.fan?.dispose();
|
|
1178
|
+
this.fan = null;
|
|
1179
|
+
for (const c of [this.own, ...this.clips.values()]) {
|
|
1180
|
+
clearTimeout(c.timer);
|
|
1181
|
+
c.run++;
|
|
1182
|
+
}
|
|
1183
|
+
this.clips.clear();
|
|
1184
|
+
this.added.clear();
|
|
1185
|
+
if (controllers.get(this.root) === this)
|
|
1186
|
+
controllers.delete(this.root);
|
|
116
1187
|
this.running.forEach(r => this.off(r, true));
|
|
117
1188
|
this.running.clear();
|
|
1189
|
+
this.leaving.clear();
|
|
118
1190
|
this.disposed = true;
|
|
119
1191
|
}
|
|
120
1192
|
/** Ids of the effects running now (tests / studio). */
|
|
@@ -129,7 +1201,9 @@ export function surfaceSignature(root) {
|
|
|
129
1201
|
root.traverse((c) => {
|
|
130
1202
|
if (!c.isMesh || c.userData?.__opFxHelper)
|
|
131
1203
|
return;
|
|
132
|
-
|
|
1204
|
+
// an effect that swaps in its own copies while it plays (shatter) leaves the real material here
|
|
1205
|
+
const own = c.userData?.__opFxOwnMaterial ?? c.material;
|
|
1206
|
+
const mats = Array.isArray(own) ? own : [own];
|
|
133
1207
|
parts.push(c.uuid + ':' + mats.map((m) => m?.uuid ?? '').join(','));
|
|
134
1208
|
});
|
|
135
1209
|
return parts.join(';');
|