@3driseai/3drise-viewer 0.1.40 → 0.1.42
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/ClipsRuntime.d.ts.map +1 -1
- package/dist/animationsV2/ClipsRuntime.js +9 -5
- package/dist/animationsV2/clipUtils.d.ts +9 -0
- package/dist/animationsV2/clipUtils.d.ts.map +1 -1
- package/dist/animationsV2/clipUtils.js +11 -2
- package/dist/animationsV2/normalize.d.ts.map +1 -1
- package/dist/animationsV2/normalize.js +2 -0
- package/dist/animationsV2/types.d.ts +4 -0
- package/dist/animationsV2/types.d.ts.map +1 -1
- package/dist/api/sceneHandle.d.ts +40 -3
- package/dist/api/sceneHandle.d.ts.map +1 -1
- package/dist/api/sceneHandle.js +40 -0
- package/dist/components/GalleryObject.d.ts +13 -0
- package/dist/components/GalleryObject.d.ts.map +1 -0
- package/dist/components/GalleryObject.js +46 -0
- package/dist/components/ImageObject.d.ts +9 -0
- package/dist/components/ImageObject.d.ts.map +1 -0
- package/dist/components/ImageObject.js +26 -0
- package/dist/components/ObjectNode.d.ts.map +1 -1
- package/dist/components/ObjectNode.js +11 -5
- package/dist/components/ProjectLoader.d.ts +2 -0
- package/dist/components/ProjectLoader.d.ts.map +1 -1
- package/dist/components/ProjectLoader.js +2 -2
- package/dist/components/SceneBuilder.d.ts +10 -0
- package/dist/components/SceneBuilder.d.ts.map +1 -1
- package/dist/components/SceneBuilder.js +3 -2
- package/dist/components/gallery/BasicCarouselGallery.d.ts +18 -0
- package/dist/components/gallery/BasicCarouselGallery.d.ts.map +1 -0
- package/dist/components/gallery/BasicCarouselGallery.js +9 -0
- package/dist/components/gallery/ContourLinesGallery.d.ts +18 -0
- package/dist/components/gallery/ContourLinesGallery.d.ts.map +1 -0
- package/dist/components/gallery/ContourLinesGallery.js +9 -0
- package/dist/components/gallery/DepthLayersGallery.d.ts +18 -0
- package/dist/components/gallery/DepthLayersGallery.d.ts.map +1 -0
- package/dist/components/gallery/DepthLayersGallery.js +9 -0
- package/dist/components/gallery/EngravingGallery.d.ts +18 -0
- package/dist/components/gallery/EngravingGallery.d.ts.map +1 -0
- package/dist/components/gallery/EngravingGallery.js +9 -0
- package/dist/components/gallery/FlowLinesGallery.d.ts +18 -0
- package/dist/components/gallery/FlowLinesGallery.d.ts.map +1 -0
- package/dist/components/gallery/FlowLinesGallery.js +9 -0
- package/dist/components/gallery/FoldGallery.d.ts +18 -0
- package/dist/components/gallery/FoldGallery.d.ts.map +1 -0
- package/dist/components/gallery/FoldGallery.js +9 -0
- package/dist/components/gallery/GlassPanesGallery.d.ts +18 -0
- package/dist/components/gallery/GlassPanesGallery.d.ts.map +1 -0
- package/dist/components/gallery/GlassPanesGallery.js +9 -0
- package/dist/components/gallery/HaloGallery.d.ts +18 -0
- package/dist/components/gallery/HaloGallery.d.ts.map +1 -0
- package/dist/components/gallery/HaloGallery.js +9 -0
- package/dist/components/gallery/LightThreadsGallery.d.ts +18 -0
- package/dist/components/gallery/LightThreadsGallery.d.ts.map +1 -0
- package/dist/components/gallery/LightThreadsGallery.js +9 -0
- package/dist/components/gallery/LoomGallery.d.ts +18 -0
- package/dist/components/gallery/LoomGallery.d.ts.map +1 -0
- package/dist/components/gallery/LoomGallery.js +9 -0
- package/dist/components/gallery/PaperLanternsGallery.d.ts +18 -0
- package/dist/components/gallery/PaperLanternsGallery.d.ts.map +1 -0
- package/dist/components/gallery/PaperLanternsGallery.js +9 -0
- package/dist/components/gallery/ParticleShiftGallery.d.ts +18 -0
- package/dist/components/gallery/ParticleShiftGallery.d.ts.map +1 -0
- package/dist/components/gallery/ParticleShiftGallery.js +9 -0
- package/dist/components/gallery/PinscreenGallery.d.ts +18 -0
- package/dist/components/gallery/PinscreenGallery.d.ts.map +1 -0
- package/dist/components/gallery/PinscreenGallery.js +9 -0
- package/dist/components/gallery/PopUpGallery.d.ts +18 -0
- package/dist/components/gallery/PopUpGallery.d.ts.map +1 -0
- package/dist/components/gallery/PopUpGallery.js +9 -0
- package/dist/components/gallery/PrismSplitGallery.d.ts +18 -0
- package/dist/components/gallery/PrismSplitGallery.d.ts.map +1 -0
- package/dist/components/gallery/PrismSplitGallery.js +9 -0
- package/dist/components/gallery/RidgelinesGallery.d.ts +18 -0
- package/dist/components/gallery/RidgelinesGallery.d.ts.map +1 -0
- package/dist/components/gallery/RidgelinesGallery.js +9 -0
- package/dist/components/gallery/ShadowBoxGallery.d.ts +18 -0
- package/dist/components/gallery/ShadowBoxGallery.d.ts.map +1 -0
- package/dist/components/gallery/ShadowBoxGallery.js +9 -0
- package/dist/components/gallery/SilkGallery.d.ts +18 -0
- package/dist/components/gallery/SilkGallery.d.ts.map +1 -0
- package/dist/components/gallery/SilkGallery.js +9 -0
- package/dist/components/gallery/SlatsGallery.d.ts +18 -0
- package/dist/components/gallery/SlatsGallery.d.ts.map +1 -0
- package/dist/components/gallery/SlatsGallery.js +9 -0
- package/dist/components/gallery/StrataGallery.d.ts +18 -0
- package/dist/components/gallery/StrataGallery.d.ts.map +1 -0
- package/dist/components/gallery/StrataGallery.js +9 -0
- package/dist/components/gallery/TerracesGallery.d.ts +18 -0
- package/dist/components/gallery/TerracesGallery.d.ts.map +1 -0
- package/dist/components/gallery/TerracesGallery.js +9 -0
- package/dist/components/gallery/WireReliefGallery.d.ts +18 -0
- package/dist/components/gallery/WireReliefGallery.d.ts.map +1 -0
- package/dist/components/gallery/WireReliefGallery.js +9 -0
- package/dist/components/gallery/index.d.ts +46 -0
- package/dist/components/gallery/index.d.ts.map +1 -0
- package/dist/components/gallery/index.js +22 -0
- package/dist/components/gallery/kit/GalleryVariant.d.ts +68 -0
- package/dist/components/gallery/kit/GalleryVariant.d.ts.map +1 -0
- package/dist/components/gallery/kit/GalleryVariant.js +231 -0
- package/dist/components/gallery/kit/feeds.d.ts +7 -0
- package/dist/components/gallery/kit/feeds.d.ts.map +1 -0
- package/dist/components/gallery/kit/feeds.js +83 -0
- package/dist/components/gallery/kit/galleryKit.d.ts +118 -0
- package/dist/components/gallery/kit/galleryKit.d.ts.map +1 -0
- package/dist/components/gallery/kit/galleryKit.js +298 -0
- package/dist/components/gallery/kit/lookBase.d.ts +157 -0
- package/dist/components/gallery/kit/lookBase.d.ts.map +1 -0
- package/dist/components/gallery/kit/lookBase.js +211 -0
- package/dist/components/gallery/kit/pictures.d.ts +14 -0
- package/dist/components/gallery/kit/pictures.d.ts.map +1 -0
- package/dist/components/gallery/kit/pictures.js +81 -0
- package/dist/components/gallery/looks/basicCarousel.d.ts +177 -0
- package/dist/components/gallery/looks/basicCarousel.d.ts.map +1 -0
- package/dist/components/gallery/looks/basicCarousel.js +315 -0
- package/dist/components/gallery/looks/contourLines.d.ts +153 -0
- package/dist/components/gallery/looks/contourLines.d.ts.map +1 -0
- package/dist/components/gallery/looks/contourLines.js +91 -0
- package/dist/components/gallery/looks/depthLayers.d.ts +155 -0
- package/dist/components/gallery/looks/depthLayers.d.ts.map +1 -0
- package/dist/components/gallery/looks/depthLayers.js +87 -0
- package/dist/components/gallery/looks/engraving.d.ts +162 -0
- package/dist/components/gallery/looks/engraving.d.ts.map +1 -0
- package/dist/components/gallery/looks/engraving.js +96 -0
- package/dist/components/gallery/looks/flowLines.d.ts +180 -0
- package/dist/components/gallery/looks/flowLines.d.ts.map +1 -0
- package/dist/components/gallery/looks/flowLines.js +113 -0
- package/dist/components/gallery/looks/fold.d.ts +209 -0
- package/dist/components/gallery/looks/fold.d.ts.map +1 -0
- package/dist/components/gallery/looks/fold.js +155 -0
- package/dist/components/gallery/looks/glassPanes.d.ts +133 -0
- package/dist/components/gallery/looks/glassPanes.d.ts.map +1 -0
- package/dist/components/gallery/looks/glassPanes.js +208 -0
- package/dist/components/gallery/looks/halo.d.ts +100 -0
- package/dist/components/gallery/looks/halo.d.ts.map +1 -0
- package/dist/components/gallery/looks/halo.js +119 -0
- package/dist/components/gallery/looks/lightThreads.d.ts +199 -0
- package/dist/components/gallery/looks/lightThreads.d.ts.map +1 -0
- package/dist/components/gallery/looks/lightThreads.js +246 -0
- package/dist/components/gallery/looks/loom.d.ts +238 -0
- package/dist/components/gallery/looks/loom.d.ts.map +1 -0
- package/dist/components/gallery/looks/loom.js +256 -0
- package/dist/components/gallery/looks/paperLanterns.d.ts +181 -0
- package/dist/components/gallery/looks/paperLanterns.d.ts.map +1 -0
- package/dist/components/gallery/looks/paperLanterns.js +399 -0
- package/dist/components/gallery/looks/particleShift.d.ts +193 -0
- package/dist/components/gallery/looks/particleShift.d.ts.map +1 -0
- package/dist/components/gallery/looks/particleShift.js +282 -0
- package/dist/components/gallery/looks/pinscreen.d.ts +175 -0
- package/dist/components/gallery/looks/pinscreen.d.ts.map +1 -0
- package/dist/components/gallery/looks/pinscreen.js +96 -0
- package/dist/components/gallery/looks/popUp.d.ts +206 -0
- package/dist/components/gallery/looks/popUp.d.ts.map +1 -0
- package/dist/components/gallery/looks/popUp.js +132 -0
- package/dist/components/gallery/looks/prismSplit.d.ts +151 -0
- package/dist/components/gallery/looks/prismSplit.d.ts.map +1 -0
- package/dist/components/gallery/looks/prismSplit.js +84 -0
- package/dist/components/gallery/looks/ridgelines.d.ts +179 -0
- package/dist/components/gallery/looks/ridgelines.d.ts.map +1 -0
- package/dist/components/gallery/looks/ridgelines.js +111 -0
- package/dist/components/gallery/looks/shadowBox.d.ts +152 -0
- package/dist/components/gallery/looks/shadowBox.d.ts.map +1 -0
- package/dist/components/gallery/looks/shadowBox.js +82 -0
- package/dist/components/gallery/looks/silk.d.ts +140 -0
- package/dist/components/gallery/looks/silk.d.ts.map +1 -0
- package/dist/components/gallery/looks/silk.js +346 -0
- package/dist/components/gallery/looks/slats.d.ts +176 -0
- package/dist/components/gallery/looks/slats.d.ts.map +1 -0
- package/dist/components/gallery/looks/slats.js +93 -0
- package/dist/components/gallery/looks/strata.d.ts +172 -0
- package/dist/components/gallery/looks/strata.d.ts.map +1 -0
- package/dist/components/gallery/looks/strata.js +88 -0
- package/dist/components/gallery/looks/terraces.d.ts +168 -0
- package/dist/components/gallery/looks/terraces.d.ts.map +1 -0
- package/dist/components/gallery/looks/terraces.js +91 -0
- package/dist/components/gallery/looks/wireRelief.d.ts +153 -0
- package/dist/components/gallery/looks/wireRelief.d.ts.map +1 -0
- package/dist/components/gallery/looks/wireRelief.js +128 -0
- package/dist/components/image/ContourImage.d.ts +7 -0
- package/dist/components/image/ContourImage.d.ts.map +1 -0
- package/dist/components/image/ContourImage.js +6 -0
- package/dist/components/image/EngravingImage.d.ts +7 -0
- package/dist/components/image/EngravingImage.d.ts.map +1 -0
- package/dist/components/image/EngravingImage.js +6 -0
- package/dist/components/image/FrostImage.d.ts +7 -0
- package/dist/components/image/FrostImage.d.ts.map +1 -0
- package/dist/components/image/FrostImage.js +6 -0
- package/dist/components/image/LenticularImage.d.ts +7 -0
- package/dist/components/image/LenticularImage.d.ts.map +1 -0
- package/dist/components/image/LenticularImage.js +6 -0
- package/dist/components/image/PinscreenImage.d.ts +7 -0
- package/dist/components/image/PinscreenImage.d.ts.map +1 -0
- package/dist/components/image/PinscreenImage.js +6 -0
- package/dist/components/image/PrismImage.d.ts +7 -0
- package/dist/components/image/PrismImage.d.ts.map +1 -0
- package/dist/components/image/PrismImage.js +6 -0
- package/dist/components/image/ProjectorImage.d.ts +7 -0
- package/dist/components/image/ProjectorImage.d.ts.map +1 -0
- package/dist/components/image/ProjectorImage.js +6 -0
- package/dist/components/image/ReliefImage.d.ts +7 -0
- package/dist/components/image/ReliefImage.d.ts.map +1 -0
- package/dist/components/image/ReliefImage.js +6 -0
- package/dist/components/image/RollImage.d.ts +7 -0
- package/dist/components/image/RollImage.d.ts.map +1 -0
- package/dist/components/image/RollImage.js +6 -0
- package/dist/components/image/ShardsImage.d.ts +126 -0
- package/dist/components/image/ShardsImage.d.ts.map +1 -0
- package/dist/components/image/ShardsImage.js +470 -0
- package/dist/components/image/core/contour.d.ts +126 -0
- package/dist/components/image/core/contour.d.ts.map +1 -0
- package/dist/components/image/core/contour.js +123 -0
- package/dist/components/image/core/engraving.d.ts +135 -0
- package/dist/components/image/core/engraving.d.ts.map +1 -0
- package/dist/components/image/core/engraving.js +163 -0
- package/dist/components/image/core/frost.d.ts +126 -0
- package/dist/components/image/core/frost.d.ts.map +1 -0
- package/dist/components/image/core/frost.js +156 -0
- package/dist/components/image/core/imageCore.d.ts +110 -0
- package/dist/components/image/core/imageCore.d.ts.map +1 -0
- package/dist/components/image/core/imageCore.js +269 -0
- package/dist/components/image/core/lenticular.d.ts +129 -0
- package/dist/components/image/core/lenticular.d.ts.map +1 -0
- package/dist/components/image/core/lenticular.js +132 -0
- package/dist/components/image/core/pinscreen.d.ts +126 -0
- package/dist/components/image/core/pinscreen.d.ts.map +1 -0
- package/dist/components/image/core/pinscreen.js +147 -0
- package/dist/components/image/core/prism.d.ts +120 -0
- package/dist/components/image/core/prism.d.ts.map +1 -0
- package/dist/components/image/core/prism.js +164 -0
- package/dist/components/image/core/projector.d.ts +135 -0
- package/dist/components/image/core/projector.d.ts.map +1 -0
- package/dist/components/image/core/projector.js +225 -0
- package/dist/components/image/core/relief.d.ts +111 -0
- package/dist/components/image/core/relief.d.ts.map +1 -0
- package/dist/components/image/core/relief.js +94 -0
- package/dist/components/image/core/roll.d.ts +114 -0
- package/dist/components/image/core/roll.d.ts.map +1 -0
- package/dist/components/image/core/roll.js +116 -0
- package/dist/components/image/imageVariant.d.ts +46 -0
- package/dist/components/image/imageVariant.d.ts.map +1 -0
- package/dist/components/image/imageVariant.js +128 -0
- package/dist/components/image/index.d.ts +22 -0
- package/dist/components/image/index.d.ts.map +1 -0
- package/dist/components/image/index.js +10 -0
- package/dist/components/image/pictureCycle.d.ts +15 -0
- package/dist/components/image/pictureCycle.d.ts.map +1 -0
- package/dist/components/image/pictureCycle.js +82 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +4 -0
- package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts +9 -7
- package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -1
- package/dist/components/volumetricClouds/VolumetricCloudsPass.js +39 -27
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -0
- package/dist/galleryRuntime.d.ts +57 -0
- package/dist/galleryRuntime.d.ts.map +1 -0
- package/dist/galleryRuntime.js +105 -0
- package/dist/hooks/useConfigLive.d.ts +1 -1
- package/dist/hooks/useConfigLive.d.ts.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/keyPad/KeyPadControls.d.ts +16 -0
- package/dist/keyPad/KeyPadControls.d.ts.map +1 -0
- package/dist/keyPad/KeyPadControls.js +176 -0
- package/dist/keyPad/index.d.ts +16 -0
- package/dist/keyPad/index.d.ts.map +1 -0
- package/dist/keyPad/index.js +8 -0
- package/dist/keyPad/keyBindings.d.ts +43 -0
- package/dist/keyPad/keyBindings.d.ts.map +1 -0
- package/dist/keyPad/keyBindings.js +92 -0
- package/dist/keyPad/keyPadAnimation.d.ts +28 -0
- package/dist/keyPad/keyPadAnimation.d.ts.map +1 -0
- package/dist/keyPad/keyPadAnimation.js +131 -0
- package/dist/keyPad/keyPadMotion.d.ts +68 -0
- package/dist/keyPad/keyPadMotion.d.ts.map +1 -0
- package/dist/keyPad/keyPadMotion.js +283 -0
- package/dist/keyPad/keyPadStore.d.ts +25 -0
- package/dist/keyPad/keyPadStore.d.ts.map +1 -0
- package/dist/keyPad/keyPadStore.js +63 -0
- package/dist/keyPad/types.d.ts +23 -0
- package/dist/keyPad/types.d.ts.map +1 -0
- package/dist/keyPad/types.js +9 -0
- package/dist/operations/catalogue/visibility.d.ts.map +1 -1
- package/dist/operations/catalogue/visibility.js +23 -1
- package/dist/shaders/clouds/CloudResolveMaterial.d.ts +2 -1
- package/dist/shaders/clouds/CloudResolveMaterial.d.ts.map +1 -1
- package/dist/shaders/clouds/CloudResolveMaterial.js +37 -12
- package/dist/shaders/clouds/CloudVolumeMaterial.d.ts +4 -0
- package/dist/shaders/clouds/CloudVolumeMaterial.d.ts.map +1 -1
- package/dist/shaders/clouds/CloudVolumeMaterial.js +15 -3
- package/dist/triggers/kinds/gallery.d.ts +2 -0
- package/dist/triggers/kinds/gallery.d.ts.map +1 -0
- package/dist/triggers/kinds/gallery.js +39 -0
- package/dist/triggers/kinds/index.d.ts +1 -0
- package/dist/triggers/kinds/index.d.ts.map +1 -1
- package/dist/triggers/kinds/index.js +1 -0
- package/dist/ui/UiLayers.d.ts +17 -1
- package/dist/ui/UiLayers.d.ts.map +1 -1
- package/dist/ui/UiLayers.js +76 -3
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// keyPadMotion — keyboard / KeyPad camera moves
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// What the mouse does to OrbitControls, driven by held keys instead. Two camera
|
|
6
|
+
// styles; the control mode picks the default one and Alt switches to the other:
|
|
7
|
+
// orbit: arrows → orbit (left-drag)
|
|
8
|
+
// fly: ↑ / ↓ → walk the camera forward / back (camera and orbit point
|
|
9
|
+
// together — not a zoom)
|
|
10
|
+
// ← / → → turn in place: the orbit point swings around the camera
|
|
11
|
+
// pan + arrows → pan (right-drag / ctrl-drag), in either style
|
|
12
|
+
// zoomIn/zoomOut → dolly (wheel)
|
|
13
|
+
// zoom slider → sets the orbit distance directly, between the zoom limits
|
|
14
|
+
// home → main view
|
|
15
|
+
//
|
|
16
|
+
// Moves the live camera only — nothing is written to the store. Each move ends
|
|
17
|
+
// with OrbitControls.update(), so the camera's own limits still clamp it, and
|
|
18
|
+
// the controls' enableRotate / enablePan / enableZoom are respected like the
|
|
19
|
+
// mouse respects them.
|
|
20
|
+
//
|
|
21
|
+
import { Spherical, Vector3 } from 'three';
|
|
22
|
+
import { cameraManager } from '../utils/CameraSingleton.js';
|
|
23
|
+
export const CONTROL_MODES = [
|
|
24
|
+
{ value: 'none', label: 'No keyboard' },
|
|
25
|
+
{ value: 'orbit', label: 'Orbit first' },
|
|
26
|
+
{ value: 'fly', label: 'Fly first' },
|
|
27
|
+
{ value: 'animation', label: 'Animation control' },
|
|
28
|
+
];
|
|
29
|
+
/** Fly style right now: the mode's default, flipped while Alt is held / latched. */
|
|
30
|
+
export const isFlying = (mode, held) => (mode === 'fly') !== held.has('alt');
|
|
31
|
+
/** Keys that move the camera while held (home is one-shot, pan is a modifier). */
|
|
32
|
+
export const HELD_MOVE_KEYS = ['up', 'down', 'left', 'right', 'zoomIn', 'zoomOut'];
|
|
33
|
+
/** Real keyboard → KeyPad key. Matched on KeyboardEvent.key. */
|
|
34
|
+
export const KEYBOARD_MAP = {
|
|
35
|
+
ArrowUp: 'up',
|
|
36
|
+
ArrowDown: 'down',
|
|
37
|
+
ArrowLeft: 'left',
|
|
38
|
+
ArrowRight: 'right',
|
|
39
|
+
'+': 'zoomIn',
|
|
40
|
+
'=': 'zoomIn',
|
|
41
|
+
'-': 'zoomOut',
|
|
42
|
+
'_': 'zoomOut',
|
|
43
|
+
Control: 'pan',
|
|
44
|
+
Alt: 'alt',
|
|
45
|
+
Home: 'home',
|
|
46
|
+
};
|
|
47
|
+
/** Shown on the KeyPad buttons' tooltips. */
|
|
48
|
+
export const KEY_HINTS = {
|
|
49
|
+
up: '↑',
|
|
50
|
+
down: '↓',
|
|
51
|
+
left: '←',
|
|
52
|
+
right: '→',
|
|
53
|
+
zoomIn: '+',
|
|
54
|
+
zoomOut: '−',
|
|
55
|
+
pan: 'Ctrl',
|
|
56
|
+
alt: 'Alt',
|
|
57
|
+
home: 'Home',
|
|
58
|
+
};
|
|
59
|
+
// Base rates at speed 1, per second.
|
|
60
|
+
const ORBIT_RAD_PER_SEC = Math.PI / 2; // 90° a second
|
|
61
|
+
const PAN_RADII_PER_SEC = 0.8; // fraction of the orbit distance
|
|
62
|
+
const ZOOM_PER_SEC = 1.6; // distance × e^(±1.6) a second
|
|
63
|
+
const _off = new Vector3();
|
|
64
|
+
const _sph = new Spherical();
|
|
65
|
+
const _right = new Vector3();
|
|
66
|
+
const _up = new Vector3();
|
|
67
|
+
const _worldUp = new Vector3(0, 1, 0);
|
|
68
|
+
const _orbitSph = new Spherical();
|
|
69
|
+
function liveRig() {
|
|
70
|
+
const cam = cameraManager.getCamera();
|
|
71
|
+
const oc = cameraManager.getControls();
|
|
72
|
+
return cam && oc && oc.enabled !== false ? { cam, oc } : null;
|
|
73
|
+
}
|
|
74
|
+
/** Orbit around the orbit point by (theta, phi) radians; the controls' limits clamp in update(). */
|
|
75
|
+
export function orbitBy(dTheta, dPhi) {
|
|
76
|
+
const rig = liveRig();
|
|
77
|
+
if (!rig)
|
|
78
|
+
return;
|
|
79
|
+
_orbitSph.setFromVector3(_off.copy(rig.cam.position).sub(rig.oc.target));
|
|
80
|
+
_orbitSph.theta += dTheta;
|
|
81
|
+
_orbitSph.phi += dPhi;
|
|
82
|
+
_orbitSph.makeSafe();
|
|
83
|
+
rig.cam.position.copy(rig.oc.target).add(_off.setFromSpherical(_orbitSph));
|
|
84
|
+
rig.cam.lookAt(rig.oc.target);
|
|
85
|
+
rig.oc.update?.();
|
|
86
|
+
}
|
|
87
|
+
/** Slide camera + orbit point together in the view plane (x right, y up), in metres. */
|
|
88
|
+
export function panBy(dx, dy) {
|
|
89
|
+
const rig = liveRig();
|
|
90
|
+
if (!rig || rig.oc.enablePan === false)
|
|
91
|
+
return;
|
|
92
|
+
rig.cam.updateMatrix();
|
|
93
|
+
_right.setFromMatrixColumn(rig.cam.matrix, 0).multiplyScalar(dx);
|
|
94
|
+
_up.setFromMatrixColumn(rig.cam.matrix, 1).multiplyScalar(dy);
|
|
95
|
+
_right.add(_up);
|
|
96
|
+
rig.cam.position.add(_right);
|
|
97
|
+
rig.oc.target.add(_right);
|
|
98
|
+
rig.oc.update?.();
|
|
99
|
+
}
|
|
100
|
+
/** Walk camera + orbit point along the view direction flattened onto the ground
|
|
101
|
+
* (height kept). Looking straight down, "forward" is the top of the screen. */
|
|
102
|
+
export function moveBy(d) {
|
|
103
|
+
const rig = liveRig();
|
|
104
|
+
if (!rig || rig.oc.enablePan === false)
|
|
105
|
+
return; // same rule as pan: it moves the orbit point
|
|
106
|
+
rig.cam.getWorldDirection(_right);
|
|
107
|
+
_right.y = 0;
|
|
108
|
+
if (_right.lengthSq() < 1e-8) {
|
|
109
|
+
rig.cam.updateMatrix();
|
|
110
|
+
_right.setFromMatrixColumn(rig.cam.matrix, 1);
|
|
111
|
+
_right.y = 0;
|
|
112
|
+
}
|
|
113
|
+
if (_right.lengthSq() < 1e-8)
|
|
114
|
+
return;
|
|
115
|
+
_right.normalize().multiplyScalar(d);
|
|
116
|
+
rig.cam.position.add(_right);
|
|
117
|
+
rig.oc.target.add(_right);
|
|
118
|
+
rig.oc.update?.();
|
|
119
|
+
}
|
|
120
|
+
// --- Zoom slider: distance ↔ 0…1 between the zoom limits --------------------------
|
|
121
|
+
//
|
|
122
|
+
// Log scale, like the wheel (each notch scales the distance), so the near end is
|
|
123
|
+
// as usable as the far end. t = 0 is the closest (minDistance), 1 the farthest.
|
|
124
|
+
/** maxDistance at / above this is the saved "no limit" (see CameraLimitsHelper). */
|
|
125
|
+
const NO_LIMIT = 1e6;
|
|
126
|
+
/** Far end of the slider when there is no max limit. */
|
|
127
|
+
const UNLIMITED_FAR = 1000;
|
|
128
|
+
const MIN_NEAR = 0.01;
|
|
129
|
+
export function zoomRange() {
|
|
130
|
+
const rig = liveRig();
|
|
131
|
+
if (!rig)
|
|
132
|
+
return null;
|
|
133
|
+
const distance = orbitDistance();
|
|
134
|
+
const near = Math.max(Number(rig.oc.minDistance) || 0, MIN_NEAR);
|
|
135
|
+
const maxD = Number(rig.oc.maxDistance);
|
|
136
|
+
let far = Number.isFinite(maxD) && maxD < NO_LIMIT ? maxD : Math.max(UNLIMITED_FAR, distance);
|
|
137
|
+
if (far <= near)
|
|
138
|
+
far = near * 1.0001;
|
|
139
|
+
return { near, far, distance, enabled: rig.oc.enableZoom !== false };
|
|
140
|
+
}
|
|
141
|
+
export function distanceToT(d, r) {
|
|
142
|
+
const t = (Math.log(d) - Math.log(r.near)) / (Math.log(r.far) - Math.log(r.near));
|
|
143
|
+
return Math.max(0, Math.min(1, t));
|
|
144
|
+
}
|
|
145
|
+
export function tToDistance(t, r) {
|
|
146
|
+
return Math.exp(Math.log(r.near) + Math.max(0, Math.min(1, t)) * (Math.log(r.far) - Math.log(r.near)));
|
|
147
|
+
}
|
|
148
|
+
/** Put the camera at `d` from the orbit point, same direction. Limits clamp in update(). */
|
|
149
|
+
export function setOrbitDistance(d) {
|
|
150
|
+
const rig = liveRig();
|
|
151
|
+
if (!rig || rig.oc.enableZoom === false)
|
|
152
|
+
return;
|
|
153
|
+
_off.copy(rig.cam.position).sub(rig.oc.target);
|
|
154
|
+
const len = _off.length();
|
|
155
|
+
if (len < 1e-9)
|
|
156
|
+
return;
|
|
157
|
+
rig.cam.position.copy(rig.oc.target).add(_off.multiplyScalar(d / len));
|
|
158
|
+
rig.oc.update?.();
|
|
159
|
+
}
|
|
160
|
+
/** Turn in place: swing the orbit point around the camera about world up (+ = right). */
|
|
161
|
+
export function turnBy(a) {
|
|
162
|
+
const rig = liveRig();
|
|
163
|
+
if (!rig || rig.oc.enablePan === false)
|
|
164
|
+
return; // same rule as move: it moves the orbit point
|
|
165
|
+
_off.copy(rig.oc.target).sub(rig.cam.position).applyAxisAngle(_worldUp, -a);
|
|
166
|
+
rig.oc.target.copy(rig.cam.position).add(_off);
|
|
167
|
+
rig.cam.lookAt(rig.oc.target);
|
|
168
|
+
rig.oc.update?.();
|
|
169
|
+
}
|
|
170
|
+
/** Scale the distance to the orbit point (<1 = closer). Limits clamp in update(). */
|
|
171
|
+
export function dollyBy(scale) {
|
|
172
|
+
const rig = liveRig();
|
|
173
|
+
if (!rig || rig.oc.enableZoom === false)
|
|
174
|
+
return;
|
|
175
|
+
_off.copy(rig.cam.position).sub(rig.oc.target);
|
|
176
|
+
_off.multiplyScalar(scale);
|
|
177
|
+
rig.cam.position.copy(rig.oc.target).add(_off);
|
|
178
|
+
rig.oc.update?.();
|
|
179
|
+
}
|
|
180
|
+
function orbitDistance() {
|
|
181
|
+
const rig = liveRig();
|
|
182
|
+
if (!rig)
|
|
183
|
+
return 0;
|
|
184
|
+
return _sph.setFromVector3(_off.copy(rig.cam.position).sub(rig.oc.target)).radius;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* One frame of camera motion.
|
|
188
|
+
* @param held keys down (modifiers included, latched or held)
|
|
189
|
+
* @param zoom zoom rate -1 … 1 (±1 from the +/− keys)
|
|
190
|
+
* @param fly fly style (else orbit) — see isFlying
|
|
191
|
+
* @param arrows false: the arrows drive something else (animation mode); zoom only
|
|
192
|
+
*/
|
|
193
|
+
export function stepKeyPad(held, zoom, dt, speed, fly, arrows = true) {
|
|
194
|
+
const rig = liveRig();
|
|
195
|
+
if (!rig)
|
|
196
|
+
return;
|
|
197
|
+
const x = arrows ? (held.has('right') ? 1 : 0) - (held.has('left') ? 1 : 0) : 0;
|
|
198
|
+
const y = arrows ? (held.has('up') ? 1 : 0) - (held.has('down') ? 1 : 0) : 0;
|
|
199
|
+
const z = zoom;
|
|
200
|
+
// Flying, the speed is the forward / back speed only: turn, pan and zoom keep
|
|
201
|
+
// their base rates. Orbiting, it scales everything.
|
|
202
|
+
const k = fly ? 1 : speed;
|
|
203
|
+
if (x || y) {
|
|
204
|
+
if (held.has('pan')) {
|
|
205
|
+
const d = orbitDistance() * PAN_RADII_PER_SEC * k * dt;
|
|
206
|
+
panBy(x * d, y * d);
|
|
207
|
+
}
|
|
208
|
+
else if (fly) {
|
|
209
|
+
// ↑ / ↓ walk, ← / → turn.
|
|
210
|
+
if (y)
|
|
211
|
+
moveBy(y * orbitDistance() * PAN_RADII_PER_SEC * speed * dt);
|
|
212
|
+
if (x)
|
|
213
|
+
turnBy(x * ORBIT_RAD_PER_SEC * dt);
|
|
214
|
+
}
|
|
215
|
+
else if (rig.oc.enableRotate !== false) {
|
|
216
|
+
// right → camera moves to its right around the orbit point (theta+),
|
|
217
|
+
// up → camera rises (phi−).
|
|
218
|
+
const a = ORBIT_RAD_PER_SEC * k * dt;
|
|
219
|
+
orbitBy(x * a, -y * a);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (z)
|
|
223
|
+
dollyBy(Math.exp(-z * ZOOM_PER_SEC * k * dt));
|
|
224
|
+
}
|
|
225
|
+
/** The live camera as a view, or null before the camera is up. */
|
|
226
|
+
export function captureView() {
|
|
227
|
+
const cam = cameraManager.getCamera();
|
|
228
|
+
const oc = cameraManager.getControls();
|
|
229
|
+
if (!cam || !oc)
|
|
230
|
+
return null;
|
|
231
|
+
const r = (n) => Math.round(n * 1000) / 1000;
|
|
232
|
+
return {
|
|
233
|
+
position: [r(cam.position.x), r(cam.position.y), r(cam.position.z)],
|
|
234
|
+
target: [r(oc.target.x), r(oc.target.y), r(oc.target.z)],
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
let viewRaf = 0;
|
|
238
|
+
const _fromPos = new Vector3();
|
|
239
|
+
const _fromTarget = new Vector3();
|
|
240
|
+
const _toPos = new Vector3();
|
|
241
|
+
const _toTarget = new Vector3();
|
|
242
|
+
const easeInOut = (t) => (t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2);
|
|
243
|
+
/** Glide camera and orbit point together to a view (a new glide replaces one in flight). */
|
|
244
|
+
export function glideToView(view, duration = 0.9) {
|
|
245
|
+
const cam = cameraManager.getCamera();
|
|
246
|
+
const oc = cameraManager.getControls();
|
|
247
|
+
if (!cam || !oc)
|
|
248
|
+
return;
|
|
249
|
+
cancelAnimationFrame(viewRaf);
|
|
250
|
+
_fromPos.copy(cam.position);
|
|
251
|
+
_fromTarget.copy(oc.target);
|
|
252
|
+
_toPos.set(...view.position);
|
|
253
|
+
_toTarget.set(...view.target);
|
|
254
|
+
const start = performance.now();
|
|
255
|
+
const step = () => {
|
|
256
|
+
const c = cameraManager.getCamera();
|
|
257
|
+
const o = cameraManager.getControls();
|
|
258
|
+
if (!c || !o)
|
|
259
|
+
return;
|
|
260
|
+
const t = Math.min((performance.now() - start) / (duration * 1000), 1);
|
|
261
|
+
const k = easeInOut(t);
|
|
262
|
+
c.position.lerpVectors(_fromPos, _toPos, k);
|
|
263
|
+
o.target.lerpVectors(_fromTarget, _toTarget, k);
|
|
264
|
+
c.lookAt(o.target);
|
|
265
|
+
o.update?.();
|
|
266
|
+
viewRaf = t < 1 ? requestAnimationFrame(step) : 0;
|
|
267
|
+
};
|
|
268
|
+
viewRaf = requestAnimationFrame(step);
|
|
269
|
+
}
|
|
270
|
+
/** Main view: glide the camera to the project's saved camera position. */
|
|
271
|
+
export function goToMainView(position) {
|
|
272
|
+
return cameraManager.animateCameraPosition(position);
|
|
273
|
+
}
|
|
274
|
+
/** Is this keyboard event aimed at a text field / editor, or already handled? */
|
|
275
|
+
export function isTypingTarget(e) {
|
|
276
|
+
if (e.defaultPrevented)
|
|
277
|
+
return true;
|
|
278
|
+
const el = e.target;
|
|
279
|
+
if (!el || !(el instanceof HTMLElement))
|
|
280
|
+
return false;
|
|
281
|
+
const tag = el.tagName;
|
|
282
|
+
return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable;
|
|
283
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { KeyPadControlMode, KeyPadKey, KeyPadModifier } from './keyPadMotion';
|
|
2
|
+
export interface KeyPadLiveState {
|
|
3
|
+
pressed: readonly KeyPadKey[];
|
|
4
|
+
/** A modifier latched on by clicking its pad button (Ctrl / Alt on the keyboard are momentary). */
|
|
5
|
+
latched: KeyPadModifier | null;
|
|
6
|
+
/** A control mode switched to by a key binding — over the saved one until changed again. */
|
|
7
|
+
modeOverride: KeyPadControlMode | null;
|
|
8
|
+
}
|
|
9
|
+
export declare const keyPadStore: {
|
|
10
|
+
get: () => KeyPadLiveState;
|
|
11
|
+
subscribe(fn: () => void): () => void;
|
|
12
|
+
press(key: KeyPadKey): void;
|
|
13
|
+
release(key: KeyPadKey): void;
|
|
14
|
+
/** Click on a modifier button: latch it, or unlatch it if it is the latched one. */
|
|
15
|
+
toggleModifier(m: KeyPadModifier): void;
|
|
16
|
+
/** Every key up (window blur, unmount). Keeps a latched modifier. */
|
|
17
|
+
releaseAll(): void;
|
|
18
|
+
/** Keys up and modifier unlatched (control mode changed). Keeps the mode override. */
|
|
19
|
+
reset(): void;
|
|
20
|
+
setModeOverride(mode: KeyPadControlMode | null): void;
|
|
21
|
+
};
|
|
22
|
+
export declare function useKeyPadState(): KeyPadLiveState;
|
|
23
|
+
/** Held keys with the latched modifier folded in. */
|
|
24
|
+
export declare function useKeyPadHeld(): ReadonlySet<KeyPadKey>;
|
|
25
|
+
//# sourceMappingURL=keyPadStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyPadStore.d.ts","sourceRoot":"","sources":["../../src/keyPad/keyPadStore.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEnF,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,mGAAmG;IACnG,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,4FAA4F;IAC5F,YAAY,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC1C;AAYD,eAAO,MAAM,WAAW;eACX,eAAe;kBACV,MAAM,IAAI,GAAG,MAAM,IAAI;eAI1B,SAAS;iBAGP,SAAS;IAGtB,oFAAoF;sBAClE,cAAc;IAGhC,qEAAqE;;IAIrE,sFAAsF;;0BAEhE,iBAAiB,GAAG,IAAI;CAGjD,CAAC;AAEF,wBAAgB,cAAc,IAAI,eAAe,CAEhD;AAED,qDAAqD;AACrD,wBAAgB,aAAa,IAAI,WAAW,CAAC,SAAS,CAAC,CAOtD"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// keyPadStore — which keys are held right now (live, never saved)
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// One store for both sources: the real keyboard (KeyPadControls) and an on-screen
|
|
6
|
+
// pad (the studio's KeyPad) press / release the same keys here, so a key held on
|
|
7
|
+
// the keyboard lights its button and a button held on screen moves the camera
|
|
8
|
+
// exactly like its key. Outside React state on purpose: the published viewer has
|
|
9
|
+
// no Redux, and the studio and the viewer share this.
|
|
10
|
+
//
|
|
11
|
+
import { useMemo, useSyncExternalStore } from 'react';
|
|
12
|
+
const EMPTY = { pressed: [], latched: null, modeOverride: null };
|
|
13
|
+
let state = EMPTY;
|
|
14
|
+
const listeners = new Set();
|
|
15
|
+
function set(next) {
|
|
16
|
+
if (next === state)
|
|
17
|
+
return;
|
|
18
|
+
state = next;
|
|
19
|
+
listeners.forEach(fn => fn());
|
|
20
|
+
}
|
|
21
|
+
export const keyPadStore = {
|
|
22
|
+
get: () => state,
|
|
23
|
+
subscribe(fn) {
|
|
24
|
+
listeners.add(fn);
|
|
25
|
+
return () => { listeners.delete(fn); };
|
|
26
|
+
},
|
|
27
|
+
press(key) {
|
|
28
|
+
if (!state.pressed.includes(key))
|
|
29
|
+
set({ ...state, pressed: [...state.pressed, key] });
|
|
30
|
+
},
|
|
31
|
+
release(key) {
|
|
32
|
+
if (state.pressed.includes(key))
|
|
33
|
+
set({ ...state, pressed: state.pressed.filter(k => k !== key) });
|
|
34
|
+
},
|
|
35
|
+
/** Click on a modifier button: latch it, or unlatch it if it is the latched one. */
|
|
36
|
+
toggleModifier(m) {
|
|
37
|
+
set({ ...state, latched: state.latched === m ? null : m });
|
|
38
|
+
},
|
|
39
|
+
/** Every key up (window blur, unmount). Keeps a latched modifier. */
|
|
40
|
+
releaseAll() {
|
|
41
|
+
if (state.pressed.length)
|
|
42
|
+
set({ ...state, pressed: [] });
|
|
43
|
+
},
|
|
44
|
+
/** Keys up and modifier unlatched (control mode changed). Keeps the mode override. */
|
|
45
|
+
reset() { set({ ...EMPTY, modeOverride: state.modeOverride }); },
|
|
46
|
+
setModeOverride(mode) {
|
|
47
|
+
if (mode !== state.modeOverride)
|
|
48
|
+
set({ ...state, modeOverride: mode });
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
export function useKeyPadState() {
|
|
52
|
+
return useSyncExternalStore(keyPadStore.subscribe, keyPadStore.get, keyPadStore.get);
|
|
53
|
+
}
|
|
54
|
+
/** Held keys with the latched modifier folded in. */
|
|
55
|
+
export function useKeyPadHeld() {
|
|
56
|
+
const s = useKeyPadState();
|
|
57
|
+
return useMemo(() => {
|
|
58
|
+
const held = new Set(s.pressed);
|
|
59
|
+
if (s.latched)
|
|
60
|
+
held.add(s.latched);
|
|
61
|
+
return held;
|
|
62
|
+
}, [s]);
|
|
63
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { KeyPadControlMode } from './keyPadMotion';
|
|
2
|
+
import type { KeyBinding } from './keyBindings';
|
|
3
|
+
/**
|
|
4
|
+
* A project's keyboard / KeyPad controller — saved as sceneSettings.keyPadSettings
|
|
5
|
+
* (scene_settings.key_pad_settings). Projects saved before it existed have none:
|
|
6
|
+
* read through resolveKeyPadSettings.
|
|
7
|
+
*/
|
|
8
|
+
export interface KeyPadSettings {
|
|
9
|
+
/** The on-screen KeyPad is shown (studio toolbar). */
|
|
10
|
+
visible: boolean;
|
|
11
|
+
/** What the keyboard drives — see KeyPadControlMode. */
|
|
12
|
+
mode: KeyPadControlMode;
|
|
13
|
+
/** General speed, 1–10 (× the base rates). Orbit: orbit / pan / zoom. Fly: forward / back only. Animation: playback. */
|
|
14
|
+
speed: number;
|
|
15
|
+
/** Animation control mode: the animations / clips the arrows drive (`seq:<id>` / `clip:<id>`). */
|
|
16
|
+
animations: string[];
|
|
17
|
+
/** Keys that run things (play, apply, effects, camera views, mode switches) — see keyBindings. */
|
|
18
|
+
bindings: KeyBinding[];
|
|
19
|
+
}
|
|
20
|
+
export declare const DEFAULT_KEYPAD_SETTINGS: KeyPadSettings;
|
|
21
|
+
/** Saved settings (possibly missing / partial / null) over the defaults. */
|
|
22
|
+
export declare const resolveKeyPadSettings: (s?: Partial<KeyPadSettings> | null) => KeyPadSettings;
|
|
23
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/keyPad/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC3B,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;IACjB,wDAAwD;IACxD,IAAI,EAAE,iBAAiB,CAAC;IACxB,wHAAwH;IACxH,KAAK,EAAE,MAAM,CAAC;IACd,kGAAkG;IAClG,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,kGAAkG;IAClG,QAAQ,EAAE,UAAU,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,uBAAuB,EAAE,cAMrC,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB,GAAI,IAAI,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,KAAG,cACzB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const DEFAULT_KEYPAD_SETTINGS = {
|
|
2
|
+
visible: false,
|
|
3
|
+
mode: 'orbit',
|
|
4
|
+
speed: 1,
|
|
5
|
+
animations: [],
|
|
6
|
+
bindings: [],
|
|
7
|
+
};
|
|
8
|
+
/** Saved settings (possibly missing / partial / null) over the defaults. */
|
|
9
|
+
export const resolveKeyPadSettings = (s) => ({ ...DEFAULT_KEYPAD_SETTINGS, ...(s ?? {}) });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/visibility.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/visibility.ts"],"names":[],"mappings":";AAiBA,wBA4BG"}
|
|
@@ -1,9 +1,20 @@
|
|
|
1
|
+
import { SceneActions } from '@3driseai/3drise-core';
|
|
1
2
|
import { defineOperation } from '../types.js';
|
|
2
3
|
const KEY = '__opVisible';
|
|
4
|
+
/**
|
|
5
|
+
* A whole scene object (a CreatedObject root) is shown / hidden through its settings, the
|
|
6
|
+
* same way an action's `visible` change is: a runtime patch layer (no store write). Its
|
|
7
|
+
* visibility-linked effects then play in and out (usePresentedVisibility) — writing
|
|
8
|
+
* Object3D.visible here would cut them. A model part has no effects: set directly.
|
|
9
|
+
*/
|
|
10
|
+
const objectIdOf = (target) => target?.userData?.id && target.userData.objectType ? String(target.userData.id) : null;
|
|
11
|
+
const layerOf = (id) => `op:visibility:${id}`;
|
|
12
|
+
/** Objects shown / hidden through a layer, by id — not on the Object3D: hiding can re-render it. */
|
|
13
|
+
const laid = new Set();
|
|
3
14
|
export default defineOperation({
|
|
4
15
|
value: 'visibility',
|
|
5
16
|
label: 'Show / hide',
|
|
6
|
-
description: 'Hide (or show) the targets instantly',
|
|
17
|
+
description: 'Hide (or show) the targets instantly — an object with visibility-linked effects plays them in / out',
|
|
7
18
|
channel: 'visual',
|
|
8
19
|
multi: true,
|
|
9
20
|
toggles: true,
|
|
@@ -12,11 +23,22 @@ export default defineOperation({
|
|
|
12
23
|
mode: { type: 'select', label: 'Make it', default: 'hide', options: [{ value: 'hide', label: 'Hidden' }, { value: 'show', label: 'Visible' }] },
|
|
13
24
|
},
|
|
14
25
|
apply(target, p) {
|
|
26
|
+
const id = objectIdOf(target);
|
|
27
|
+
if (id) {
|
|
28
|
+
laid.add(id);
|
|
29
|
+
SceneActions.setLayer(layerOf(id), { [id]: { meshSettings: { visible: p.mode === 'show' } } });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
15
32
|
if (target.userData[KEY] === undefined)
|
|
16
33
|
target.userData[KEY] = target.visible;
|
|
17
34
|
target.visible = p.mode === 'show';
|
|
18
35
|
},
|
|
19
36
|
revert(target) {
|
|
37
|
+
const id = objectIdOf(target);
|
|
38
|
+
if (id && laid.delete(id)) {
|
|
39
|
+
SceneActions.setLayer(layerOf(id), null);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
20
42
|
if (target.userData[KEY] === undefined)
|
|
21
43
|
return;
|
|
22
44
|
target.visible = target.userData[KEY];
|
|
@@ -7,7 +7,8 @@ export declare const CloudResolveMaterial: import("@react-three/fiber").Construc
|
|
|
7
7
|
u_invProj: THREE.Matrix4;
|
|
8
8
|
u_camWorld: THREE.Matrix4;
|
|
9
9
|
u_camPos: THREE.Vector3;
|
|
10
|
-
|
|
10
|
+
u_curSize: THREE.Vector2;
|
|
11
|
+
u_offset: THREE.Vector2;
|
|
11
12
|
u_blend: number;
|
|
12
13
|
u_proxyHeight: number;
|
|
13
14
|
u_valid: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudResolveMaterial.d.ts","sourceRoot":"","sources":["../../../src/shaders/clouds/CloudResolveMaterial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"CloudResolveMaterial.d.ts","sourceRoot":"","sources":["../../../src/shaders/clouds/CloudResolveMaterial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AA0F9D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;CAgBhC,CAAA;AAID,OAAO,QAAQ,oBAAoB,CAAC;IAClC,UAAU,aAAa;QACrB,oBAAoB,EAAE,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAA;KAChE;CACF"}
|
|
@@ -2,9 +2,20 @@ import * as THREE from 'three';
|
|
|
2
2
|
import { shaderMaterial } from '@react-three/drei';
|
|
3
3
|
import { extend } from '@react-three/fiber';
|
|
4
4
|
/**
|
|
5
|
-
* Temporal
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Temporal reconstruction for the layer path.
|
|
6
|
+
*
|
|
7
|
+
* The march runs at a quarter of the cloud buffer's pixels: each frame, every march
|
|
8
|
+
* texel traces ONE of the four buffer pixels under it, cycling through all four over
|
|
9
|
+
* four frames. This pass rebuilds the full buffer from that:
|
|
10
|
+
*
|
|
11
|
+
* - the pixel traced this frame takes the fresh sample, blended with its history
|
|
12
|
+
* to average out the march's per-frame step jitter;
|
|
13
|
+
* - the other three take their reprojected history, clamped to the neighbourhood
|
|
14
|
+
* of this frame's samples so a stale value cannot ghost far.
|
|
15
|
+
*
|
|
16
|
+
* So every pixel is re-traced every fourth frame, and the march costs a quarter of
|
|
17
|
+
* what it did — the same scheme production volumetric clouds use, at a milder ratio
|
|
18
|
+
* (they trace one in sixteen).
|
|
8
19
|
*
|
|
9
20
|
* Reprojection runs against a proxy surface at the layer's mid-height rather than a
|
|
10
21
|
* per-pixel cloud depth. That avoids a second render target for depth, and for a layer
|
|
@@ -20,18 +31,28 @@ precision highp float;
|
|
|
20
31
|
in vec2 vUv;
|
|
21
32
|
out vec4 outColor;
|
|
22
33
|
|
|
23
|
-
uniform sampler2D u_current;
|
|
24
|
-
uniform sampler2D u_history;
|
|
34
|
+
uniform sampler2D u_current; // the march, a quarter of this pass's pixels
|
|
35
|
+
uniform sampler2D u_history; // last frame's output, this pass's size
|
|
25
36
|
uniform mat4 u_prevViewProj;
|
|
26
37
|
uniform mat4 u_invProj, u_camWorld;
|
|
27
38
|
uniform vec3 u_camPos;
|
|
28
|
-
uniform vec2
|
|
29
|
-
uniform
|
|
39
|
+
uniform vec2 u_curSize; // march buffer size in texels
|
|
40
|
+
uniform vec2 u_offset; // which of the 2x2 pixels was traced this frame (0 or 1 each)
|
|
41
|
+
uniform float u_blend; // history weight on the freshly traced pixel
|
|
30
42
|
uniform float u_proxyHeight;
|
|
31
43
|
uniform float u_valid;
|
|
32
44
|
|
|
33
45
|
void main(){
|
|
34
|
-
|
|
46
|
+
ivec2 p = ivec2(gl_FragCoord.xy);
|
|
47
|
+
ivec2 q = p / 2;
|
|
48
|
+
ivec2 qMax = ivec2(u_curSize) - 1;
|
|
49
|
+
bool fresh = (p - q * 2) == ivec2(u_offset);
|
|
50
|
+
|
|
51
|
+
// This frame's samples sit on the centres of the traced pixels, so in march texel
|
|
52
|
+
// space this pixel's centre is at (p - offset) / 2 + 0.5. Bilinear there is an exact
|
|
53
|
+
// fetch for the traced pixel and an interpolation for the other three.
|
|
54
|
+
vec2 cUv = ((vec2(p) - u_offset) * 0.5 + 0.5) / u_curSize;
|
|
55
|
+
vec4 cur = texture(u_current, cUv);
|
|
35
56
|
|
|
36
57
|
if (u_valid < 0.5){ outColor = cur; return; }
|
|
37
58
|
|
|
@@ -53,13 +74,16 @@ void main(){
|
|
|
53
74
|
|
|
54
75
|
vec4 hist = texture(u_history, pUv);
|
|
55
76
|
|
|
56
|
-
|
|
77
|
+
// Neighbourhood of this frame's samples: the 3x3 march texels around the nearest one.
|
|
78
|
+
ivec2 n = clamp(ivec2(cUv * u_curSize), ivec2(0), qMax);
|
|
79
|
+
vec4 lo = vec4(1e9), hi = vec4(-1e9);
|
|
57
80
|
for (int y = -1; y <= 1; y++)
|
|
58
81
|
for (int x = -1; x <= 1; x++){
|
|
59
|
-
vec4 s =
|
|
82
|
+
vec4 s = texelFetch(u_current, clamp(n + ivec2(x, y), ivec2(0), qMax), 0);
|
|
60
83
|
lo = min(lo, s); hi = max(hi, s);
|
|
61
84
|
}
|
|
62
|
-
|
|
85
|
+
vec4 h = clamp(hist, lo, hi);
|
|
86
|
+
outColor = fresh ? mix(cur, h, u_blend) : h;
|
|
63
87
|
}
|
|
64
88
|
`;
|
|
65
89
|
export const CloudResolveMaterial = shaderMaterial({
|
|
@@ -69,7 +93,8 @@ export const CloudResolveMaterial = shaderMaterial({
|
|
|
69
93
|
u_invProj: new THREE.Matrix4(),
|
|
70
94
|
u_camWorld: new THREE.Matrix4(),
|
|
71
95
|
u_camPos: new THREE.Vector3(),
|
|
72
|
-
|
|
96
|
+
u_curSize: new THREE.Vector2(1, 1),
|
|
97
|
+
u_offset: new THREE.Vector2(0, 0),
|
|
73
98
|
u_blend: 0.9,
|
|
74
99
|
u_proxyHeight: 2400,
|
|
75
100
|
u_valid: 0
|
|
@@ -72,6 +72,8 @@ export declare const cloudVolumeDefaults: {
|
|
|
72
72
|
u_far: number;
|
|
73
73
|
u_resolution: THREE.Vector2;
|
|
74
74
|
u_screenSpace: number;
|
|
75
|
+
u_uvOffset: THREE.Vector2;
|
|
76
|
+
u_minStep: number;
|
|
75
77
|
};
|
|
76
78
|
export declare const CloudVolumeMaterial: import("@react-three/fiber").ConstructorRepresentation<THREE.ShaderMaterial & {
|
|
77
79
|
u_base: any;
|
|
@@ -142,6 +144,8 @@ export declare const CloudVolumeMaterial: import("@react-three/fiber").Construct
|
|
|
142
144
|
u_far: number;
|
|
143
145
|
u_resolution: THREE.Vector2;
|
|
144
146
|
u_screenSpace: number;
|
|
147
|
+
u_uvOffset: THREE.Vector2;
|
|
148
|
+
u_minStep: number;
|
|
145
149
|
}> & {
|
|
146
150
|
key: string;
|
|
147
151
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudVolumeMaterial.d.ts","sourceRoot":"","sources":["../../../src/shaders/clouds/CloudVolumeMaterial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"CloudVolumeMaterial.d.ts","sourceRoot":"","sources":["../../../src/shaders/clouds/CloudVolumeMaterial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAiO9D,MAAM,WAAW,0BAA0B;IACzC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+E/B,CAAA;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAwD,CAAA;AAIxF,OAAO,QAAQ,oBAAoB,CAAC;IAClC,UAAU,aAAa;QACrB,mBAAmB,EAAE,YAAY,CAAC,OAAO,mBAAmB,CAAC,CAAA;KAC9D;CACF"}
|
|
@@ -40,6 +40,12 @@ uniform vec2 u_resolution;
|
|
|
40
40
|
uniform int u_steps;
|
|
41
41
|
uniform float u_stepGrowth, u_maxSpan, u_fogDensity, u_detailFade;
|
|
42
42
|
uniform float u_screenSpace;
|
|
43
|
+
// Layer path only. The march runs at a quarter of the cloud buffer's pixels and each
|
|
44
|
+
// frame picks one of the four half-res pixels under every march texel; this shifts the
|
|
45
|
+
// ray onto that pixel's centre. The resolve pass rebuilds the full buffer from it.
|
|
46
|
+
uniform vec2 u_uvOffset;
|
|
47
|
+
// Floor on the fine step, in metres, from the detail noise size (see applyDeckUniforms).
|
|
48
|
+
uniform float u_minStep;
|
|
43
49
|
|
|
44
50
|
// Lightning. Declared here rather than in the shared cloudUniforms chunk so the
|
|
45
51
|
// exported cloudField, which host apps pull into their own surface materials for
|
|
@@ -59,7 +65,7 @@ float ign(vec2 p){
|
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
void main(){
|
|
62
|
-
vec2 uv = (u_screenSpace > 0.5) ? vUv : (gl_FragCoord.xy / u_resolution);
|
|
68
|
+
vec2 uv = (u_screenSpace > 0.5) ? (vUv + u_uvOffset) : (gl_FragCoord.xy / u_resolution);
|
|
63
69
|
vec2 ndc = uv * 2.0 - 1.0;
|
|
64
70
|
|
|
65
71
|
vec4 vp = u_invProj * vec4(ndc, -1.0, 1.0);
|
|
@@ -98,7 +104,11 @@ void main(){
|
|
|
98
104
|
// spans 100 km; dividing that by the step budget gives kilometre steps and every
|
|
99
105
|
// feature dissolves into fog. Empty space is skipped 2.8x coarser, and the step
|
|
100
106
|
// grows with distance to hold screen-space error roughly constant.
|
|
101
|
-
|
|
107
|
+
//
|
|
108
|
+
// The floor is the other half: a step much finer than the detail noise samples
|
|
109
|
+
// the same erosion feature many times over. On a shallow deck the depth-derived
|
|
110
|
+
// step can be a fraction of that, which costs samples and buys nothing visible.
|
|
111
|
+
float dt0 = min(max(thick * 2.0 / float(u_steps), u_minStep), span / 8.0);
|
|
102
112
|
dt0 = max(dt0, thick * 0.004);
|
|
103
113
|
float big = dt0 * 2.8;
|
|
104
114
|
|
|
@@ -279,7 +289,9 @@ export const cloudVolumeDefaults = {
|
|
|
279
289
|
u_near: 1,
|
|
280
290
|
u_far: 100000,
|
|
281
291
|
u_resolution: new THREE.Vector2(1, 1),
|
|
282
|
-
u_screenSpace: 0
|
|
292
|
+
u_screenSpace: 0,
|
|
293
|
+
u_uvOffset: new THREE.Vector2(0, 0),
|
|
294
|
+
u_minStep: 0
|
|
283
295
|
};
|
|
284
296
|
export const CloudVolumeMaterial = shaderMaterial(cloudVolumeDefaults, vertex, fragment);
|
|
285
297
|
extend({ CloudVolumeMaterial });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gallery.d.ts","sourceRoot":"","sources":["../../../src/triggers/kinds/gallery.ts"],"names":[],"mappings":""}
|