angular-three 0.0.7 → 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/angular-three.mjs +1 -1
- package/esm2020/index.mjs +2 -35
- package/esm2020/lib/canvas.mjs +141 -128
- package/esm2020/lib/di/catalogue.mjs +7 -0
- package/esm2020/lib/directives/args.mjs +37 -17
- package/esm2020/lib/directives/repeat.mjs +5 -8
- package/esm2020/lib/events.mjs +341 -52
- package/esm2020/lib/loader.mjs +55 -0
- package/esm2020/lib/loop.mjs +137 -0
- package/esm2020/lib/renderer/di.mjs +3 -0
- package/esm2020/lib/renderer/enums.mjs +2 -0
- package/esm2020/lib/renderer/provider.mjs +19 -0
- package/esm2020/lib/renderer/renderer.mjs +293 -0
- package/esm2020/lib/renderer/state.mjs +350 -0
- package/esm2020/lib/renderer/utils.mjs +177 -0
- package/esm2020/lib/stores/rx-store.mjs +99 -0
- package/esm2020/lib/stores/store.mjs +190 -239
- package/esm2020/lib/types.mjs +1 -1
- package/esm2020/lib/utils/apply-props.mjs +37 -80
- package/esm2020/lib/utils/attach.mjs +29 -0
- package/esm2020/lib/utils/instance.mjs +43 -28
- package/esm2020/lib/utils/is.mjs +7 -11
- package/esm2020/lib/utils/make.mjs +30 -10
- package/esm2020/lib/utils/update.mjs +37 -0
- package/esm2020/lib/web/events.mjs +68 -0
- package/fesm2015/angular-three.mjs +2053 -2046
- package/fesm2015/angular-three.mjs.map +1 -1
- package/fesm2020/angular-three.mjs +2003 -1990
- package/fesm2020/angular-three.mjs.map +1 -1
- package/index.d.ts +1 -34
- package/lib/canvas.d.ts +29 -28
- package/lib/di/catalogue.d.ts +3 -0
- package/lib/directives/args.d.ts +8 -12
- package/lib/events.d.ts +7 -2
- package/lib/loader.d.ts +15 -0
- package/lib/{utils/loop.d.ts → loop.d.ts} +7 -6
- package/lib/renderer/di.d.ts +2 -0
- package/lib/renderer/enums.d.ts +25 -0
- package/lib/renderer/provider.d.ts +25 -0
- package/lib/renderer/renderer.d.ts +49 -0
- package/lib/renderer/state.d.ts +59 -0
- package/lib/renderer/utils.d.ts +20 -0
- package/lib/stores/rx-store.d.ts +17 -0
- package/lib/stores/store.d.ts +6 -23
- package/lib/types.d.ts +182 -191
- package/lib/utils/apply-props.d.ts +2 -6
- package/lib/utils/attach.d.ts +3 -0
- package/lib/utils/instance.d.ts +3 -3
- package/lib/utils/is.d.ts +6 -10
- package/lib/utils/make.d.ts +5 -2
- package/lib/utils/update.d.ts +4 -0
- package/lib/web/events.d.ts +4 -0
- package/package.json +30 -99
- package/attributes/README.md +0 -3
- package/attributes/index.d.ts +0 -22
- package/attributes/lib/buffer-attribute/buffer-attribute.d.ts +0 -8
- package/attributes/lib/color-attribute/color-attribute.d.ts +0 -8
- package/attributes/lib/common.d.ts +0 -1
- package/attributes/lib/float16-buffer-attribute/float16-buffer-attribute.d.ts +0 -8
- package/attributes/lib/float32-buffer-attribute/float32-buffer-attribute.d.ts +0 -8
- package/attributes/lib/float64-buffer-attribute/float64-buffer-attribute.d.ts +0 -8
- package/attributes/lib/fog-attribute/fog-attribute.d.ts +0 -8
- package/attributes/lib/fog-exp2-attribute/fog-exp2-attribute.d.ts +0 -8
- package/attributes/lib/instanced-buffer-attribute/instanced-buffer-attribute.d.ts +0 -8
- package/attributes/lib/int16-buffer-attribute/int16-buffer-attribute.d.ts +0 -8
- package/attributes/lib/int32-buffer-attribute/int32-buffer-attribute.d.ts +0 -8
- package/attributes/lib/int8-buffer-attribute/int8-buffer-attribute.d.ts +0 -8
- package/attributes/lib/interleaved-buffer-attribute/interleaved-buffer-attribute.d.ts +0 -8
- package/attributes/lib/matrix3-attribute/matrix3-attribute.d.ts +0 -8
- package/attributes/lib/matrix4-attribute/matrix4-attribute.d.ts +0 -8
- package/attributes/lib/uint16-buffer-attribute/uint16-buffer-attribute.d.ts +0 -8
- package/attributes/lib/uint32-buffer-attribute/uint32-buffer-attribute.d.ts +0 -8
- package/attributes/lib/uint8-buffer-attribute/uint8-buffer-attribute.d.ts +0 -8
- package/attributes/lib/uint8-clamped-buffer-attribute/uint8-clamped-buffer-attribute.d.ts +0 -8
- package/attributes/lib/value-attribute/value-attribute.d.ts +0 -8
- package/attributes/lib/vector2-attribute/vector2-attribute.d.ts +0 -8
- package/attributes/lib/vector3-attribute/vector3-attribute.d.ts +0 -8
- package/attributes/lib/vector4-attribute/vector4-attribute.d.ts +0 -8
- package/audios/README.md +0 -3
- package/audios/index.d.ts +0 -3
- package/audios/lib/audio/audio.d.ts +0 -49
- package/audios/lib/audio-listener/audio-listener.d.ts +0 -35
- package/audios/lib/common.d.ts +0 -3
- package/audios/lib/positional-audio/positional-audio.d.ts +0 -49
- package/cameras/README.md +0 -3
- package/cameras/index.d.ts +0 -5
- package/cameras/lib/array-camera/array-camera.d.ts +0 -56
- package/cameras/lib/common.d.ts +0 -3
- package/cameras/lib/cube-camera/cube-camera.d.ts +0 -36
- package/cameras/lib/orthographic-camera/orthographic-camera.d.ts +0 -54
- package/cameras/lib/perspective-camera/perspective-camera.d.ts +0 -55
- package/cameras/lib/stereo-camera/stereo-camera.d.ts +0 -42
- package/esm2020/attributes/angular-three-attributes.mjs +0 -5
- package/esm2020/attributes/index.mjs +0 -24
- package/esm2020/attributes/lib/buffer-attribute/buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/color-attribute/color-attribute.mjs +0 -26
- package/esm2020/attributes/lib/common.mjs +0 -13
- package/esm2020/attributes/lib/float16-buffer-attribute/float16-buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/float32-buffer-attribute/float32-buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/float64-buffer-attribute/float64-buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/fog-attribute/fog-attribute.mjs +0 -26
- package/esm2020/attributes/lib/fog-exp2-attribute/fog-exp2-attribute.mjs +0 -26
- package/esm2020/attributes/lib/instanced-buffer-attribute/instanced-buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/int16-buffer-attribute/int16-buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/int32-buffer-attribute/int32-buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/int8-buffer-attribute/int8-buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/interleaved-buffer-attribute/interleaved-buffer-attribute.mjs +0 -30
- package/esm2020/attributes/lib/matrix3-attribute/matrix3-attribute.mjs +0 -26
- package/esm2020/attributes/lib/matrix4-attribute/matrix4-attribute.mjs +0 -26
- package/esm2020/attributes/lib/uint16-buffer-attribute/uint16-buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/uint32-buffer-attribute/uint32-buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/uint8-buffer-attribute/uint8-buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/uint8-clamped-buffer-attribute/uint8-clamped-buffer-attribute.mjs +0 -26
- package/esm2020/attributes/lib/value-attribute/value-attribute.mjs +0 -28
- package/esm2020/attributes/lib/vector2-attribute/vector2-attribute.mjs +0 -26
- package/esm2020/attributes/lib/vector3-attribute/vector3-attribute.mjs +0 -26
- package/esm2020/attributes/lib/vector4-attribute/vector4-attribute.mjs +0 -26
- package/esm2020/audios/angular-three-audios.mjs +0 -5
- package/esm2020/audios/index.mjs +0 -5
- package/esm2020/audios/lib/audio/audio.mjs +0 -45
- package/esm2020/audios/lib/audio-listener/audio-listener.mjs +0 -38
- package/esm2020/audios/lib/common.mjs +0 -54
- package/esm2020/audios/lib/positional-audio/positional-audio.mjs +0 -45
- package/esm2020/cameras/angular-three-cameras.mjs +0 -5
- package/esm2020/cameras/index.mjs +0 -7
- package/esm2020/cameras/lib/array-camera/array-camera.mjs +0 -44
- package/esm2020/cameras/lib/common.mjs +0 -54
- package/esm2020/cameras/lib/cube-camera/cube-camera.mjs +0 -30
- package/esm2020/cameras/lib/orthographic-camera/orthographic-camera.mjs +0 -42
- package/esm2020/cameras/lib/perspective-camera/perspective-camera.mjs +0 -43
- package/esm2020/cameras/lib/stereo-camera/stereo-camera.mjs +0 -38
- package/esm2020/geometries/angular-three-geometries.mjs +0 -5
- package/esm2020/geometries/index.mjs +0 -25
- package/esm2020/geometries/lib/box-geometry/box-geometry.mjs +0 -26
- package/esm2020/geometries/lib/buffer-geometry/buffer-geometry.mjs +0 -26
- package/esm2020/geometries/lib/capsule-geometry/capsule-geometry.mjs +0 -26
- package/esm2020/geometries/lib/circle-geometry/circle-geometry.mjs +0 -26
- package/esm2020/geometries/lib/common.mjs +0 -13
- package/esm2020/geometries/lib/cone-geometry/cone-geometry.mjs +0 -26
- package/esm2020/geometries/lib/cylinder-geometry/cylinder-geometry.mjs +0 -26
- package/esm2020/geometries/lib/dodecahedron-geometry/dodecahedron-geometry.mjs +0 -26
- package/esm2020/geometries/lib/edges-geometry/edges-geometry.mjs +0 -26
- package/esm2020/geometries/lib/extrude-geometry/extrude-geometry.mjs +0 -26
- package/esm2020/geometries/lib/icosahedron-geometry/icosahedron-geometry.mjs +0 -26
- package/esm2020/geometries/lib/instanced-buffer-geometry/instanced-buffer-geometry.mjs +0 -26
- package/esm2020/geometries/lib/lathe-geometry/lathe-geometry.mjs +0 -26
- package/esm2020/geometries/lib/octahedron-geometry/octahedron-geometry.mjs +0 -26
- package/esm2020/geometries/lib/plane-geometry/plane-geometry.mjs +0 -26
- package/esm2020/geometries/lib/polyhedron-geometry/polyhedron-geometry.mjs +0 -26
- package/esm2020/geometries/lib/ring-geometry/ring-geometry.mjs +0 -26
- package/esm2020/geometries/lib/shape-geometry/shape-geometry.mjs +0 -26
- package/esm2020/geometries/lib/sphere-geometry/sphere-geometry.mjs +0 -26
- package/esm2020/geometries/lib/tetrahedron-geometry/tetrahedron-geometry.mjs +0 -26
- package/esm2020/geometries/lib/torus-geometry/torus-geometry.mjs +0 -26
- package/esm2020/geometries/lib/torus-knot-geometry/torus-knot-geometry.mjs +0 -26
- package/esm2020/geometries/lib/tube-geometry/tube-geometry.mjs +0 -26
- package/esm2020/geometries/lib/wireframe-geometry/wireframe-geometry.mjs +0 -26
- package/esm2020/helpers/angular-three-helpers.mjs +0 -5
- package/esm2020/helpers/index.mjs +0 -15
- package/esm2020/helpers/lib/arrow-helper/arrow-helper.mjs +0 -26
- package/esm2020/helpers/lib/axes-helper/axes-helper.mjs +0 -26
- package/esm2020/helpers/lib/box-helper/box-helper.mjs +0 -36
- package/esm2020/helpers/lib/box3-helper/box3-helper.mjs +0 -36
- package/esm2020/helpers/lib/camera-helper/camera-helper.mjs +0 -36
- package/esm2020/helpers/lib/common.mjs +0 -13
- package/esm2020/helpers/lib/directional-light-helper/directional-light-helper.mjs +0 -36
- package/esm2020/helpers/lib/grid-helper/grid-helper.mjs +0 -26
- package/esm2020/helpers/lib/hemisphere-light-helper/hemisphere-light-helper.mjs +0 -36
- package/esm2020/helpers/lib/plane-helper/plane-helper.mjs +0 -36
- package/esm2020/helpers/lib/point-light-helper/point-light-helper.mjs +0 -36
- package/esm2020/helpers/lib/polar-grid-helper/polar-grid-helper.mjs +0 -26
- package/esm2020/helpers/lib/skeleton-helper/skeleton-helper.mjs +0 -36
- package/esm2020/helpers/lib/spot-light-helper/spot-light-helper.mjs +0 -36
- package/esm2020/lib/di/resize.mjs +0 -19
- package/esm2020/lib/di/window.mjs +0 -13
- package/esm2020/lib/directives/cursor.mjs +0 -35
- package/esm2020/lib/instance.mjs +0 -368
- package/esm2020/lib/pipes/math.mjs +0 -15
- package/esm2020/lib/pipes/pi.mjs +0 -14
- package/esm2020/lib/pipes/radian.mjs +0 -14
- package/esm2020/lib/pipes/side.mjs +0 -22
- package/esm2020/lib/ref.mjs +0 -15
- package/esm2020/lib/services/loader.mjs +0 -45
- package/esm2020/lib/services/resize.mjs +0 -127
- package/esm2020/lib/stores/component-store.mjs +0 -137
- package/esm2020/lib/utils/build-graph.mjs +0 -15
- package/esm2020/lib/utils/camera.mjs +0 -28
- package/esm2020/lib/utils/capitalize.mjs +0 -4
- package/esm2020/lib/utils/check-update.mjs +0 -22
- package/esm2020/lib/utils/events.mjs +0 -353
- package/esm2020/lib/utils/get-instance-local-state.mjs +0 -6
- package/esm2020/lib/utils/inject.mjs +0 -18
- package/esm2020/lib/utils/loop.mjs +0 -139
- package/esm2020/lib/utils/mutate.mjs +0 -24
- package/esm2020/lib/utils/proxy.mjs +0 -99
- package/esm2020/lib/utils/renderer.mjs +0 -15
- package/esm2020/lights/angular-three-lights.mjs +0 -5
- package/esm2020/lights/index.mjs +0 -11
- package/esm2020/lights/lib/ambient-light/ambient-light.mjs +0 -30
- package/esm2020/lights/lib/ambient-light-probe/ambient-light-probe.mjs +0 -30
- package/esm2020/lights/lib/common.mjs +0 -54
- package/esm2020/lights/lib/directional-light/directional-light.mjs +0 -30
- package/esm2020/lights/lib/hemisphere-light/hemisphere-light.mjs +0 -30
- package/esm2020/lights/lib/hemisphere-light-probe/hemisphere-light-probe.mjs +0 -30
- package/esm2020/lights/lib/light-probe/light-probe.mjs +0 -30
- package/esm2020/lights/lib/point-light/point-light.mjs +0 -30
- package/esm2020/lights/lib/rect-area-light/rect-area-light.mjs +0 -30
- package/esm2020/lights/lib/spot-light/spot-light.mjs +0 -42
- package/esm2020/materials/angular-three-materials.mjs +0 -5
- package/esm2020/materials/index.mjs +0 -19
- package/esm2020/materials/lib/common.mjs +0 -13
- package/esm2020/materials/lib/line-basic-material/line-basic-material.mjs +0 -77
- package/esm2020/materials/lib/line-dashed-material/line-dashed-material.mjs +0 -80
- package/esm2020/materials/lib/mesh-basic-material/mesh-basic-material.mjs +0 -89
- package/esm2020/materials/lib/mesh-depth-material/mesh-depth-material.mjs +0 -80
- package/esm2020/materials/lib/mesh-distance-material/mesh-distance-material.mjs +0 -80
- package/esm2020/materials/lib/mesh-lambert-material/mesh-lambert-material.mjs +0 -100
- package/esm2020/materials/lib/mesh-matcap-material/mesh-matcap-material.mjs +0 -86
- package/esm2020/materials/lib/mesh-normal-material/mesh-normal-material.mjs +0 -83
- package/esm2020/materials/lib/mesh-phong-material/mesh-phong-material.mjs +0 -103
- package/esm2020/materials/lib/mesh-physical-material/mesh-physical-material.mjs +0 -119
- package/esm2020/materials/lib/mesh-standard-material/mesh-standard-material.mjs +0 -100
- package/esm2020/materials/lib/mesh-toon-material/mesh-toon-material.mjs +0 -96
- package/esm2020/materials/lib/points-material/points-material.mjs +0 -78
- package/esm2020/materials/lib/raw-shader-material/raw-shader-material.mjs +0 -83
- package/esm2020/materials/lib/shader-material/shader-material.mjs +0 -83
- package/esm2020/materials/lib/shadow-material/shadow-material.mjs +0 -74
- package/esm2020/materials/lib/sprite-material/sprite-material.mjs +0 -78
- package/esm2020/objects/angular-three-objects.mjs +0 -5
- package/esm2020/objects/index.mjs +0 -14
- package/esm2020/objects/lib/bone/bone.mjs +0 -27
- package/esm2020/objects/lib/common.mjs +0 -54
- package/esm2020/objects/lib/group/group.mjs +0 -27
- package/esm2020/objects/lib/instanced-mesh/instanced-mesh.mjs +0 -40
- package/esm2020/objects/lib/line/line.mjs +0 -30
- package/esm2020/objects/lib/line-loop/line-loop.mjs +0 -30
- package/esm2020/objects/lib/line-segments/line-segments.mjs +0 -30
- package/esm2020/objects/lib/lod/lod.mjs +0 -30
- package/esm2020/objects/lib/mesh/mesh.mjs +0 -30
- package/esm2020/objects/lib/points/points.mjs +0 -30
- package/esm2020/objects/lib/skeleton/skeleton.mjs +0 -41
- package/esm2020/objects/lib/skinned-mesh/skinned-mesh.mjs +0 -39
- package/esm2020/objects/lib/sprite/sprite.mjs +0 -30
- package/esm2020/primitives/angular-three-primitives.mjs +0 -5
- package/esm2020/primitives/index.mjs +0 -3
- package/esm2020/primitives/lib/common.mjs +0 -54
- package/esm2020/primitives/lib/object-primitive/object-primitive.mjs +0 -27
- package/esm2020/primitives/lib/primitive/primitive.mjs +0 -38
- package/esm2020/stats/angular-three-stats.mjs +0 -5
- package/esm2020/stats/index.mjs +0 -2
- package/esm2020/stats/lib/stats/stats.mjs +0 -54
- package/esm2020/textures/angular-three-textures.mjs +0 -5
- package/esm2020/textures/index.mjs +0 -12
- package/esm2020/textures/lib/canvas-texture/canvas-texture.mjs +0 -26
- package/esm2020/textures/lib/common.mjs +0 -13
- package/esm2020/textures/lib/compressed-array-texture/compressed-array-texture.mjs +0 -26
- package/esm2020/textures/lib/compressed-texture/compressed-texture.mjs +0 -26
- package/esm2020/textures/lib/cube-texture/cube-texture.mjs +0 -26
- package/esm2020/textures/lib/data-array-texture/data-array-texture.mjs +0 -26
- package/esm2020/textures/lib/data-texture/data-texture.mjs +0 -26
- package/esm2020/textures/lib/data3-dtexture/data3-dtexture.mjs +0 -26
- package/esm2020/textures/lib/depth-texture/depth-texture.mjs +0 -26
- package/esm2020/textures/lib/framebuffer-texture/framebuffer-texture.mjs +0 -26
- package/esm2020/textures/lib/video-texture/video-texture.mjs +0 -26
- package/fesm2015/angular-three-attributes.mjs +0 -475
- package/fesm2015/angular-three-attributes.mjs.map +0 -1
- package/fesm2015/angular-three-audios.mjs +0 -179
- package/fesm2015/angular-three-audios.mjs.map +0 -1
- package/fesm2015/angular-three-cameras.mjs +0 -236
- package/fesm2015/angular-three-cameras.mjs.map +0 -1
- package/fesm2015/angular-three-geometries.mjs +0 -488
- package/fesm2015/angular-three-geometries.mjs.map +0 -1
- package/fesm2015/angular-three-helpers.mjs +0 -378
- package/fesm2015/angular-three-helpers.mjs.map +0 -1
- package/fesm2015/angular-three-lights.mjs +0 -297
- package/fesm2015/angular-three-lights.mjs.map +0 -1
- package/fesm2015/angular-three-materials.mjs +0 -1415
- package/fesm2015/angular-three-materials.mjs.map +0 -1
- package/fesm2015/angular-three-objects.mjs +0 -381
- package/fesm2015/angular-three-objects.mjs.map +0 -1
- package/fesm2015/angular-three-primitives.mjs +0 -120
- package/fesm2015/angular-three-primitives.mjs.map +0 -1
- package/fesm2015/angular-three-stats.mjs +0 -62
- package/fesm2015/angular-three-stats.mjs.map +0 -1
- package/fesm2015/angular-three-textures.mjs +0 -228
- package/fesm2015/angular-three-textures.mjs.map +0 -1
- package/fesm2020/angular-three-attributes.mjs +0 -475
- package/fesm2020/angular-three-attributes.mjs.map +0 -1
- package/fesm2020/angular-three-audios.mjs +0 -179
- package/fesm2020/angular-three-audios.mjs.map +0 -1
- package/fesm2020/angular-three-cameras.mjs +0 -236
- package/fesm2020/angular-three-cameras.mjs.map +0 -1
- package/fesm2020/angular-three-geometries.mjs +0 -488
- package/fesm2020/angular-three-geometries.mjs.map +0 -1
- package/fesm2020/angular-three-helpers.mjs +0 -378
- package/fesm2020/angular-three-helpers.mjs.map +0 -1
- package/fesm2020/angular-three-lights.mjs +0 -297
- package/fesm2020/angular-three-lights.mjs.map +0 -1
- package/fesm2020/angular-three-materials.mjs +0 -1415
- package/fesm2020/angular-three-materials.mjs.map +0 -1
- package/fesm2020/angular-three-objects.mjs +0 -381
- package/fesm2020/angular-three-objects.mjs.map +0 -1
- package/fesm2020/angular-three-primitives.mjs +0 -120
- package/fesm2020/angular-three-primitives.mjs.map +0 -1
- package/fesm2020/angular-three-stats.mjs +0 -62
- package/fesm2020/angular-three-stats.mjs.map +0 -1
- package/fesm2020/angular-three-textures.mjs +0 -228
- package/fesm2020/angular-three-textures.mjs.map +0 -1
- package/geometries/README.md +0 -3
- package/geometries/index.d.ts +0 -23
- package/geometries/lib/box-geometry/box-geometry.d.ts +0 -8
- package/geometries/lib/buffer-geometry/buffer-geometry.d.ts +0 -8
- package/geometries/lib/capsule-geometry/capsule-geometry.d.ts +0 -8
- package/geometries/lib/circle-geometry/circle-geometry.d.ts +0 -8
- package/geometries/lib/common.d.ts +0 -1
- package/geometries/lib/cone-geometry/cone-geometry.d.ts +0 -8
- package/geometries/lib/cylinder-geometry/cylinder-geometry.d.ts +0 -8
- package/geometries/lib/dodecahedron-geometry/dodecahedron-geometry.d.ts +0 -8
- package/geometries/lib/edges-geometry/edges-geometry.d.ts +0 -8
- package/geometries/lib/extrude-geometry/extrude-geometry.d.ts +0 -8
- package/geometries/lib/icosahedron-geometry/icosahedron-geometry.d.ts +0 -8
- package/geometries/lib/instanced-buffer-geometry/instanced-buffer-geometry.d.ts +0 -8
- package/geometries/lib/lathe-geometry/lathe-geometry.d.ts +0 -8
- package/geometries/lib/octahedron-geometry/octahedron-geometry.d.ts +0 -8
- package/geometries/lib/plane-geometry/plane-geometry.d.ts +0 -8
- package/geometries/lib/polyhedron-geometry/polyhedron-geometry.d.ts +0 -8
- package/geometries/lib/ring-geometry/ring-geometry.d.ts +0 -8
- package/geometries/lib/shape-geometry/shape-geometry.d.ts +0 -8
- package/geometries/lib/sphere-geometry/sphere-geometry.d.ts +0 -8
- package/geometries/lib/tetrahedron-geometry/tetrahedron-geometry.d.ts +0 -8
- package/geometries/lib/torus-geometry/torus-geometry.d.ts +0 -8
- package/geometries/lib/torus-knot-geometry/torus-knot-geometry.d.ts +0 -8
- package/geometries/lib/tube-geometry/tube-geometry.d.ts +0 -8
- package/geometries/lib/wireframe-geometry/wireframe-geometry.d.ts +0 -8
- package/helpers/README.md +0 -3
- package/helpers/index.d.ts +0 -13
- package/helpers/lib/arrow-helper/arrow-helper.d.ts +0 -8
- package/helpers/lib/axes-helper/axes-helper.d.ts +0 -8
- package/helpers/lib/box-helper/box-helper.d.ts +0 -8
- package/helpers/lib/box3-helper/box3-helper.d.ts +0 -8
- package/helpers/lib/camera-helper/camera-helper.d.ts +0 -8
- package/helpers/lib/common.d.ts +0 -1
- package/helpers/lib/directional-light-helper/directional-light-helper.d.ts +0 -8
- package/helpers/lib/grid-helper/grid-helper.d.ts +0 -8
- package/helpers/lib/hemisphere-light-helper/hemisphere-light-helper.d.ts +0 -8
- package/helpers/lib/plane-helper/plane-helper.d.ts +0 -8
- package/helpers/lib/point-light-helper/point-light-helper.d.ts +0 -8
- package/helpers/lib/polar-grid-helper/polar-grid-helper.d.ts +0 -8
- package/helpers/lib/skeleton-helper/skeleton-helper.d.ts +0 -8
- package/helpers/lib/spot-light-helper/spot-light-helper.d.ts +0 -8
- package/lib/di/resize.d.ts +0 -12
- package/lib/di/window.d.ts +0 -1
- package/lib/directives/cursor.d.ts +0 -7
- package/lib/instance.d.ts +0 -81
- package/lib/pipes/math.d.ts +0 -7
- package/lib/pipes/pi.d.ts +0 -7
- package/lib/pipes/radian.d.ts +0 -7
- package/lib/pipes/side.d.ts +0 -8
- package/lib/ref.d.ts +0 -5
- package/lib/services/loader.d.ts +0 -11
- package/lib/services/resize.d.ts +0 -19
- package/lib/stores/component-store.d.ts +0 -69
- package/lib/utils/build-graph.d.ts +0 -3
- package/lib/utils/camera.d.ts +0 -4
- package/lib/utils/capitalize.d.ts +0 -1
- package/lib/utils/check-update.d.ts +0 -2
- package/lib/utils/events.d.ts +0 -6
- package/lib/utils/get-instance-local-state.d.ts +0 -2
- package/lib/utils/inject.d.ts +0 -9
- package/lib/utils/mutate.d.ts +0 -2
- package/lib/utils/proxy.d.ts +0 -7
- package/lib/utils/renderer.d.ts +0 -3
- package/lights/README.md +0 -3
- package/lights/index.d.ts +0 -9
- package/lights/lib/ambient-light/ambient-light.d.ts +0 -39
- package/lights/lib/ambient-light-probe/ambient-light-probe.d.ts +0 -40
- package/lights/lib/common.d.ts +0 -3
- package/lights/lib/directional-light/directional-light.d.ts +0 -40
- package/lights/lib/hemisphere-light/hemisphere-light.d.ts +0 -41
- package/lights/lib/hemisphere-light-probe/hemisphere-light-probe.d.ts +0 -42
- package/lights/lib/light-probe/light-probe.d.ts +0 -40
- package/lights/lib/point-light/point-light.d.ts +0 -42
- package/lights/lib/rect-area-light/rect-area-light.d.ts +0 -42
- package/lights/lib/spot-light/spot-light.d.ts +0 -45
- package/materials/README.md +0 -3
- package/materials/index.d.ts +0 -17
- package/materials/lib/common.d.ts +0 -1
- package/materials/lib/line-basic-material/line-basic-material.d.ts +0 -55
- package/materials/lib/line-dashed-material/line-dashed-material.d.ts +0 -58
- package/materials/lib/mesh-basic-material/mesh-basic-material.d.ts +0 -67
- package/materials/lib/mesh-depth-material/mesh-depth-material.d.ts +0 -58
- package/materials/lib/mesh-distance-material/mesh-distance-material.d.ts +0 -58
- package/materials/lib/mesh-lambert-material/mesh-lambert-material.d.ts +0 -78
- package/materials/lib/mesh-matcap-material/mesh-matcap-material.d.ts +0 -64
- package/materials/lib/mesh-normal-material/mesh-normal-material.d.ts +0 -61
- package/materials/lib/mesh-phong-material/mesh-phong-material.d.ts +0 -81
- package/materials/lib/mesh-physical-material/mesh-physical-material.d.ts +0 -97
- package/materials/lib/mesh-standard-material/mesh-standard-material.d.ts +0 -78
- package/materials/lib/mesh-toon-material/mesh-toon-material.d.ts +0 -74
- package/materials/lib/points-material/points-material.d.ts +0 -56
- package/materials/lib/raw-shader-material/raw-shader-material.d.ts +0 -68
- package/materials/lib/shader-material/shader-material.d.ts +0 -68
- package/materials/lib/shadow-material/shadow-material.d.ts +0 -52
- package/materials/lib/sprite-material/sprite-material.d.ts +0 -56
- package/objects/README.md +0 -3
- package/objects/index.d.ts +0 -12
- package/objects/lib/bone/bone.d.ts +0 -35
- package/objects/lib/common.d.ts +0 -3
- package/objects/lib/group/group.d.ts +0 -35
- package/objects/lib/instanced-mesh/instanced-mesh.d.ts +0 -44
- package/objects/lib/line/line.d.ts +0 -41
- package/objects/lib/line-loop/line-loop.d.ts +0 -41
- package/objects/lib/line-segments/line-segments.d.ts +0 -41
- package/objects/lib/lod/lod.d.ts +0 -40
- package/objects/lib/mesh/mesh.d.ts +0 -41
- package/objects/lib/points/points.d.ts +0 -41
- package/objects/lib/skeleton/skeleton.d.ts +0 -16
- package/objects/lib/skinned-mesh/skinned-mesh.d.ts +0 -45
- package/objects/lib/sprite/sprite.d.ts +0 -38
- package/primitives/README.md +0 -3
- package/primitives/index.d.ts +0 -2
- package/primitives/lib/common.d.ts +0 -3
- package/primitives/lib/object-primitive/object-primitive.d.ts +0 -35
- package/primitives/lib/primitive/primitive.d.ts +0 -10
- package/schematics/README.md +0 -11
- package/stats/README.md +0 -3
- package/stats/index.d.ts +0 -1
- package/stats/lib/stats/stats.d.ts +0 -16
- package/textures/README.md +0 -3
- package/textures/index.d.ts +0 -10
- package/textures/lib/canvas-texture/canvas-texture.d.ts +0 -8
- package/textures/lib/common.d.ts +0 -1
- package/textures/lib/compressed-array-texture/compressed-array-texture.d.ts +0 -8
- package/textures/lib/compressed-texture/compressed-texture.d.ts +0 -8
- package/textures/lib/cube-texture/cube-texture.d.ts +0 -8
- package/textures/lib/data-array-texture/data-array-texture.d.ts +0 -8
- package/textures/lib/data-texture/data-texture.d.ts +0 -8
- package/textures/lib/data3-dtexture/data3-dtexture.d.ts +0 -8
- package/textures/lib/depth-texture/depth-texture.d.ts +0 -8
- package/textures/lib/framebuffer-texture/framebuffer-texture.d.ts +0 -8
- package/textures/lib/video-texture/video-texture.d.ts +0 -8
|
@@ -1,477 +1,161 @@
|
|
|
1
|
-
import { DOCUMENT, NgIf, NgTemplateOutlet, AsyncPipe, NgForOf } from '@angular/common';
|
|
2
1
|
import * as i0 from '@angular/core';
|
|
3
|
-
import {
|
|
2
|
+
import { ElementRef, Injectable, inject, InjectionToken, ViewContainerRef, TemplateRef, Directive, Input, EventEmitter, getDebugNode, ChangeDetectorRef, RendererFactory2, Component, Output, EnvironmentInjector, createEnvironmentInjector, HostBinding, ViewChild } from '@angular/core';
|
|
3
|
+
import { injectNgxResize, provideNgxResizeOptions } from 'ngx-resize';
|
|
4
|
+
import { BehaviorSubject, startWith, tap, isObservable, of, map, from, retry, catchError, share, ReplaySubject, switchMap, forkJoin, take, filter } from 'rxjs';
|
|
5
|
+
import { DOCUMENT, NgForOf } from '@angular/common';
|
|
6
|
+
import { RxState, selectSlice } from '@rx-angular/state';
|
|
4
7
|
import * as THREE from 'three';
|
|
5
|
-
import {
|
|
6
|
-
import { ComponentStore } from '@ngrx/component-store';
|
|
8
|
+
import { ɵDomRendererFactory2 } from '@angular/platform-browser';
|
|
7
9
|
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const idCache = {};
|
|
15
|
-
function makeId(event) {
|
|
16
|
-
if (event) {
|
|
17
|
-
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
18
|
-
}
|
|
19
|
-
const newId = THREE.MathUtils.generateUUID();
|
|
20
|
-
// ensure not already used
|
|
21
|
-
if (!idCache[newId]) {
|
|
22
|
-
idCache[newId] = true;
|
|
23
|
-
return newId;
|
|
24
|
-
}
|
|
25
|
-
return makeId();
|
|
26
|
-
}
|
|
27
|
-
function makeDpr(dpr, window) {
|
|
28
|
-
const target = window?.devicePixelRatio || 1;
|
|
29
|
-
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
|
|
30
|
-
}
|
|
31
|
-
function make(type, input) {
|
|
32
|
-
if (!input)
|
|
33
|
-
return new type();
|
|
34
|
-
if (input instanceof type) {
|
|
35
|
-
return input;
|
|
36
|
-
}
|
|
37
|
-
if (!Array.isArray(input)) {
|
|
38
|
-
input = typeof input === 'number' ? [input, input, input, input] : [input];
|
|
39
|
-
}
|
|
40
|
-
return new type(...input);
|
|
10
|
+
function createSubs(callback, subs) {
|
|
11
|
+
const sub = { callback };
|
|
12
|
+
subs.add(sub);
|
|
13
|
+
return () => void subs.delete(sub);
|
|
41
14
|
}
|
|
42
|
-
|
|
15
|
+
const globalEffects = new Set();
|
|
16
|
+
const globalAfterEffects = new Set();
|
|
17
|
+
const globalTailEffects = new Set();
|
|
43
18
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
19
|
+
* Adds a global render callback which is called each frame.
|
|
20
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
|
|
46
21
|
*/
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
22
|
+
const addEffect = (callback) => createSubs(callback, globalEffects);
|
|
23
|
+
/**
|
|
24
|
+
* Adds a global after-render callback which is called each frame.
|
|
25
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
|
|
26
|
+
*/
|
|
27
|
+
const addAfterEffect = (callback) => createSubs(callback, globalAfterEffects);
|
|
28
|
+
/**
|
|
29
|
+
* Adds a global callback which is called when rendering stops.
|
|
30
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
|
|
31
|
+
*/
|
|
32
|
+
const addTail = (callback) => createSubs(callback, globalTailEffects);
|
|
33
|
+
function run(effects, timestamp) {
|
|
34
|
+
if (!effects.size)
|
|
35
|
+
return;
|
|
36
|
+
for (const { callback } of effects.values()) {
|
|
37
|
+
callback(timestamp);
|
|
56
38
|
}
|
|
57
39
|
}
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
internal.hovered.delete(key);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
internal.capturedMap.forEach((captures, pointerId) => {
|
|
70
|
-
releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
function createEvents(stateFactory) {
|
|
74
|
-
/** Calculates delta */
|
|
75
|
-
function calculateDistance(event) {
|
|
76
|
-
const { internal } = stateFactory();
|
|
77
|
-
const dx = event.offsetX - internal.initialClick[0];
|
|
78
|
-
const dy = event.offsetY - internal.initialClick[1];
|
|
79
|
-
return Math.round(Math.sqrt(dx * dx + dy * dy));
|
|
40
|
+
function flushGlobalEffects(type, timestamp) {
|
|
41
|
+
switch (type) {
|
|
42
|
+
case 'before':
|
|
43
|
+
return run(globalEffects, timestamp);
|
|
44
|
+
case 'after':
|
|
45
|
+
return run(globalAfterEffects, timestamp);
|
|
46
|
+
case 'tail':
|
|
47
|
+
return run(globalTailEffects, timestamp);
|
|
80
48
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
49
|
+
}
|
|
50
|
+
function render(timestamp, store, frame) {
|
|
51
|
+
const state = store.get();
|
|
52
|
+
// Run local effects
|
|
53
|
+
let delta = state.clock.getDelta();
|
|
54
|
+
// In frameloop='never' mode, clock times are updated using the provided timestamp
|
|
55
|
+
if (state.frameloop === 'never' && typeof timestamp === 'number') {
|
|
56
|
+
delta = timestamp - state.clock.elapsedTime;
|
|
57
|
+
state.clock.oldTime = state.clock.elapsedTime;
|
|
58
|
+
state.clock.elapsedTime = timestamp;
|
|
87
59
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
const eventsObjects = filter ? filter(state.internal.interaction) : state.internal.interaction;
|
|
94
|
-
// Reset all raycaster cameras to undefined
|
|
95
|
-
for (let i = 0; i < eventsObjects.length; i++) {
|
|
96
|
-
const instanceState = getInstanceLocalState(eventsObjects[i])?.stateFactory();
|
|
97
|
-
if (instanceState) {
|
|
98
|
-
instanceState.raycaster.camera = undefined;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (!state.previousStateFactory) {
|
|
102
|
-
// Make sure root-level pointer and ray are set up
|
|
103
|
-
state.events.compute?.(event, () => state);
|
|
104
|
-
}
|
|
105
|
-
function handleRaycast(obj) {
|
|
106
|
-
const state = getInstanceLocalState(obj)?.stateFactory();
|
|
107
|
-
// Skip event handling when noEvents is set, or when the raycasters camera is null
|
|
108
|
-
if (!state || !state.events.enabled || state.raycaster.camera === null)
|
|
109
|
-
return [];
|
|
110
|
-
// When the camera is undefined we have to call the event layers update function
|
|
111
|
-
if (state.raycaster.camera === undefined) {
|
|
112
|
-
state.events.compute?.(event, () => state, state.previousStateFactory);
|
|
113
|
-
// If the camera is still undefined we have to skip this layer entirely
|
|
114
|
-
if (state.raycaster.camera === undefined)
|
|
115
|
-
state.raycaster.camera = null;
|
|
116
|
-
}
|
|
117
|
-
// Intersect object by object
|
|
118
|
-
return state.raycaster.camera ? state.raycaster.intersectObject(obj, true) : [];
|
|
119
|
-
}
|
|
120
|
-
// Collect events
|
|
121
|
-
let hits = eventsObjects
|
|
122
|
-
// Intersect objects
|
|
123
|
-
.flatMap(handleRaycast)
|
|
124
|
-
// Sort by event priority and distance
|
|
125
|
-
.sort((a, b) => {
|
|
126
|
-
const aState = getInstanceLocalState(a.object)?.stateFactory();
|
|
127
|
-
const bState = getInstanceLocalState(b.object)?.stateFactory();
|
|
128
|
-
if (!aState || !bState)
|
|
129
|
-
return 0;
|
|
130
|
-
return bState.events.priority - aState.events.priority || a.distance - b.distance;
|
|
131
|
-
})
|
|
132
|
-
// Filter out duplicates
|
|
133
|
-
.filter((item) => {
|
|
134
|
-
const id = makeId(item);
|
|
135
|
-
if (duplicates.has(id))
|
|
136
|
-
return false;
|
|
137
|
-
duplicates.add(id);
|
|
138
|
-
return true;
|
|
139
|
-
});
|
|
140
|
-
// https://github.com/mrdoob/three.js/issues/16031
|
|
141
|
-
// Allow custom userland intersect sort order, this likely only makes sense on the root filter
|
|
142
|
-
if (state.events.filter)
|
|
143
|
-
hits = state.events.filter(hits, () => state);
|
|
144
|
-
// Bubble up the events, find the event source (eventObject)
|
|
145
|
-
for (const hit of hits) {
|
|
146
|
-
let eventObject = hit.object;
|
|
147
|
-
// Bubble event up
|
|
148
|
-
while (eventObject) {
|
|
149
|
-
if (getInstanceLocalState(eventObject)?.eventCount)
|
|
150
|
-
intersections.push({ ...hit, eventObject });
|
|
151
|
-
eventObject = eventObject.parent;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
// If the interaction is captured, make all capturing targets part of the intersect.
|
|
155
|
-
if ('pointerId' in event && state.internal.capturedMap.has(event.pointerId)) {
|
|
156
|
-
for (const captureData of state.internal.capturedMap.get(event.pointerId).values()) {
|
|
157
|
-
intersections.push(captureData.intersection);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return intersections;
|
|
60
|
+
// Call subscribers (useFrame)
|
|
61
|
+
// subscribers = state.internal.subscribers;
|
|
62
|
+
for (let i = 0; i < state.internal.subscribers.length; i++) {
|
|
63
|
+
const subscriber = state.internal.subscribers[i];
|
|
64
|
+
subscriber.callback({ ...state, delta, frame });
|
|
161
65
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// If anything has been found, forward it to the event listeners
|
|
166
|
-
if (intersections.length) {
|
|
167
|
-
const localState = { stopped: false };
|
|
168
|
-
for (const hit of intersections) {
|
|
169
|
-
const state = getInstanceLocalState(hit.object)?.stateFactory() || rootState;
|
|
170
|
-
const { raycaster, pointer, camera, internal } = state;
|
|
171
|
-
const unprojectedPoint = new THREE.Vector3(pointer.x, pointer.y, 0).unproject(camera);
|
|
172
|
-
const hasPointerCapture = (id) => internal.capturedMap.get(id)?.has(hit.eventObject) ?? false;
|
|
173
|
-
const setPointerCapture = (id) => {
|
|
174
|
-
const captureData = {
|
|
175
|
-
intersection: hit,
|
|
176
|
-
target: event.target,
|
|
177
|
-
};
|
|
178
|
-
if (internal.capturedMap.has(id)) {
|
|
179
|
-
// if the pointerId was previously captured, we add the hit to the
|
|
180
|
-
// event capturedMap.
|
|
181
|
-
internal.capturedMap.get(id).set(hit.eventObject, captureData);
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
// if the pointerId was not previously captured, we create a map
|
|
185
|
-
// containing the hitObject, and the hit. hitObject is used for
|
|
186
|
-
// faster access.
|
|
187
|
-
internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
|
|
188
|
-
}
|
|
189
|
-
// Call the original event now
|
|
190
|
-
event.target.setPointerCapture(id);
|
|
191
|
-
};
|
|
192
|
-
const releasePointerCapture = (id) => {
|
|
193
|
-
const captures = internal.capturedMap.get(id);
|
|
194
|
-
if (captures) {
|
|
195
|
-
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
// Add native event props
|
|
199
|
-
const extractEventProps = {};
|
|
200
|
-
// This iterates over the event's properties including the inherited ones. Native PointerEvents have most of their props as getters which are inherited, but polyfilled PointerEvents have them all as their own properties (i.e. not inherited). We can't use Object.keys() or Object.entries() as they only return "own" properties; nor Object.getPrototypeOf(event) as that *doesn't* return "own" properties, only inherited ones.
|
|
201
|
-
for (const prop in event) {
|
|
202
|
-
const property = event[prop];
|
|
203
|
-
// Only copy over atomics, leave functions alone as these should be
|
|
204
|
-
// called as event.nativeEvent.fn()
|
|
205
|
-
if (typeof property !== 'function')
|
|
206
|
-
extractEventProps[prop] = property;
|
|
207
|
-
}
|
|
208
|
-
const raycastEvent = {
|
|
209
|
-
...hit,
|
|
210
|
-
...extractEventProps,
|
|
211
|
-
pointer,
|
|
212
|
-
intersections,
|
|
213
|
-
stopped: localState.stopped,
|
|
214
|
-
delta,
|
|
215
|
-
unprojectedPoint,
|
|
216
|
-
ray: raycaster.ray,
|
|
217
|
-
camera: camera,
|
|
218
|
-
// Hijack stopPropagation, which just sets a flag
|
|
219
|
-
stopPropagation() {
|
|
220
|
-
// https://github.com/pmndrs/react-three-fiber/issues/596
|
|
221
|
-
// Events are not allowed to stop propagation if the pointer has been captured
|
|
222
|
-
const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId);
|
|
223
|
-
// We only authorize stopPropagation...
|
|
224
|
-
if (
|
|
225
|
-
// ...if this pointer hasn't been captured
|
|
226
|
-
!capturesForPointer ||
|
|
227
|
-
// ... or if the hit object is capturing the pointer
|
|
228
|
-
capturesForPointer.has(hit.eventObject)) {
|
|
229
|
-
raycastEvent.stopped = localState.stopped = true;
|
|
230
|
-
// Propagation is stopped, remove all other hover records
|
|
231
|
-
// An event handler is only allowed to flush other handlers if it is hovered itself
|
|
232
|
-
if (internal.hovered.size &&
|
|
233
|
-
Array.from(internal.hovered.values()).find((i) => i.eventObject === hit.eventObject)) {
|
|
234
|
-
// Objects cannot flush out higher up objects that have already caught the event
|
|
235
|
-
const higher = intersections.slice(0, intersections.indexOf(hit));
|
|
236
|
-
cancelPointer([...higher, hit]);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
// there should be a distinction between target and currentTarget
|
|
241
|
-
target: {
|
|
242
|
-
hasPointerCapture,
|
|
243
|
-
setPointerCapture,
|
|
244
|
-
releasePointerCapture,
|
|
245
|
-
},
|
|
246
|
-
currentTarget: {
|
|
247
|
-
hasPointerCapture,
|
|
248
|
-
setPointerCapture,
|
|
249
|
-
releasePointerCapture,
|
|
250
|
-
},
|
|
251
|
-
nativeEvent: event,
|
|
252
|
-
};
|
|
253
|
-
// Call subscribers
|
|
254
|
-
callback(raycastEvent);
|
|
255
|
-
// Event bubbling may be interrupted by stopPropagation
|
|
256
|
-
if (localState.stopped === true)
|
|
257
|
-
break;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return intersections;
|
|
66
|
+
// Render content
|
|
67
|
+
if (!state.internal.priority && state.gl.render) {
|
|
68
|
+
state.gl.render(state.scene, state.camera);
|
|
261
69
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
70
|
+
// Decrease frame count
|
|
71
|
+
state.internal.frames = Math.max(0, state.internal.frames - 1);
|
|
72
|
+
return state.frameloop === 'always' ? 1 : state.internal.frames;
|
|
73
|
+
}
|
|
74
|
+
function createLoop(roots) {
|
|
75
|
+
let running = false;
|
|
76
|
+
let repeat;
|
|
77
|
+
let frame;
|
|
78
|
+
function loop(timestamp) {
|
|
79
|
+
frame = requestAnimationFrame(loop);
|
|
80
|
+
running = true;
|
|
81
|
+
repeat = 0;
|
|
82
|
+
// Run effects
|
|
83
|
+
flushGlobalEffects('before', timestamp);
|
|
84
|
+
// Render all roots
|
|
85
|
+
for (const root of roots.values()) {
|
|
86
|
+
const state = root.get();
|
|
87
|
+
// If the frameloop is invalidated, do not run another frame
|
|
88
|
+
if (state.internal.active &&
|
|
89
|
+
(state.frameloop === 'always' || state.internal.frames > 0) &&
|
|
90
|
+
!state.gl.xr?.isPresenting) {
|
|
91
|
+
repeat += render(timestamp, root);
|
|
281
92
|
}
|
|
282
93
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
switch (name) {
|
|
293
|
-
case 'pointerleave':
|
|
294
|
-
case 'pointercancel':
|
|
295
|
-
return () => cancelPointer([]);
|
|
296
|
-
case 'lostpointercapture':
|
|
297
|
-
return (event) => {
|
|
298
|
-
const { internal } = stateFactory();
|
|
299
|
-
if ('pointerId' in event && !internal.capturedMap.has(event.pointerId)) {
|
|
300
|
-
// If the object event interface had onLostPointerCapture, we'd call it here on every
|
|
301
|
-
// object that's getting removed.
|
|
302
|
-
internal.capturedMap.delete(event.pointerId);
|
|
303
|
-
cancelPointer([]);
|
|
304
|
-
}
|
|
305
|
-
};
|
|
94
|
+
// Run after-effects
|
|
95
|
+
flushGlobalEffects('after', timestamp);
|
|
96
|
+
// Stop the loop if nothing invalidates it
|
|
97
|
+
if (repeat === 0) {
|
|
98
|
+
// Tail call effects, they are called when rendering stops
|
|
99
|
+
flushGlobalEffects('tail', timestamp);
|
|
100
|
+
// Flag end of operation
|
|
101
|
+
running = false;
|
|
102
|
+
return cancelAnimationFrame(frame);
|
|
306
103
|
}
|
|
307
|
-
// Any other pointer goes here ...
|
|
308
|
-
return function handleEvent(event) {
|
|
309
|
-
const { onPointerMissed, internal } = stateFactory();
|
|
310
|
-
// prepareRay(event)
|
|
311
|
-
internal.lastEvent = event;
|
|
312
|
-
// Get fresh intersects
|
|
313
|
-
const isPointerMove = name === 'pointermove';
|
|
314
|
-
const isClickEvent = name === 'click' || name === 'contextmenu' || name === 'dblclick';
|
|
315
|
-
const filter = isPointerMove ? filterPointerEvents : undefined;
|
|
316
|
-
// const hits = patchIntersects(intersect(filter), event)
|
|
317
|
-
const hits = intersect(event, filter);
|
|
318
|
-
const delta = isClickEvent ? calculateDistance(event) : 0;
|
|
319
|
-
// Save initial coordinates on pointer-down
|
|
320
|
-
if (name === 'pointerdown') {
|
|
321
|
-
internal.initialClick = [event.offsetX, event.offsetY];
|
|
322
|
-
internal.initialHits = hits.map((hit) => hit.eventObject);
|
|
323
|
-
}
|
|
324
|
-
// If a click yields no results, pass it back to the user as a miss
|
|
325
|
-
// Missed events have to come first in order to establish user-land side-effect clean up
|
|
326
|
-
if (isClickEvent && !hits.length) {
|
|
327
|
-
if (delta <= 2) {
|
|
328
|
-
pointerMissed(event, internal.interaction);
|
|
329
|
-
if (onPointerMissed)
|
|
330
|
-
onPointerMissed(event);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
// Take care of unhover
|
|
334
|
-
if (isPointerMove)
|
|
335
|
-
cancelPointer(hits);
|
|
336
|
-
function onIntersect(data) {
|
|
337
|
-
const eventObject = data.eventObject;
|
|
338
|
-
const instance = getInstanceLocalState(eventObject);
|
|
339
|
-
const handlers = instance?.handlers;
|
|
340
|
-
// Check presence of handlers
|
|
341
|
-
if (!instance?.eventCount)
|
|
342
|
-
return;
|
|
343
|
-
if (isPointerMove) {
|
|
344
|
-
// Move event ...
|
|
345
|
-
if (handlers?.pointerover ||
|
|
346
|
-
handlers?.pointerenter ||
|
|
347
|
-
handlers?.pointerout ||
|
|
348
|
-
handlers?.pointerleave) {
|
|
349
|
-
// When enter or out is present take care of hover-state
|
|
350
|
-
const id = makeId(data);
|
|
351
|
-
const hoveredItem = internal.hovered.get(id);
|
|
352
|
-
if (!hoveredItem) {
|
|
353
|
-
// If the object wasn't previously hovered, book it and call its handler
|
|
354
|
-
internal.hovered.set(id, data);
|
|
355
|
-
handlers.pointerover?.(data);
|
|
356
|
-
handlers.pointerenter?.(data);
|
|
357
|
-
}
|
|
358
|
-
else if (hoveredItem.stopped) {
|
|
359
|
-
// If the object was previously hovered and stopped, we shouldn't allow other items to proceed
|
|
360
|
-
data.stopPropagation();
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
// Call mouse move
|
|
364
|
-
handlers?.pointermove?.(data);
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
// All other events ...
|
|
368
|
-
const handler = handlers[name];
|
|
369
|
-
if (handler) {
|
|
370
|
-
// Forward all events back to their respective handlers with the exception of click events,
|
|
371
|
-
// which must use the initial target
|
|
372
|
-
if (!isClickEvent || internal.initialHits.includes(eventObject)) {
|
|
373
|
-
// Missed events have to come first
|
|
374
|
-
pointerMissed(event, internal.interaction.filter((object) => !internal.initialHits.includes(object)));
|
|
375
|
-
// Now call the handler
|
|
376
|
-
handler(data);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
else {
|
|
380
|
-
// Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
|
|
381
|
-
if (isClickEvent && internal.initialHits.includes(eventObject)) {
|
|
382
|
-
pointerMissed(event, internal.interaction.filter((object) => !internal.initialHits.includes(object)));
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
handleIntersects(hits, event, delta, onIntersect);
|
|
388
|
-
};
|
|
389
104
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
pointercancel: true,
|
|
403
|
-
lostpointercapture: true,
|
|
404
|
-
};
|
|
405
|
-
function createPointerEvents(stateFactory) {
|
|
406
|
-
const { handlePointer } = createEvents(stateFactory);
|
|
407
|
-
return {
|
|
408
|
-
priority: 1,
|
|
409
|
-
enabled: true,
|
|
410
|
-
compute: (event, rootFactory) => {
|
|
411
|
-
const state = rootFactory();
|
|
412
|
-
// https://github.com/pmndrs/react-three-fiber/pull/782
|
|
413
|
-
// Events trigger outside of canvas when moved, use offsetX/Y by default and allow overrides
|
|
414
|
-
state.pointer.set((event.offsetX / state.size.width) * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
415
|
-
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
416
|
-
},
|
|
417
|
-
connected: undefined,
|
|
418
|
-
handlers: Object.keys(DOM_EVENTS).reduce((handlers, supportedEventName) => {
|
|
419
|
-
handlers[supportedEventName] = handlePointer(supportedEventName);
|
|
420
|
-
return handlers;
|
|
421
|
-
}, {}),
|
|
422
|
-
connect: (target) => {
|
|
423
|
-
const state = stateFactory();
|
|
424
|
-
state.events.disconnect?.();
|
|
425
|
-
state.setEvents({ connected: target });
|
|
426
|
-
Object.entries(state.events.handlers ?? {}).forEach(([eventName, eventHandler]) => {
|
|
427
|
-
const passive = DOM_EVENTS[eventName];
|
|
428
|
-
target.addEventListener(eventName, eventHandler, { passive });
|
|
429
|
-
});
|
|
430
|
-
},
|
|
431
|
-
disconnect: () => {
|
|
432
|
-
const { events, setEvents } = stateFactory();
|
|
433
|
-
if (events.connected) {
|
|
434
|
-
Object.entries(events.handlers ?? {}).forEach(([eventName, eventHandler]) => {
|
|
435
|
-
if (events.connected instanceof HTMLElement) {
|
|
436
|
-
events.connected.removeEventListener(eventName, eventHandler);
|
|
437
|
-
}
|
|
438
|
-
});
|
|
439
|
-
setEvents({ connected: undefined });
|
|
440
|
-
}
|
|
441
|
-
},
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
class NgtRef extends BehaviorSubject {
|
|
446
|
-
constructor(value) {
|
|
447
|
-
super(value ? value : null);
|
|
448
|
-
}
|
|
449
|
-
set(valueOrFactory) {
|
|
450
|
-
if (typeof valueOrFactory === 'function') {
|
|
451
|
-
this.next(valueOrFactory(this.value));
|
|
452
|
-
}
|
|
453
|
-
else {
|
|
454
|
-
this.next(valueOrFactory);
|
|
105
|
+
function invalidate(store, frames = 1) {
|
|
106
|
+
const state = store?.get();
|
|
107
|
+
if (!state)
|
|
108
|
+
return roots.forEach((root) => invalidate(root, frames));
|
|
109
|
+
if (state.gl.xr?.isPresenting || !state.internal.active || state.frameloop === 'never')
|
|
110
|
+
return;
|
|
111
|
+
// Increase frames, do not go higher than 60
|
|
112
|
+
state.internal.frames = Math.min(60, state.internal.frames + frames);
|
|
113
|
+
// If the render-loop isn't active, start it
|
|
114
|
+
if (!running) {
|
|
115
|
+
running = true;
|
|
116
|
+
requestAnimationFrame(loop);
|
|
455
117
|
}
|
|
456
118
|
}
|
|
119
|
+
function advance(timestamp, runGlobalEffects = true, store, frame) {
|
|
120
|
+
const state = store?.get();
|
|
121
|
+
if (runGlobalEffects)
|
|
122
|
+
flushGlobalEffects('before', timestamp);
|
|
123
|
+
if (!state)
|
|
124
|
+
for (const root of roots.values())
|
|
125
|
+
render(timestamp, root);
|
|
126
|
+
// safe to assume store is available here
|
|
127
|
+
else
|
|
128
|
+
render(timestamp, store, frame);
|
|
129
|
+
if (runGlobalEffects)
|
|
130
|
+
flushGlobalEffects('after', timestamp);
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
loop,
|
|
134
|
+
/**
|
|
135
|
+
* Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
|
|
136
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
|
|
137
|
+
*/
|
|
138
|
+
invalidate,
|
|
139
|
+
/**
|
|
140
|
+
* Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
|
|
141
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
|
|
142
|
+
*/
|
|
143
|
+
advance,
|
|
144
|
+
};
|
|
457
145
|
}
|
|
458
146
|
|
|
459
147
|
const is = {
|
|
460
148
|
obj: (a) => a === Object(a) && !Array.isArray(a) && typeof a !== 'function',
|
|
461
149
|
material: (a) => !!a && a.isMaterial,
|
|
462
150
|
geometry: (a) => !!a && a.isBufferGeometry,
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
orthographic: (a) => !!a && a.isOrthographicCamera,
|
|
466
|
-
perspective: (a) => !!a && a.isPerspectiveCamera,
|
|
151
|
+
orthographicCamera: (a) => !!a && a.isOrthographicCamera,
|
|
152
|
+
perspectiveCamera: (a) => !!a && a.isPerspectiveCamera,
|
|
467
153
|
camera: (a) => !!a && a.isCamera,
|
|
468
|
-
|
|
154
|
+
renderer: (a) => !!a && a instanceof THREE.WebGLRenderer,
|
|
469
155
|
scene: (a) => !!a && a.isScene,
|
|
470
|
-
|
|
156
|
+
object3D: (a) => !!a && a.isObject3D,
|
|
471
157
|
instance: (a) => !!a && !!a['__ngt__'],
|
|
472
|
-
ref: (a) =>
|
|
473
|
-
supportColorManagement: () => 'ColorManagement' in THREE,
|
|
474
|
-
canvas: (a) => a instanceof HTMLCanvasElement,
|
|
158
|
+
ref: (a) => a instanceof ElementRef,
|
|
475
159
|
equ(a, b, { arrays = 'shallow', objects = 'reference', strict = true } = {}) {
|
|
476
160
|
// Wrong type or one of the two undefined, doesn't match
|
|
477
161
|
if (typeof a !== typeof b || !!a !== !!b)
|
|
@@ -508,165 +192,6 @@ const is = {
|
|
|
508
192
|
},
|
|
509
193
|
};
|
|
510
194
|
|
|
511
|
-
/**
|
|
512
|
-
* a default Selector that consumers can quickly use for their selectors projector
|
|
513
|
-
*/
|
|
514
|
-
const defaultProjector = () => ({});
|
|
515
|
-
/**
|
|
516
|
-
* A custom operator that skips the first undefined value but allows subsequent undefined values.
|
|
517
|
-
* NgRxComponentStore#select always emits the first value regardless of undefined or not after initialize
|
|
518
|
-
*/
|
|
519
|
-
const skipFirstUndefined = () => filter((value, index) => index > 0 || value !== undefined);
|
|
520
|
-
/**
|
|
521
|
-
* An extended `tap` operator that accepts an `effectFn` which:
|
|
522
|
-
* - runs on every `next` notification from `source$`
|
|
523
|
-
* - can optionally return a `cleanUp` function that
|
|
524
|
-
* invokes from the 2nd `next` notification onward and on `unsubscribe` (destroyed)
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
* @example
|
|
528
|
-
* ```typescript
|
|
529
|
-
* source$.pipe(
|
|
530
|
-
* tapEffect((sourceValue) = {
|
|
531
|
-
* const cb = () => {
|
|
532
|
-
* doStuff(sourceValue);
|
|
533
|
-
* };
|
|
534
|
-
* addListener('event', cb);
|
|
535
|
-
*
|
|
536
|
-
* return () => {
|
|
537
|
-
* removeListener('event', cb);
|
|
538
|
-
* }
|
|
539
|
-
* })
|
|
540
|
-
* )
|
|
541
|
-
* ```
|
|
542
|
-
*/
|
|
543
|
-
function tapEffect(effectFn) {
|
|
544
|
-
let cleanupFn = noop;
|
|
545
|
-
let firstRun = false;
|
|
546
|
-
let prev = undefined;
|
|
547
|
-
const teardown = (error) => {
|
|
548
|
-
return () => {
|
|
549
|
-
if (cleanupFn) {
|
|
550
|
-
cleanupFn({ prev, complete: true, error });
|
|
551
|
-
}
|
|
552
|
-
};
|
|
553
|
-
};
|
|
554
|
-
return tap({
|
|
555
|
-
next: (value) => {
|
|
556
|
-
if (cleanupFn && firstRun) {
|
|
557
|
-
cleanupFn({ prev, complete: false, error: false });
|
|
558
|
-
}
|
|
559
|
-
const cleanUpOrVoid = effectFn(value);
|
|
560
|
-
if (cleanUpOrVoid) {
|
|
561
|
-
cleanupFn = cleanUpOrVoid;
|
|
562
|
-
}
|
|
563
|
-
prev = value;
|
|
564
|
-
if (!firstRun) {
|
|
565
|
-
firstRun = true;
|
|
566
|
-
}
|
|
567
|
-
},
|
|
568
|
-
complete: teardown(false),
|
|
569
|
-
unsubscribe: teardown(false),
|
|
570
|
-
error: teardown(true),
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
class NgtComponentStore extends ComponentStore {
|
|
574
|
-
constructor() {
|
|
575
|
-
super({});
|
|
576
|
-
// exposing get since THREE is imperative at its core
|
|
577
|
-
// we need to imperatively get state sometimes for usages in Animation Loop
|
|
578
|
-
// we also bind "this" instance, so we don't have to bind it later
|
|
579
|
-
this.read = this.get.bind(this);
|
|
580
|
-
this.initialize();
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* A custom patchState that allows for:
|
|
584
|
-
* - Partial state updates and Observable of partial state updates like patchState
|
|
585
|
-
* - Pass a Record<string, ObservableInput> to update a specific key with an Observable.
|
|
586
|
-
* This is similar to `RxState.connect()` API
|
|
587
|
-
*/
|
|
588
|
-
write(partialStateOrFactory) {
|
|
589
|
-
if (typeof partialStateOrFactory === 'function') {
|
|
590
|
-
return this.write(partialStateOrFactory(this.read()));
|
|
591
|
-
}
|
|
592
|
-
const partialState = partialStateOrFactory;
|
|
593
|
-
if (Object.keys(partialState).length === 0) {
|
|
594
|
-
return;
|
|
595
|
-
}
|
|
596
|
-
if (isObservable(partialState)) {
|
|
597
|
-
return this.patchState(partialState);
|
|
598
|
-
}
|
|
599
|
-
const entries = Object.entries(partialState);
|
|
600
|
-
const hasObservable = entries.some(([_, value]) => isObservable(value) && !is.ref(value));
|
|
601
|
-
if (!hasObservable) {
|
|
602
|
-
return this.patchState(partialState);
|
|
603
|
-
}
|
|
604
|
-
const [rawValues, observableValues] = entries.reduce((result, [key, value]) => {
|
|
605
|
-
if (isObservable(value)) {
|
|
606
|
-
result[1][key] = value;
|
|
607
|
-
}
|
|
608
|
-
else {
|
|
609
|
-
result[0][key] = value;
|
|
610
|
-
}
|
|
611
|
-
return result;
|
|
612
|
-
}, [{}, {}]);
|
|
613
|
-
if (Object.keys(rawValues).length > 0) {
|
|
614
|
-
this.patchState(rawValues);
|
|
615
|
-
}
|
|
616
|
-
if (Object.keys(observableValues).length > 0) {
|
|
617
|
-
this.patchState(combineLatest(observableValues));
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
initialize() {
|
|
621
|
-
return;
|
|
622
|
-
}
|
|
623
|
-
/**
|
|
624
|
-
* A utility class method to select a state on the template as Observable
|
|
625
|
-
* - This method always debounce the Observable
|
|
626
|
-
*/
|
|
627
|
-
selectKey(key, skipFirst = false) {
|
|
628
|
-
return this.select((s) => s[key], { debounce: true }).pipe(skipFirst ? skipFirstUndefined() : (s) => s);
|
|
629
|
-
}
|
|
630
|
-
/**
|
|
631
|
-
* A utility class method to get a state on the template as imperative Value
|
|
632
|
-
*/
|
|
633
|
-
readKey(key) {
|
|
634
|
-
return this.read((s) => s[key]);
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
NgtComponentStore.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtComponentStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
638
|
-
NgtComponentStore.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtComponentStore });
|
|
639
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtComponentStore, decorators: [{
|
|
640
|
-
type: Injectable
|
|
641
|
-
}], ctorParameters: function () { return []; } });
|
|
642
|
-
|
|
643
|
-
function createInjection(description, { defaultValueOrFactory, provideValueFactory, } = {}) {
|
|
644
|
-
const factory = (defaultValueOrFactory && typeof defaultValueOrFactory === 'function'
|
|
645
|
-
? defaultValueOrFactory
|
|
646
|
-
: () => defaultValueOrFactory);
|
|
647
|
-
const injectionToken = new InjectionToken(description, { factory });
|
|
648
|
-
function injectFn(options = {}) {
|
|
649
|
-
return inject(injectionToken, options);
|
|
650
|
-
}
|
|
651
|
-
function provideFn(value) {
|
|
652
|
-
return {
|
|
653
|
-
provide: injectionToken,
|
|
654
|
-
useValue: provideValueFactory ? provideValueFactory(value) : value,
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
return [injectFn, provideFn, injectionToken];
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
const [injectWindow] = createInjection('window', {
|
|
661
|
-
defaultValueOrFactory: () => {
|
|
662
|
-
const { defaultView } = inject(DOCUMENT);
|
|
663
|
-
if (!defaultView) {
|
|
664
|
-
throw `window is not available!`;
|
|
665
|
-
}
|
|
666
|
-
return defaultView;
|
|
667
|
-
},
|
|
668
|
-
});
|
|
669
|
-
|
|
670
195
|
function checkNeedsUpdate(value) {
|
|
671
196
|
if (value !== null && is.obj(value) && 'needsUpdate' in value) {
|
|
672
197
|
value['needsUpdate'] = true;
|
|
@@ -676,183 +201,20 @@ function checkNeedsUpdate(value) {
|
|
|
676
201
|
}
|
|
677
202
|
}
|
|
678
203
|
function checkUpdate(value) {
|
|
679
|
-
if (is.
|
|
204
|
+
if (is.object3D(value)) {
|
|
680
205
|
value.updateMatrix();
|
|
681
206
|
}
|
|
682
|
-
|
|
683
|
-
if (is.
|
|
207
|
+
if (is.camera(value)) {
|
|
208
|
+
if (is.perspectiveCamera(value) || is.orthographicCamera(value)) {
|
|
684
209
|
value.updateProjectionMatrix();
|
|
685
210
|
}
|
|
686
211
|
value.updateMatrixWorld();
|
|
687
212
|
}
|
|
688
213
|
checkNeedsUpdate(value);
|
|
689
214
|
}
|
|
690
|
-
|
|
691
|
-
function invalidateInstance(instance) {
|
|
692
|
-
const state = getInstanceLocalState(instance)?.stateFactory();
|
|
693
|
-
if (state && state.internal.frames === 0)
|
|
694
|
-
state.invalidate();
|
|
695
|
-
checkUpdate(instance);
|
|
696
|
-
}
|
|
697
|
-
function prepare(instance, parentStateFactory, rootStateFactory, parentInstance, previousInstance, isPrimitive = false) {
|
|
698
|
-
const previousInstanceInternal = getInstanceLocalState(previousInstance?.value);
|
|
699
|
-
const parent = parentInstance
|
|
700
|
-
? parentInstance
|
|
701
|
-
: previousInstanceInternal
|
|
702
|
-
? previousInstanceInternal.parentRef
|
|
703
|
-
: undefined;
|
|
704
|
-
if (is.scene(instance)) {
|
|
705
|
-
applyProps(instance, { dispose: null });
|
|
706
|
-
}
|
|
707
|
-
return Object.assign(instance, {
|
|
708
|
-
__ngt__: {
|
|
709
|
-
stateFactory: parentStateFactory,
|
|
710
|
-
rootFactory: rootStateFactory,
|
|
711
|
-
isPrimitive: !isPrimitive ? previousInstanceInternal?.isPrimitive : isPrimitive,
|
|
712
|
-
eventCount: previousInstanceInternal?.eventCount ?? 0,
|
|
713
|
-
handlers: previousInstanceInternal?.handlers ?? {},
|
|
714
|
-
instancesRefs: previousInstanceInternal?.instancesRefs ?? new NgtRef([]),
|
|
715
|
-
objectsRefs: previousInstanceInternal?.objectsRefs ?? new NgtRef([]),
|
|
716
|
-
parentRef: parent ? (parent === instance || parent.value === instance ? null : parent) : null,
|
|
717
|
-
},
|
|
718
|
-
});
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
const DEFAULT = '__default';
|
|
722
|
-
function diffProps(instance, props, previousProps = {}, remove = false) {
|
|
723
|
-
const localState = getInstanceLocalState(instance) || {};
|
|
724
|
-
const propsEntries = Object.entries(props);
|
|
725
|
-
const changes = [];
|
|
726
|
-
// Catch removed props, prepend them, so they can be reset or removed
|
|
727
|
-
if (remove) {
|
|
728
|
-
const previousKeys = Object.keys(previousProps);
|
|
729
|
-
for (const previousKey of previousKeys) {
|
|
730
|
-
// @ts-ignore
|
|
731
|
-
if (!Object.hasOwn(props, previousKey)) {
|
|
732
|
-
propsEntries.unshift([previousKey, DEFAULT + 'remove']);
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
for (const [propKey, propValue] of propsEntries) {
|
|
737
|
-
if (is.equ(propValue, previousProps[propKey]))
|
|
738
|
-
continue;
|
|
739
|
-
changes.push([propKey, propValue]);
|
|
740
|
-
}
|
|
741
|
-
const memoized = { ...props };
|
|
742
|
-
if (localState.memoized && localState.memoized['args']) {
|
|
743
|
-
memoized['args'] = localState.memoized['args'];
|
|
744
|
-
}
|
|
745
|
-
if (localState.memoized && localState.memoized['attach']) {
|
|
746
|
-
memoized['attach'] = localState.memoized['attach'] || localState.attach;
|
|
747
|
-
}
|
|
748
|
-
return { changes, memoized };
|
|
749
|
-
}
|
|
750
|
-
function applyProps(instance, props) {
|
|
751
|
-
// props is empty
|
|
752
|
-
if (!Object.keys(props).length)
|
|
753
|
-
return instance;
|
|
754
|
-
// Filter equals, events and reserved props
|
|
755
|
-
const localState = getInstanceLocalState(instance) || {};
|
|
756
|
-
const rootState = localState.stateFactory?.();
|
|
757
|
-
const { changes, memoized } = diffProps(instance, props);
|
|
758
|
-
const instanceHandlers = localState.eventCount;
|
|
759
|
-
if (getInstanceLocalState(instance)) {
|
|
760
|
-
getInstanceLocalState(instance).memoized = memoized;
|
|
761
|
-
}
|
|
762
|
-
for (let i = 0; i < changes.length; i++) {
|
|
763
|
-
const key = changes[i][0];
|
|
764
|
-
const currentInstance = instance;
|
|
765
|
-
const targetProp = currentInstance[key];
|
|
766
|
-
let value = changes[i][1];
|
|
767
|
-
if (is.ref(value)) {
|
|
768
|
-
value = value.value;
|
|
769
|
-
}
|
|
770
|
-
if (value === DEFAULT + 'remove') {
|
|
771
|
-
if (targetProp && targetProp.constructor) {
|
|
772
|
-
// use the prop constructor to find the default it should be
|
|
773
|
-
value = new targetProp.constructor(...(memoized['args'] ?? []));
|
|
774
|
-
}
|
|
775
|
-
else if (currentInstance.constructor) {
|
|
776
|
-
const dummyInstance = new currentInstance.constructor(...(getInstanceLocalState(currentInstance)?.memoized?.['args'] || []));
|
|
777
|
-
value = dummyInstance[targetProp];
|
|
778
|
-
// destroy the instance
|
|
779
|
-
if (dummyInstance.dispose)
|
|
780
|
-
dummyInstance.dispose();
|
|
781
|
-
}
|
|
782
|
-
else {
|
|
783
|
-
value = 0;
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
// Special treatment for objects with support for set/copy, and layers
|
|
787
|
-
if (targetProp && targetProp['set'] && (targetProp['copy'] || targetProp instanceof THREE.Layers)) {
|
|
788
|
-
const isColor = targetProp instanceof THREE.Color;
|
|
789
|
-
// If value is an array
|
|
790
|
-
if (Array.isArray(value)) {
|
|
791
|
-
if (targetProp['fromArray'])
|
|
792
|
-
targetProp['fromArray'](value);
|
|
793
|
-
else
|
|
794
|
-
targetProp['set'](...value);
|
|
795
|
-
}
|
|
796
|
-
// Test again target.copy(class) next ...
|
|
797
|
-
else if (targetProp['copy'] &&
|
|
798
|
-
value &&
|
|
799
|
-
value.constructor &&
|
|
800
|
-
targetProp.constructor.name === value.constructor.name) {
|
|
801
|
-
targetProp['copy'](value);
|
|
802
|
-
if (!is.supportColorManagement() && !rootState.linear && isColor) {
|
|
803
|
-
targetProp['convertSRGBToLinear']();
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
// If nothing else fits, just set the single value, ignore undefined
|
|
807
|
-
// https://github.com/pmndrs/react-three-fiber/issues/274
|
|
808
|
-
else if (value !== undefined) {
|
|
809
|
-
const isColor = targetProp instanceof THREE.Color;
|
|
810
|
-
// Allow setting array scalars
|
|
811
|
-
if (!isColor && targetProp['setScalar'])
|
|
812
|
-
targetProp['setScalar'](value);
|
|
813
|
-
// Layers have no copy function, we must therefore copy the mask property
|
|
814
|
-
else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers)
|
|
815
|
-
targetProp.mask = value.mask;
|
|
816
|
-
// Otherwise just set ...
|
|
817
|
-
else
|
|
818
|
-
targetProp['set'](value);
|
|
819
|
-
// For versions of three which don't support THREE.ColorManagement,
|
|
820
|
-
// Auto-convert sRGB colors
|
|
821
|
-
// https://github.com/pmndrs/react-three-fiber/issues/344
|
|
822
|
-
if (!is.supportColorManagement() && !rootState.linear && isColor)
|
|
823
|
-
targetProp.convertSRGBToLinear();
|
|
824
|
-
}
|
|
825
|
-
// Else, just overwrite the value
|
|
826
|
-
}
|
|
827
|
-
else {
|
|
828
|
-
currentInstance[key] = value;
|
|
829
|
-
// Auto-convert sRGB textures, for now ...
|
|
830
|
-
// https://github.com/pmndrs/react-three-fiber/issues/344
|
|
831
|
-
if (!rootState?.linear && currentInstance[key] instanceof THREE.Texture) {
|
|
832
|
-
currentInstance[key]['encoding'] = THREE.sRGBEncoding;
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
checkNeedsUpdate(targetProp);
|
|
836
|
-
invalidateInstance(instance);
|
|
837
|
-
}
|
|
838
|
-
if (localState.parentRef &&
|
|
839
|
-
rootState.internal &&
|
|
840
|
-
instance['raycast'] &&
|
|
841
|
-
instanceHandlers !== localState.eventCount) {
|
|
842
|
-
// Pre-emptively remove the instance from the interaction manager
|
|
843
|
-
rootState.removeInteraction(instance['uuid']);
|
|
844
|
-
// Add the instance to the interaction manager only when it has handlers
|
|
845
|
-
if (localState.eventCount)
|
|
846
|
-
rootState.addInteraction(instance);
|
|
847
|
-
}
|
|
848
|
-
return instance;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
215
|
function updateCamera(camera, size) {
|
|
852
|
-
// https://github.com/pmndrs/react-three-fiber/issues/92
|
|
853
|
-
// Do not mess with the camera if it belongs to the user
|
|
854
216
|
if (!camera.manual) {
|
|
855
|
-
if (is.
|
|
217
|
+
if (is.orthographicCamera(camera)) {
|
|
856
218
|
camera.left = size.width / -2;
|
|
857
219
|
camera.right = size.width / 2;
|
|
858
220
|
camera.top = size.height / 2;
|
|
@@ -862,161 +224,172 @@ function updateCamera(camera, size) {
|
|
|
862
224
|
camera.aspect = size.width / size.height;
|
|
863
225
|
}
|
|
864
226
|
camera.updateProjectionMatrix();
|
|
865
|
-
// https://github.com/pmndrs/react-three-fiber/issues/178
|
|
866
|
-
// Update matrix world since the renderer is a frame late
|
|
867
227
|
camera.updateMatrixWorld();
|
|
868
228
|
}
|
|
869
229
|
}
|
|
870
|
-
function createDefaultCamera(isOrthographic, size) {
|
|
871
|
-
if (isOrthographic) {
|
|
872
|
-
return new THREE.OrthographicCamera(0, 0, 0, 0, 0.1, 1000);
|
|
873
|
-
}
|
|
874
|
-
return new THREE.PerspectiveCamera(75, size.width / size.height, 0.1, 1000);
|
|
875
|
-
}
|
|
876
230
|
|
|
877
|
-
function
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
return
|
|
231
|
+
function getLocalState(obj) {
|
|
232
|
+
if (!obj)
|
|
233
|
+
return {};
|
|
234
|
+
return obj['__ngt__'] || {};
|
|
881
235
|
}
|
|
882
|
-
|
|
883
|
-
const
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
|
|
888
|
-
*/
|
|
889
|
-
const addEffect = (callback) => createSubs(callback, globalEffects);
|
|
890
|
-
/**
|
|
891
|
-
* Adds a global after-render callback which is called each frame.
|
|
892
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
|
|
893
|
-
*/
|
|
894
|
-
const addAfterEffect = (callback) => createSubs(callback, globalAfterEffects);
|
|
895
|
-
/**
|
|
896
|
-
* Adds a global callback which is called when rendering stops.
|
|
897
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
|
|
898
|
-
*/
|
|
899
|
-
const addTail = (callback) => createSubs(callback, globalTailEffects);
|
|
900
|
-
function run(effects, timestamp) {
|
|
901
|
-
if (!effects.size)
|
|
902
|
-
return;
|
|
903
|
-
for (const { callback } of effects.values()) {
|
|
904
|
-
callback(timestamp);
|
|
905
|
-
}
|
|
236
|
+
function invalidateInstance(instance) {
|
|
237
|
+
const state = getLocalState(instance).store?.get();
|
|
238
|
+
if (state && state.internal.frames === 0)
|
|
239
|
+
state.invalidate();
|
|
240
|
+
checkUpdate(instance);
|
|
906
241
|
}
|
|
907
|
-
function
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
242
|
+
function prepare(object, localState) {
|
|
243
|
+
const instance = object;
|
|
244
|
+
if (localState?.primitive || !instance.__ngt__) {
|
|
245
|
+
const { objects = new BehaviorSubject([]), nonObjects = new BehaviorSubject([]), ...rest } = localState || {};
|
|
246
|
+
instance.__ngt__ = {
|
|
247
|
+
previousAttach: null,
|
|
248
|
+
store: null,
|
|
249
|
+
parent: null,
|
|
250
|
+
memoized: {},
|
|
251
|
+
eventCount: 0,
|
|
252
|
+
handlers: {},
|
|
253
|
+
objects,
|
|
254
|
+
nonObjects,
|
|
255
|
+
add: (object, type) => {
|
|
256
|
+
instance.__ngt__[type].next([...instance.__ngt__[type].value, object]);
|
|
257
|
+
notifyAncestors(instance.__ngt__.parent);
|
|
258
|
+
},
|
|
259
|
+
remove: (object, type) => {
|
|
260
|
+
instance.__ngt__[type].next(instance.__ngt__[type].value.filter((o) => o !== object));
|
|
261
|
+
notifyAncestors(instance.__ngt__.parent);
|
|
262
|
+
},
|
|
263
|
+
...rest,
|
|
264
|
+
};
|
|
915
265
|
}
|
|
266
|
+
return instance;
|
|
916
267
|
}
|
|
917
|
-
function
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
268
|
+
function notifyAncestors(instance) {
|
|
269
|
+
if (!instance)
|
|
270
|
+
return;
|
|
271
|
+
const localState = getLocalState(instance);
|
|
272
|
+
if (localState.objects)
|
|
273
|
+
localState.objects.next(localState.objects.value);
|
|
274
|
+
if (localState.nonObjects)
|
|
275
|
+
localState.nonObjects.next(localState.nonObjects.value);
|
|
276
|
+
notifyAncestors(localState.parent);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function diffProps(instance, props) {
|
|
280
|
+
const propsEntries = Object.entries(props);
|
|
281
|
+
const changes = [];
|
|
282
|
+
for (const [propKey, propValue] of propsEntries) {
|
|
283
|
+
if (is.equ(propValue, instance[propKey]))
|
|
284
|
+
continue;
|
|
285
|
+
changes.push([propKey, propValue]);
|
|
933
286
|
}
|
|
934
|
-
|
|
935
|
-
if (!state.internal.priority && state.gl.render)
|
|
936
|
-
state.gl.render(state.scene, state.camera);
|
|
937
|
-
// Decrease frame count
|
|
938
|
-
state.internal.frames = Math.max(0, state.internal.frames - 1);
|
|
939
|
-
return state.frameloop === 'always' ? 1 : state.internal.frames;
|
|
287
|
+
return changes;
|
|
940
288
|
}
|
|
941
|
-
function
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
289
|
+
function applyProps(instance, props) {
|
|
290
|
+
// if props is empty
|
|
291
|
+
if (!Object.keys(props).length)
|
|
292
|
+
return instance;
|
|
293
|
+
// filter equals, events , and reserved props
|
|
294
|
+
const localState = getLocalState(instance);
|
|
295
|
+
const rootState = localState.store?.get();
|
|
296
|
+
const changes = diffProps(instance, props);
|
|
297
|
+
for (let i = 0; i < changes.length; i++) {
|
|
298
|
+
const key = changes[i][0];
|
|
299
|
+
const currentInstance = instance;
|
|
300
|
+
const targetProp = currentInstance[key];
|
|
301
|
+
const value = changes[i][1];
|
|
302
|
+
// special treatmen for objects with support for set/copy, and layers
|
|
303
|
+
if (targetProp && targetProp['set'] && (targetProp['copy'] || targetProp instanceof THREE.Layers)) {
|
|
304
|
+
const isColor = targetProp instanceof THREE.Color;
|
|
305
|
+
// if value is an array
|
|
306
|
+
if (Array.isArray(value)) {
|
|
307
|
+
if (targetProp['fromArray'])
|
|
308
|
+
targetProp['fromArray'](value);
|
|
309
|
+
else
|
|
310
|
+
targetProp['set'](...value);
|
|
311
|
+
}
|
|
312
|
+
// test again target.copy
|
|
313
|
+
else if (targetProp['copy'] &&
|
|
314
|
+
value &&
|
|
315
|
+
value.constructor &&
|
|
316
|
+
targetProp.constructor.name === value.constructor.name) {
|
|
317
|
+
targetProp['copy'](value);
|
|
318
|
+
if (!THREE.ColorManagement && !rootState.linear && isColor) {
|
|
319
|
+
targetProp['convertSRGBToLinear']();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// if nothing else fits, just set the single value, ignore undefined
|
|
323
|
+
else if (value !== undefined) {
|
|
324
|
+
const isColor = targetProp instanceof THREE.Color;
|
|
325
|
+
// allow setting array scalars
|
|
326
|
+
if (!isColor && targetProp['setScalar'])
|
|
327
|
+
targetProp['setScalar'](value);
|
|
328
|
+
// layers have no copy function, copy the mask
|
|
329
|
+
else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers) {
|
|
330
|
+
targetProp.mask = value.mask;
|
|
331
|
+
}
|
|
332
|
+
// otherwise just set ...
|
|
333
|
+
else {
|
|
334
|
+
targetProp['set'](value);
|
|
335
|
+
}
|
|
336
|
+
// auto-convert srgb
|
|
337
|
+
if (!THREE.ColorManagement && !rootState?.linear && isColor) {
|
|
338
|
+
targetProp.convertSRGBToLinear();
|
|
339
|
+
}
|
|
960
340
|
}
|
|
961
341
|
}
|
|
962
|
-
//
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
running = false;
|
|
970
|
-
return cancelAnimationFrame(frame);
|
|
342
|
+
// else just overwrite the value
|
|
343
|
+
else {
|
|
344
|
+
currentInstance[key] = value;
|
|
345
|
+
// auto-convert srgb textures
|
|
346
|
+
if (!rootState?.linear && currentInstance[key] instanceof THREE.Texture) {
|
|
347
|
+
currentInstance[key]['encoding'] = THREE.sRGBEncoding;
|
|
348
|
+
}
|
|
971
349
|
}
|
|
350
|
+
checkUpdate(targetProp);
|
|
351
|
+
invalidateInstance(instance);
|
|
972
352
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
return;
|
|
981
|
-
// Increase frames, do not go higher than 60
|
|
982
|
-
stateToInvalidate.internal.frames = Math.min(60, stateToInvalidate.internal.frames + frames);
|
|
983
|
-
// If the render-loop isn't active, start it
|
|
984
|
-
if (!running) {
|
|
985
|
-
running = true;
|
|
986
|
-
requestAnimationFrame(loop);
|
|
987
|
-
}
|
|
353
|
+
const instanceHandlers = localState.eventCount;
|
|
354
|
+
if (localState.parent && rootState.internal && instance['raycast'] && instanceHandlers !== localState.eventCount) {
|
|
355
|
+
// pre-emptively remove the interaction from manager
|
|
356
|
+
rootState.removeInteraction(instance['uuid']);
|
|
357
|
+
// add the instance to the interaction manager only when it has handlers
|
|
358
|
+
if (localState.eventCount)
|
|
359
|
+
rootState.addInteraction(instance);
|
|
988
360
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
flushGlobalEffects('before', timestamp);
|
|
992
|
-
if (!stateFactory)
|
|
993
|
-
for (const root of roots.values())
|
|
994
|
-
render(timestamp, root);
|
|
995
|
-
else
|
|
996
|
-
render(timestamp, stateFactory, frame);
|
|
997
|
-
if (runGlobalEffects)
|
|
998
|
-
flushGlobalEffects('after', timestamp);
|
|
361
|
+
if (localState.parent && localState.afterUpdate && localState.afterUpdate.observed && changes.length) {
|
|
362
|
+
localState.afterUpdate.emit(instance);
|
|
999
363
|
}
|
|
1000
|
-
return
|
|
1001
|
-
loop,
|
|
1002
|
-
/**
|
|
1003
|
-
* Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
|
|
1004
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
|
|
1005
|
-
*/
|
|
1006
|
-
invalidate,
|
|
1007
|
-
/**
|
|
1008
|
-
* Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
|
|
1009
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
|
|
1010
|
-
*/
|
|
1011
|
-
advance,
|
|
1012
|
-
};
|
|
364
|
+
return instance;
|
|
1013
365
|
}
|
|
1014
366
|
|
|
1015
|
-
|
|
367
|
+
const idCache = {};
|
|
368
|
+
function makeId(event) {
|
|
369
|
+
if (event) {
|
|
370
|
+
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
371
|
+
}
|
|
372
|
+
const newId = THREE.MathUtils.generateUUID();
|
|
373
|
+
// ensure not already used
|
|
374
|
+
if (!idCache[newId]) {
|
|
375
|
+
idCache[newId] = true;
|
|
376
|
+
return newId;
|
|
377
|
+
}
|
|
378
|
+
return makeId();
|
|
379
|
+
}
|
|
380
|
+
function makeDpr(dpr, window) {
|
|
381
|
+
const target = window?.devicePixelRatio || 1;
|
|
382
|
+
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
|
|
383
|
+
}
|
|
384
|
+
function makeDefaultCamera(isOrthographic, size) {
|
|
385
|
+
if (isOrthographic)
|
|
386
|
+
return new THREE.OrthographicCamera(0, 0, 0, 0, 0.1, 1000);
|
|
387
|
+
return new THREE.PerspectiveCamera(75, size.width / size.height, 0.1, 1000);
|
|
388
|
+
}
|
|
389
|
+
function makeDefaultRenderer(glOptions, canvasElement) {
|
|
1016
390
|
const customRenderer = (typeof glOptions === 'function' ? glOptions(canvasElement) : glOptions);
|
|
1017
|
-
if (customRenderer?.render != null)
|
|
391
|
+
if (customRenderer?.render != null)
|
|
1018
392
|
return customRenderer;
|
|
1019
|
-
}
|
|
1020
393
|
return new THREE.WebGLRenderer({
|
|
1021
394
|
powerPreference: 'high-performance',
|
|
1022
395
|
canvas: canvasElement,
|
|
@@ -1025,157 +398,176 @@ function createRenderer(glOptions, canvasElement) {
|
|
|
1025
398
|
...(glOptions || {}),
|
|
1026
399
|
});
|
|
1027
400
|
}
|
|
401
|
+
function makeObjectGraph(object) {
|
|
402
|
+
const data = { nodes: {}, materials: {} };
|
|
403
|
+
if (object) {
|
|
404
|
+
object.traverse((child) => {
|
|
405
|
+
if (child.name)
|
|
406
|
+
data.nodes[child.name] = child;
|
|
407
|
+
if ('material' in child && !data.materials[child.material.name]) {
|
|
408
|
+
data.materials[child.material.name] = child
|
|
409
|
+
.material;
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
return data;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
const startWithUndefined = () => startWith(undefined);
|
|
417
|
+
/**
|
|
418
|
+
* An extended `tap` operator that accepts an `effectFn` which:
|
|
419
|
+
* - runs on every `next` notification from `source$`
|
|
420
|
+
* - can optionally return a `cleanUp` function that
|
|
421
|
+
* invokes from the 2nd `next` notification onward and on `unsubscribe` (destroyed)
|
|
422
|
+
*
|
|
423
|
+
*
|
|
424
|
+
* @example
|
|
425
|
+
* ```typescript
|
|
426
|
+
* source$.pipe(
|
|
427
|
+
* tapEffect((sourceValue) = {
|
|
428
|
+
* const cb = () => {
|
|
429
|
+
* doStuff(sourceValue);
|
|
430
|
+
* };
|
|
431
|
+
* addListener('event', cb);
|
|
432
|
+
*
|
|
433
|
+
* return () => {
|
|
434
|
+
* removeListener('event', cb);
|
|
435
|
+
* }
|
|
436
|
+
* })
|
|
437
|
+
* )
|
|
438
|
+
* ```
|
|
439
|
+
*/
|
|
440
|
+
function tapEffect(effectFn) {
|
|
441
|
+
let cleanupFn = () => { };
|
|
442
|
+
let firstRun = false;
|
|
443
|
+
let prev = undefined;
|
|
444
|
+
const teardown = (error) => {
|
|
445
|
+
return () => {
|
|
446
|
+
if (cleanupFn) {
|
|
447
|
+
cleanupFn({ prev, complete: true, error });
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
};
|
|
451
|
+
return tap({
|
|
452
|
+
next: (value) => {
|
|
453
|
+
if (cleanupFn && firstRun) {
|
|
454
|
+
cleanupFn({ prev, complete: false, error: false });
|
|
455
|
+
}
|
|
456
|
+
const cleanUpOrVoid = effectFn(value);
|
|
457
|
+
if (cleanUpOrVoid) {
|
|
458
|
+
cleanupFn = cleanUpOrVoid;
|
|
459
|
+
}
|
|
460
|
+
prev = value;
|
|
461
|
+
if (!firstRun) {
|
|
462
|
+
firstRun = true;
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
complete: teardown(false),
|
|
466
|
+
unsubscribe: teardown(false),
|
|
467
|
+
error: teardown(true),
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
class NgtRxStore extends RxState {
|
|
471
|
+
constructor() {
|
|
472
|
+
super();
|
|
473
|
+
// set a dummy property so that initial this.get() won't return undefined
|
|
474
|
+
this.set({ __ngt_dummy__: '__ngt_dummy__' });
|
|
475
|
+
// call initialize that might be setup by derived Stores
|
|
476
|
+
this.initialize();
|
|
477
|
+
// override set so our consumers don't have to handle undefined for state that already have default values
|
|
478
|
+
const originalSet = this.set.bind(this);
|
|
479
|
+
Object.defineProperty(this, 'set', {
|
|
480
|
+
get: () => {
|
|
481
|
+
// Parameters type does not do well with overloads. So we use any[] here
|
|
482
|
+
return (...args) => {
|
|
483
|
+
const firstArg = args[0];
|
|
484
|
+
if (is.obj(firstArg)) {
|
|
485
|
+
const modArgs = Object.entries(firstArg).reduce((modded, [key, value]) => {
|
|
486
|
+
modded[key] = value === undefined ? this.get(key) : value;
|
|
487
|
+
return modded;
|
|
488
|
+
}, {});
|
|
489
|
+
return originalSet(modArgs);
|
|
490
|
+
}
|
|
491
|
+
// @ts-ignore
|
|
492
|
+
return originalSet(...args);
|
|
493
|
+
};
|
|
494
|
+
},
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
initialize() {
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
effect(obs, sideEffectFn) {
|
|
501
|
+
return this.hold(obs.pipe(tapEffect(sideEffectFn)));
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
NgtRxStore.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRxStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
505
|
+
NgtRxStore.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRxStore });
|
|
506
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRxStore, decorators: [{
|
|
507
|
+
type: Injectable
|
|
508
|
+
}], ctorParameters: function () { return []; } });
|
|
1028
509
|
|
|
1029
510
|
const rootStateMap = new Map();
|
|
1030
511
|
const { invalidate, advance } = createLoop(rootStateMap);
|
|
1031
512
|
const shallowLoose = { objects: 'shallow', strict: false };
|
|
1032
|
-
class NgtStore extends
|
|
513
|
+
class NgtStore extends NgtRxStore {
|
|
1033
514
|
constructor() {
|
|
1034
515
|
super(...arguments);
|
|
1035
516
|
this.parentStore = inject(NgtStore, { optional: true, skipSelf: true });
|
|
1036
|
-
this.
|
|
1037
|
-
this.window = injectWindow();
|
|
1038
|
-
this.position = new THREE.Vector3();
|
|
1039
|
-
this.defaultTarget = new THREE.Vector3();
|
|
1040
|
-
this.tempTarget = new THREE.Vector3();
|
|
1041
|
-
this.resize = this.effect(($) => {
|
|
1042
|
-
let oldSize = this.read((s) => s.size);
|
|
1043
|
-
let oldDpr = this.read((s) => s.viewport?.dpr);
|
|
1044
|
-
return $.pipe(tap(() => {
|
|
1045
|
-
const { camera, size, viewport, gl } = this.read();
|
|
1046
|
-
// Resize camera and renderer on changes to size and pixelratio
|
|
1047
|
-
if (size !== oldSize || viewport.dpr !== oldDpr) {
|
|
1048
|
-
oldSize = size;
|
|
1049
|
-
oldDpr = viewport.dpr;
|
|
1050
|
-
// Update camera & renderer
|
|
1051
|
-
updateCamera(camera, size);
|
|
1052
|
-
gl.setPixelRatio(viewport.dpr);
|
|
1053
|
-
gl.setSize(size.width, size.height, size.updateStyle);
|
|
1054
|
-
}
|
|
1055
|
-
}));
|
|
1056
|
-
});
|
|
1057
|
-
this.invalidate = this.effect(tap(() => void this.read((s) => s.invalidate)()));
|
|
517
|
+
this.window = inject(DOCUMENT).defaultView;
|
|
1058
518
|
this.isInit = false;
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
this.write((state) => ({
|
|
1088
|
-
size,
|
|
1089
|
-
viewport: {
|
|
1090
|
-
...state.viewport,
|
|
1091
|
-
...this.getCurrentViewport(camera, this.defaultTarget, size),
|
|
1092
|
-
},
|
|
1093
|
-
}));
|
|
1094
|
-
};
|
|
1095
|
-
this.setCamera = (camera) => {
|
|
1096
|
-
this.write((s) => ({
|
|
1097
|
-
camera,
|
|
1098
|
-
viewport: {
|
|
1099
|
-
...s.viewport,
|
|
1100
|
-
...this.getCurrentViewport(camera),
|
|
1101
|
-
},
|
|
1102
|
-
}));
|
|
1103
|
-
this.read((s) => s.cameraRef).set(camera);
|
|
1104
|
-
};
|
|
1105
|
-
this.setDpr = (dpr) => {
|
|
1106
|
-
const resolved = makeDpr(dpr, this.window);
|
|
1107
|
-
this.write((s) => ({
|
|
1108
|
-
viewport: {
|
|
1109
|
-
...s.viewport,
|
|
1110
|
-
dpr: resolved,
|
|
1111
|
-
initialDpr: s.viewport.initialDpr || resolved,
|
|
1112
|
-
},
|
|
1113
|
-
}));
|
|
1114
|
-
};
|
|
1115
|
-
this.setFrameloop = (frameloop = 'always') => {
|
|
1116
|
-
const clock = this.read((s) => s.clock);
|
|
1117
|
-
// if frameloop === "never" clock.elapsedTime is updated using advance(timestamp)
|
|
1118
|
-
clock.stop();
|
|
1119
|
-
clock.elapsedTime = 0;
|
|
1120
|
-
if (frameloop !== 'never') {
|
|
1121
|
-
clock.start();
|
|
1122
|
-
clock.elapsedTime = 0;
|
|
1123
|
-
}
|
|
1124
|
-
this.write({ frameloop });
|
|
1125
|
-
};
|
|
1126
|
-
this.getCurrentViewport = (camera = this.read((s) => s.camera), target = this.defaultTarget, size = this.read((s) => s.size)) => {
|
|
1127
|
-
const { width, height, top, left } = size;
|
|
1128
|
-
const aspect = width / height;
|
|
1129
|
-
if (target instanceof THREE.Vector3)
|
|
1130
|
-
this.tempTarget.copy(target);
|
|
1131
|
-
else
|
|
1132
|
-
this.tempTarget.set(...target);
|
|
1133
|
-
const distance = camera.getWorldPosition(this.position).distanceTo(this.tempTarget);
|
|
1134
|
-
if (is.orthographic(camera)) {
|
|
519
|
+
}
|
|
520
|
+
init() {
|
|
521
|
+
if (!this.isInit) {
|
|
522
|
+
const position = new THREE.Vector3();
|
|
523
|
+
const defaultTarget = new THREE.Vector3();
|
|
524
|
+
const tempTarget = new THREE.Vector3();
|
|
525
|
+
const getCurrentViewport = (camera = this.get('camera'), target = defaultTarget, size = this.get('size')) => {
|
|
526
|
+
const { width, height, top, left } = size;
|
|
527
|
+
const aspect = width / height;
|
|
528
|
+
if (target instanceof THREE.Vector3)
|
|
529
|
+
tempTarget.copy(target);
|
|
530
|
+
else
|
|
531
|
+
tempTarget.set(...target);
|
|
532
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
533
|
+
if (is.orthographicCamera(camera)) {
|
|
534
|
+
return {
|
|
535
|
+
width: width / camera.zoom,
|
|
536
|
+
height: height / camera.zoom,
|
|
537
|
+
top,
|
|
538
|
+
left,
|
|
539
|
+
factor: 1,
|
|
540
|
+
distance,
|
|
541
|
+
aspect,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
const fov = (camera.fov * Math.PI) / 180; // convert vertical fov to radians
|
|
545
|
+
const h = 2 * Math.tan(fov / 2) * distance; // visible height
|
|
546
|
+
const w = h * aspect;
|
|
1135
547
|
return {
|
|
1136
|
-
width:
|
|
1137
|
-
height:
|
|
548
|
+
width: w,
|
|
549
|
+
height: h,
|
|
1138
550
|
top,
|
|
1139
551
|
left,
|
|
1140
|
-
factor:
|
|
552
|
+
factor: width / w,
|
|
1141
553
|
distance,
|
|
1142
554
|
aspect,
|
|
1143
555
|
};
|
|
1144
|
-
}
|
|
1145
|
-
const fov = (camera.fov * Math.PI) / 180; // convert vertical fov to radians
|
|
1146
|
-
const h = 2 * Math.tan(fov / 2) * distance; // visible height
|
|
1147
|
-
const w = h * (width / height);
|
|
1148
|
-
return {
|
|
1149
|
-
width: w,
|
|
1150
|
-
height: h,
|
|
1151
|
-
top,
|
|
1152
|
-
left,
|
|
1153
|
-
factor: width / w,
|
|
1154
|
-
distance,
|
|
1155
|
-
aspect,
|
|
1156
556
|
};
|
|
1157
|
-
};
|
|
1158
|
-
}
|
|
1159
|
-
get rootStateFactory() {
|
|
1160
|
-
let root = this.read((s) => s.previousStateFactory);
|
|
1161
|
-
while (root && root().previousStateFactory) {
|
|
1162
|
-
root = root().previousStateFactory;
|
|
1163
|
-
}
|
|
1164
|
-
return root || this.read;
|
|
1165
|
-
}
|
|
1166
|
-
init() {
|
|
1167
|
-
if (!this.isInit) {
|
|
1168
557
|
const pointer = new THREE.Vector2();
|
|
1169
|
-
const scene = prepare(new THREE.Scene(), this.read, this.rootStateFactory, this.parentStore?.get((s) => s.sceneRef));
|
|
1170
558
|
let performanceTimeout;
|
|
1171
|
-
|
|
559
|
+
const setPerformanceCurrent = (current) => {
|
|
560
|
+
this.set((state) => ({ performance: { ...state.performance, current } }));
|
|
561
|
+
};
|
|
562
|
+
this.set({
|
|
563
|
+
get: this.get.bind(this),
|
|
564
|
+
set: this.set.bind(this),
|
|
565
|
+
select: this.select.bind(this),
|
|
1172
566
|
ready: false,
|
|
1173
|
-
|
|
1174
|
-
scene,
|
|
1175
|
-
sceneRef: new NgtRef(scene),
|
|
567
|
+
scene: prepare(new THREE.Scene(), { store: this }),
|
|
1176
568
|
events: { priority: 1, enabled: true, connected: false },
|
|
1177
|
-
invalidate: (frames = 1) => invalidate(this
|
|
1178
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, this
|
|
569
|
+
invalidate: (frames = 1) => invalidate(this, frames),
|
|
570
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, this),
|
|
1179
571
|
legacy: false,
|
|
1180
572
|
linear: false,
|
|
1181
573
|
flat: false,
|
|
@@ -1189,20 +581,19 @@ class NgtStore extends NgtComponentStore {
|
|
|
1189
581
|
max: 1,
|
|
1190
582
|
debounce: 200,
|
|
1191
583
|
regress: () => {
|
|
1192
|
-
this.
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
});
|
|
584
|
+
const state = this.get();
|
|
585
|
+
// clear timeout
|
|
586
|
+
if (performanceTimeout)
|
|
587
|
+
clearTimeout(performanceTimeout);
|
|
588
|
+
// set lower bound
|
|
589
|
+
if (state.performance.current !== state.performance.min) {
|
|
590
|
+
setPerformanceCurrent(state.performance.min);
|
|
591
|
+
}
|
|
592
|
+
// go back to upper bound
|
|
593
|
+
performanceTimeout = setTimeout(() => setPerformanceCurrent(this.get('performance', 'max') || 1), state.performance.debounce);
|
|
1203
594
|
},
|
|
1204
595
|
},
|
|
1205
|
-
size: { width: 0, height: 0, top: 0, left: 0
|
|
596
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
1206
597
|
viewport: {
|
|
1207
598
|
initialDpr: 0,
|
|
1208
599
|
dpr: 0,
|
|
@@ -1213,9 +604,9 @@ class NgtStore extends NgtComponentStore {
|
|
|
1213
604
|
aspect: 0,
|
|
1214
605
|
distance: 0,
|
|
1215
606
|
factor: 0,
|
|
1216
|
-
getCurrentViewport
|
|
607
|
+
getCurrentViewport,
|
|
1217
608
|
},
|
|
1218
|
-
|
|
609
|
+
previousStore: this.parentStore,
|
|
1219
610
|
internal: {
|
|
1220
611
|
active: false,
|
|
1221
612
|
priority: 0,
|
|
@@ -1223,127 +614,153 @@ class NgtStore extends NgtComponentStore {
|
|
|
1223
614
|
lastEvent: null,
|
|
1224
615
|
interaction: [],
|
|
1225
616
|
hovered: new Map(),
|
|
1226
|
-
capturedMap: new Map(),
|
|
1227
|
-
animations: new Map(),
|
|
1228
617
|
subscribers: [],
|
|
1229
618
|
initialClick: [0, 0],
|
|
1230
619
|
initialHits: [],
|
|
1231
|
-
|
|
1232
|
-
|
|
620
|
+
capturedMap: new Map(),
|
|
621
|
+
subscribe: (callback, priority = 0, store = this) => {
|
|
622
|
+
const internal = this.get('internal');
|
|
1233
623
|
// If this subscription was given a priority, it takes rendering into its own hands
|
|
1234
624
|
// For that reason we switch off automatic rendering and increase the manual flag
|
|
1235
625
|
// As long as this flag is positive there can be no internal rendering at all
|
|
1236
626
|
// because there could be multiple render subscriptions
|
|
1237
627
|
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
1238
|
-
internal.subscribers.push({ priority,
|
|
628
|
+
internal.subscribers.push({ priority, store, callback });
|
|
1239
629
|
// Register subscriber and sort layers from lowest to highest, meaning,
|
|
1240
630
|
// highest priority renders last (on top of the other frames)
|
|
1241
631
|
internal.subscribers.sort((a, b) => (a.priority || 0) - (b.priority || 0));
|
|
1242
632
|
return () => {
|
|
1243
|
-
const
|
|
1244
|
-
if (
|
|
633
|
+
const internal = this.get('internal');
|
|
634
|
+
if (internal?.subscribers) {
|
|
1245
635
|
// Decrease manual flag if this subscription had a priority
|
|
1246
|
-
|
|
636
|
+
internal.priority = internal.priority - (priority > 0 ? 1 : 0);
|
|
1247
637
|
// Remove subscriber from list
|
|
1248
|
-
|
|
638
|
+
internal.subscribers = internal.subscribers.filter((s) => s.callback !== callback);
|
|
1249
639
|
}
|
|
1250
640
|
};
|
|
1251
641
|
},
|
|
1252
642
|
},
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
setSize:
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
643
|
+
setEvents: (events) => {
|
|
644
|
+
this.set((state) => ({ events: { ...state.events, ...events } }));
|
|
645
|
+
},
|
|
646
|
+
setSize: (width, height, top, left) => {
|
|
647
|
+
const camera = this.get('camera');
|
|
648
|
+
const size = { width, height, top: top || 0, left: left || 0 };
|
|
649
|
+
this.set((state) => ({
|
|
650
|
+
size,
|
|
651
|
+
viewport: { ...state.viewport, ...getCurrentViewport(camera, defaultTarget, size) },
|
|
652
|
+
}));
|
|
653
|
+
},
|
|
654
|
+
setDpr: (dpr) => {
|
|
655
|
+
const resolved = makeDpr(dpr, this.window);
|
|
656
|
+
this.set((state) => ({
|
|
657
|
+
viewport: {
|
|
658
|
+
...state.viewport,
|
|
659
|
+
dpr: resolved,
|
|
660
|
+
initialDpr: state.viewport.initialDpr || resolved,
|
|
661
|
+
},
|
|
662
|
+
}));
|
|
663
|
+
},
|
|
664
|
+
setFrameloop: (frameloop = 'always') => {
|
|
665
|
+
const clock = this.get('clock');
|
|
666
|
+
clock.stop();
|
|
667
|
+
clock.elapsedTime = 0;
|
|
668
|
+
if (frameloop !== 'never') {
|
|
669
|
+
clock.start();
|
|
670
|
+
clock.elapsedTime = 0;
|
|
671
|
+
}
|
|
672
|
+
this.set({ frameloop });
|
|
673
|
+
},
|
|
674
|
+
addInteraction: (interaction) => {
|
|
675
|
+
this.set((state) => ({
|
|
676
|
+
internal: { ...state.internal, interaction: [...state.internal.interaction, interaction] },
|
|
677
|
+
}));
|
|
678
|
+
},
|
|
679
|
+
removeInteraction: (uuid) => {
|
|
680
|
+
this.set((state) => ({
|
|
681
|
+
internal: {
|
|
682
|
+
...state.internal,
|
|
683
|
+
interaction: state.internal.interaction.filter((interaction) => interaction.uuid !== uuid),
|
|
684
|
+
},
|
|
685
|
+
}));
|
|
686
|
+
},
|
|
1261
687
|
});
|
|
1262
688
|
this.isInit = true;
|
|
689
|
+
this.resize();
|
|
1263
690
|
}
|
|
1264
691
|
}
|
|
1265
692
|
configure(inputs, canvasElement) {
|
|
1266
|
-
const { gl: glOptions, size: sizeOptions, camera: cameraOptions, raycaster: raycasterOptions, events, orthographic, lookAt, shadows, linear,
|
|
1267
|
-
const state = this.
|
|
1268
|
-
|
|
693
|
+
const { gl: glOptions, size: sizeOptions, camera: cameraOptions, raycaster: raycasterOptions, events, orthographic, lookAt, shadows, linear, legacy, flat, dpr, frameloop, performance, } = inputs;
|
|
694
|
+
const state = this.get();
|
|
695
|
+
const stateToUpdate = {};
|
|
696
|
+
// setup renderer
|
|
1269
697
|
let gl = state.gl;
|
|
1270
698
|
if (!state.gl) {
|
|
1271
|
-
|
|
699
|
+
stateToUpdate.gl = gl = makeDefaultRenderer(glOptions, canvasElement);
|
|
1272
700
|
}
|
|
1273
|
-
//
|
|
701
|
+
// setup raycaster
|
|
1274
702
|
let raycaster = state.raycaster;
|
|
1275
703
|
if (!raycaster) {
|
|
1276
|
-
|
|
704
|
+
stateToUpdate.raycaster = raycaster = new THREE.Raycaster();
|
|
1277
705
|
}
|
|
1278
|
-
//
|
|
706
|
+
// set raycaster options
|
|
1279
707
|
const { params, ...options } = raycasterOptions || {};
|
|
1280
|
-
if (!is.equ(options, raycaster, shallowLoose))
|
|
708
|
+
if (!is.equ(options, raycaster, shallowLoose))
|
|
1281
709
|
applyProps(raycaster, { ...options });
|
|
1282
|
-
}
|
|
1283
710
|
if (!is.equ(params, raycaster.params, shallowLoose)) {
|
|
1284
|
-
applyProps(raycaster, {
|
|
1285
|
-
params: { ...raycaster.params, ...(params || {}) },
|
|
1286
|
-
});
|
|
711
|
+
applyProps(raycaster, { params: { ...raycaster.params, ...(params || {}) } });
|
|
1287
712
|
}
|
|
1288
|
-
//
|
|
713
|
+
// create default camera
|
|
1289
714
|
if (!state.camera) {
|
|
1290
715
|
const isCamera = is.camera(cameraOptions);
|
|
1291
|
-
let camera = isCamera ? cameraOptions :
|
|
716
|
+
let camera = isCamera ? cameraOptions : makeDefaultCamera(orthographic || false, state.size);
|
|
1292
717
|
if (!isCamera) {
|
|
1293
|
-
if (cameraOptions)
|
|
718
|
+
if (cameraOptions)
|
|
1294
719
|
applyProps(camera, cameraOptions);
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
if (!cameraOptions?.position) {
|
|
720
|
+
// set position.z
|
|
721
|
+
if (!cameraOptions?.position)
|
|
1298
722
|
camera.position.z = 5;
|
|
1299
|
-
|
|
1300
|
-
// Always look at center or passed-in lookAt by default
|
|
723
|
+
// always look at center or passed-in lookAt by default
|
|
1301
724
|
if (!cameraOptions?.rotation) {
|
|
1302
|
-
if (Array.isArray(lookAt))
|
|
725
|
+
if (Array.isArray(lookAt))
|
|
1303
726
|
camera.lookAt(lookAt[0], lookAt[1], lookAt[2]);
|
|
1304
|
-
|
|
1305
|
-
else if (lookAt instanceof THREE.Vector3) {
|
|
727
|
+
else if (lookAt instanceof THREE.Vector3)
|
|
1306
728
|
camera.lookAt(lookAt);
|
|
1307
|
-
|
|
1308
|
-
else {
|
|
729
|
+
else
|
|
1309
730
|
camera.lookAt(0, 0, 0);
|
|
1310
|
-
}
|
|
1311
731
|
}
|
|
1312
|
-
//
|
|
732
|
+
// update projection matrix after applyprops
|
|
1313
733
|
camera.updateProjectionMatrix();
|
|
1314
734
|
}
|
|
1315
735
|
if (!is.instance(camera)) {
|
|
1316
|
-
camera = prepare(camera,
|
|
736
|
+
camera = prepare(camera, { store: this });
|
|
1317
737
|
}
|
|
1318
|
-
|
|
1319
|
-
this.read((s) => s.cameraRef).set(camera);
|
|
738
|
+
stateToUpdate.camera = camera;
|
|
1320
739
|
}
|
|
1321
740
|
// Set up XR (one time only!)
|
|
1322
741
|
if (!state.xr) {
|
|
1323
742
|
// Handle frame behavior in WebXR
|
|
1324
743
|
const handleXRFrame = (timestamp, frame) => {
|
|
1325
|
-
const state = this.
|
|
744
|
+
const state = this.get();
|
|
1326
745
|
if (state.frameloop === 'never')
|
|
1327
746
|
return;
|
|
1328
|
-
advance(timestamp, true, this
|
|
747
|
+
advance(timestamp, true, this, frame);
|
|
1329
748
|
};
|
|
1330
749
|
// Toggle render switching on session
|
|
1331
750
|
const handleSessionChange = () => {
|
|
1332
|
-
const state = this.
|
|
751
|
+
const state = this.get();
|
|
1333
752
|
state.gl.xr.enabled = state.gl.xr.isPresenting;
|
|
1334
753
|
state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
|
|
1335
754
|
if (!state.gl.xr.isPresenting)
|
|
1336
|
-
invalidate(this
|
|
755
|
+
invalidate(this);
|
|
1337
756
|
};
|
|
1338
757
|
// WebXR session manager
|
|
1339
758
|
const xr = {
|
|
1340
759
|
connect: () => {
|
|
1341
|
-
const gl = this.read((s) => s.gl);
|
|
1342
760
|
gl.xr.addEventListener('sessionstart', handleSessionChange);
|
|
1343
761
|
gl.xr.addEventListener('sessionend', handleSessionChange);
|
|
1344
762
|
},
|
|
1345
763
|
disconnect: () => {
|
|
1346
|
-
const gl = this.read((s) => s.gl);
|
|
1347
764
|
gl.xr.removeEventListener('sessionstart', handleSessionChange);
|
|
1348
765
|
gl.xr.removeEventListener('sessionend', handleSessionChange);
|
|
1349
766
|
},
|
|
@@ -1351,7 +768,7 @@ class NgtStore extends NgtComponentStore {
|
|
|
1351
768
|
// Subscribe to WebXR session events
|
|
1352
769
|
if (gl.xr)
|
|
1353
770
|
xr.connect();
|
|
1354
|
-
|
|
771
|
+
stateToUpdate.xr = xr;
|
|
1355
772
|
}
|
|
1356
773
|
// Set shadowmap
|
|
1357
774
|
if (gl.shadowMap) {
|
|
@@ -1369,9 +786,8 @@ class NgtStore extends NgtComponentStore {
|
|
|
1369
786
|
}
|
|
1370
787
|
// Safely set color management if available.
|
|
1371
788
|
// Avoid accessing THREE.ColorManagement to play nice with older versions
|
|
1372
|
-
if (
|
|
789
|
+
if (THREE.ColorManagement)
|
|
1373
790
|
THREE.ColorManagement.legacyMode = state.legacy;
|
|
1374
|
-
}
|
|
1375
791
|
const outputEncoding = linear ? THREE.LinearEncoding : THREE.sRGBEncoding;
|
|
1376
792
|
const toneMapping = flat ? THREE.NoToneMapping : THREE.ACESFilmicToneMapping;
|
|
1377
793
|
if (gl.outputEncoding !== outputEncoding)
|
|
@@ -1380,71 +796,485 @@ class NgtStore extends NgtComponentStore {
|
|
|
1380
796
|
gl.toneMapping = toneMapping;
|
|
1381
797
|
// Update color management state
|
|
1382
798
|
if (state.legacy !== legacy)
|
|
1383
|
-
|
|
799
|
+
stateToUpdate.legacy = legacy;
|
|
1384
800
|
if (state.linear !== linear)
|
|
1385
|
-
|
|
801
|
+
stateToUpdate.linear = linear;
|
|
1386
802
|
if (state.flat !== flat)
|
|
1387
|
-
|
|
803
|
+
stateToUpdate.flat = flat;
|
|
1388
804
|
// Set gl props
|
|
1389
805
|
gl.setClearAlpha(0);
|
|
1390
806
|
gl.setPixelRatio(makeDpr(state.viewport.dpr));
|
|
1391
|
-
gl.setSize(state.size.width, state.size.height
|
|
807
|
+
gl.setSize(state.size.width, state.size.height);
|
|
1392
808
|
if (is.obj(glOptions) &&
|
|
1393
809
|
!(typeof glOptions === 'function') &&
|
|
1394
|
-
!is.
|
|
810
|
+
!is.renderer(glOptions) &&
|
|
1395
811
|
!is.equ(glOptions, gl, shallowLoose)) {
|
|
1396
812
|
applyProps(gl, glOptions);
|
|
1397
813
|
}
|
|
1398
814
|
// Store events internally
|
|
1399
815
|
if (events && !state.events.handlers) {
|
|
1400
|
-
|
|
816
|
+
stateToUpdate.events = events(this);
|
|
1401
817
|
}
|
|
818
|
+
// Check performance
|
|
819
|
+
if (performance && !is.equ(performance, state.performance, shallowLoose)) {
|
|
820
|
+
stateToUpdate.performance = { ...state.performance, ...performance };
|
|
821
|
+
}
|
|
822
|
+
this.set(stateToUpdate);
|
|
1402
823
|
// Check pixelratio
|
|
1403
|
-
if (dpr && state.viewport.dpr !== makeDpr(dpr))
|
|
824
|
+
if (dpr && state.viewport.dpr !== makeDpr(dpr))
|
|
1404
825
|
state.setDpr(dpr);
|
|
1405
|
-
}
|
|
1406
826
|
// Check size, allow it to take on container bounds initially
|
|
1407
827
|
const size = computeInitialSize(canvasElement, sizeOptions);
|
|
1408
|
-
if (!is.equ(size, state.size, shallowLoose))
|
|
828
|
+
if (!is.equ(size, state.size, shallowLoose))
|
|
1409
829
|
state.setSize(size.width, size.height, size.top, size.left);
|
|
1410
|
-
}
|
|
1411
830
|
// Check frameloop
|
|
1412
831
|
if (state.frameloop !== frameloop)
|
|
1413
832
|
state.setFrameloop(frameloop);
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
this.
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
833
|
+
if (!this.get('ready')) {
|
|
834
|
+
this.set({ ready: true });
|
|
835
|
+
}
|
|
836
|
+
this.invalidate();
|
|
837
|
+
}
|
|
838
|
+
resize() {
|
|
839
|
+
const state = this.get();
|
|
840
|
+
let oldSize = state.size;
|
|
841
|
+
let oldDpr = state.viewport.dpr;
|
|
842
|
+
let oldCamera = state.camera;
|
|
843
|
+
this.hold(this.select(selectSlice(['camera', 'size', 'viewport', 'gl'])), () => {
|
|
844
|
+
const { camera, size, viewport, gl, set } = this.get();
|
|
845
|
+
// resize camera and renderer on changes to size and dpr
|
|
846
|
+
if (size !== oldSize || viewport.dpr !== oldDpr) {
|
|
847
|
+
oldSize = size;
|
|
848
|
+
oldDpr = viewport.dpr;
|
|
849
|
+
// update camera
|
|
850
|
+
updateCamera(camera, size);
|
|
851
|
+
gl.setPixelRatio(viewport.dpr);
|
|
852
|
+
gl.setSize(size.width, size.height);
|
|
853
|
+
}
|
|
854
|
+
// update viewport when camera changes
|
|
855
|
+
if (camera !== oldCamera) {
|
|
856
|
+
updateCamera(camera, size);
|
|
857
|
+
oldCamera = camera;
|
|
858
|
+
set((state) => ({ viewport: { ...state.viewport, ...state.viewport.getCurrentViewport(camera) } }));
|
|
859
|
+
}
|
|
1425
860
|
});
|
|
1426
861
|
}
|
|
1427
|
-
|
|
1428
|
-
|
|
862
|
+
invalidate() {
|
|
863
|
+
this.hold(this.select(), () => invalidate(this));
|
|
1429
864
|
}
|
|
1430
865
|
}
|
|
1431
|
-
NgtStore.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.
|
|
1432
|
-
NgtStore.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.
|
|
1433
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.
|
|
866
|
+
NgtStore.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtStore, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
867
|
+
NgtStore.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtStore });
|
|
868
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtStore, decorators: [{
|
|
1434
869
|
type: Injectable
|
|
1435
870
|
}] });
|
|
1436
871
|
function computeInitialSize(canvas, defaultSize) {
|
|
1437
872
|
if (defaultSize) {
|
|
1438
873
|
return defaultSize;
|
|
1439
874
|
}
|
|
1440
|
-
if (
|
|
875
|
+
if (canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
1441
876
|
const { width, height, top, left } = canvas.parentElement.getBoundingClientRect();
|
|
1442
877
|
return { width, height, top, left };
|
|
1443
878
|
}
|
|
1444
|
-
return { width: 0, height: 0, top: 0, left: 0 };
|
|
879
|
+
return { width: 0, height: 0, top: 0, left: 0 };
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
const NGT_COMPOUND_PREFIXES = new InjectionToken('NgtCompoundPrefixes');
|
|
883
|
+
|
|
884
|
+
const catalogue = {};
|
|
885
|
+
function extend(objects) {
|
|
886
|
+
Object.assign(catalogue, objects);
|
|
887
|
+
}
|
|
888
|
+
const NGT_CATALOGUE = new InjectionToken('THREE Constructors Catalogue', { factory: () => catalogue });
|
|
889
|
+
|
|
890
|
+
class NgtArgs {
|
|
891
|
+
constructor() {
|
|
892
|
+
this.vcr = inject(ViewContainerRef);
|
|
893
|
+
this.template = inject(TemplateRef);
|
|
894
|
+
this.injectedArgs = [];
|
|
895
|
+
this.injected = false;
|
|
896
|
+
const commentNode = this.vcr.element.nativeElement;
|
|
897
|
+
if (commentNode['__ngt_renderer_add_comment__']) {
|
|
898
|
+
commentNode['__ngt_renderer_add_comment__']();
|
|
899
|
+
delete commentNode['__ngt_renderer_add_comment__'];
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
set args(args) {
|
|
903
|
+
if (args == null || !Array.isArray(args))
|
|
904
|
+
return;
|
|
905
|
+
if (args.length === 1 && args[0] === null)
|
|
906
|
+
return;
|
|
907
|
+
this.injected = false;
|
|
908
|
+
this.injectedArgs = args;
|
|
909
|
+
this.createView();
|
|
910
|
+
}
|
|
911
|
+
get args() {
|
|
912
|
+
if (this.validate()) {
|
|
913
|
+
this.injected = true;
|
|
914
|
+
return this.injectedArgs;
|
|
915
|
+
}
|
|
916
|
+
return null;
|
|
917
|
+
}
|
|
918
|
+
validate() {
|
|
919
|
+
return !this.injected && !!this.injectedArgs.length;
|
|
920
|
+
}
|
|
921
|
+
createView() {
|
|
922
|
+
if (this.view && !this.view.destroyed) {
|
|
923
|
+
this.view.destroy();
|
|
924
|
+
}
|
|
925
|
+
this.view = this.vcr.createEmbeddedView(this.template);
|
|
926
|
+
this.view.detectChanges();
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
NgtArgs.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtArgs, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
930
|
+
NgtArgs.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.1", type: NgtArgs, isStandalone: true, selector: "[args]", inputs: { args: "args" }, ngImport: i0 });
|
|
931
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtArgs, decorators: [{
|
|
932
|
+
type: Directive,
|
|
933
|
+
args: [{ selector: '[args]', standalone: true }]
|
|
934
|
+
}], ctorParameters: function () { return []; }, propDecorators: { args: [{
|
|
935
|
+
type: Input
|
|
936
|
+
}] } });
|
|
937
|
+
|
|
938
|
+
function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
|
|
939
|
+
const captureData = captures.get(obj);
|
|
940
|
+
if (captureData) {
|
|
941
|
+
captures.delete(obj);
|
|
942
|
+
// if this was the last captured object for this pointer
|
|
943
|
+
if (captures.size === 0) {
|
|
944
|
+
capturedMap.delete(pointerId);
|
|
945
|
+
captureData.target.releasePointerCapture(pointerId);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
function removeInteractivity(store, object) {
|
|
950
|
+
const internal = store.get('internal');
|
|
951
|
+
// removes every trace of an object from data store
|
|
952
|
+
internal.interaction = internal.interaction.filter((o) => o !== object);
|
|
953
|
+
internal.initialHits = internal.initialHits.filter((o) => o !== object);
|
|
954
|
+
internal.hovered.forEach((value, key) => {
|
|
955
|
+
if (value.eventObject === object || value.object === object) {
|
|
956
|
+
// clear out intersects, they are outdated by now
|
|
957
|
+
internal.hovered.delete(key);
|
|
958
|
+
}
|
|
959
|
+
});
|
|
960
|
+
internal.capturedMap.forEach((captures, pointerId) => {
|
|
961
|
+
releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
|
|
962
|
+
});
|
|
963
|
+
if (store.get('previousStore')) {
|
|
964
|
+
removeInteractivity(store.get('previousStore'), object);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
function createEvents(store) {
|
|
968
|
+
/** calculates delta **/
|
|
969
|
+
function calculateDistance(event) {
|
|
970
|
+
const internal = store.get('internal');
|
|
971
|
+
const dx = event.offsetX - internal.initialClick[0];
|
|
972
|
+
const dy = event.offsetY - internal.initialClick[1];
|
|
973
|
+
return Math.round(Math.sqrt(dx * dx + dy * dy));
|
|
974
|
+
}
|
|
975
|
+
/** returns true if an instance has a valid pointer-event registered, this excludes scroll, clicks etc... **/
|
|
976
|
+
function filterPointerEvents(objects) {
|
|
977
|
+
return objects.filter((obj) => ['move', 'over', 'enter', 'out', 'leave'].some((name) => {
|
|
978
|
+
const eventName = `pointer${name}`;
|
|
979
|
+
return getLocalState(obj).handlers?.[eventName];
|
|
980
|
+
}));
|
|
981
|
+
}
|
|
982
|
+
function intersect(event, filter) {
|
|
983
|
+
const state = store.get();
|
|
984
|
+
const duplicates = new Set();
|
|
985
|
+
const intersections = [];
|
|
986
|
+
// allow callers to eliminate event objects
|
|
987
|
+
const eventObjects = filter ? filter(state.internal.interaction) : state.internal.interaction;
|
|
988
|
+
// reset all raycaster cameras to undefined
|
|
989
|
+
for (let i = 0; i < eventObjects.length; i++) {
|
|
990
|
+
const instanceState = getLocalState(eventObjects[i]).store?.get();
|
|
991
|
+
if (instanceState) {
|
|
992
|
+
instanceState.raycaster.camera = undefined;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
if (!state.previousStore) {
|
|
996
|
+
// make sure root-level pointer and ray are setup
|
|
997
|
+
state.events.compute?.(event, store);
|
|
998
|
+
}
|
|
999
|
+
function handleRaycast(obj) {
|
|
1000
|
+
const objLocalState = getLocalState(obj);
|
|
1001
|
+
const objStore = objLocalState.store;
|
|
1002
|
+
const objState = objStore?.get();
|
|
1003
|
+
// skip event handling when noEvents is set, or when raycaster camera is null
|
|
1004
|
+
if (!objState || !objState.events.enabled || objState.raycaster.camera === null)
|
|
1005
|
+
return [];
|
|
1006
|
+
// when the camera is undefined, we have to call the events layers to update function
|
|
1007
|
+
if (objState.raycaster.camera === undefined) {
|
|
1008
|
+
objState.events.compute?.(event, objStore, objState.previousStore);
|
|
1009
|
+
// if the camera is still undefined, we have to skip this layer entirely
|
|
1010
|
+
if (objState.raycaster.camera === undefined)
|
|
1011
|
+
objState.raycaster.camera = null;
|
|
1012
|
+
}
|
|
1013
|
+
// intersect object by object
|
|
1014
|
+
return objState.raycaster.camera ? objState.raycaster.intersectObject(obj, true) : [];
|
|
1015
|
+
}
|
|
1016
|
+
// collect events
|
|
1017
|
+
let hits = eventObjects
|
|
1018
|
+
// intersect objects
|
|
1019
|
+
.flatMap(handleRaycast)
|
|
1020
|
+
// sort by event priority
|
|
1021
|
+
.sort((a, b) => {
|
|
1022
|
+
const aState = getLocalState(a.object).store.get();
|
|
1023
|
+
const bState = getLocalState(b.object).store.get();
|
|
1024
|
+
if (!aState || !bState)
|
|
1025
|
+
return a.distance - b.distance;
|
|
1026
|
+
return bState.events.priority - aState.events.priority || a.distance - b.distance;
|
|
1027
|
+
})
|
|
1028
|
+
// filter out duplicates
|
|
1029
|
+
.filter((item) => {
|
|
1030
|
+
const id = makeId(item);
|
|
1031
|
+
if (duplicates.has(id))
|
|
1032
|
+
return false;
|
|
1033
|
+
duplicates.add(id);
|
|
1034
|
+
return true;
|
|
1035
|
+
});
|
|
1036
|
+
// allow custom userland intersect sort order, this likely only makes sense on the root
|
|
1037
|
+
if (state.events.filter)
|
|
1038
|
+
hits = state.events.filter(hits, store);
|
|
1039
|
+
// bubble up the events, find the event source
|
|
1040
|
+
for (const hit of hits) {
|
|
1041
|
+
let eventObject = hit.object;
|
|
1042
|
+
// bubble event up
|
|
1043
|
+
while (eventObject) {
|
|
1044
|
+
if (getLocalState(eventObject).eventCount) {
|
|
1045
|
+
intersections.push({ ...hit, eventObject });
|
|
1046
|
+
}
|
|
1047
|
+
eventObject = eventObject.parent;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
// if the interaction is captured, make all capturing targets part of the intersects
|
|
1051
|
+
if ('pointerId' in event && state.internal.capturedMap.has(event.pointerId)) {
|
|
1052
|
+
for (const capturedData of state.internal.capturedMap.get(event.pointerId).values()) {
|
|
1053
|
+
if (!duplicates.has(makeId(capturedData.intersection))) {
|
|
1054
|
+
intersections.push(capturedData.intersection);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
return intersections;
|
|
1059
|
+
}
|
|
1060
|
+
/** handle intersections by forwarding them to handlers */
|
|
1061
|
+
function handleIntersects(intersections, event, delta, callback) {
|
|
1062
|
+
const rootState = store.get();
|
|
1063
|
+
// if anything has been found, forward it to the event listeners
|
|
1064
|
+
if (intersections.length) {
|
|
1065
|
+
const localState = { stopped: false };
|
|
1066
|
+
for (const hit of intersections) {
|
|
1067
|
+
const state = getLocalState(hit.object).store?.get() || rootState;
|
|
1068
|
+
const { raycaster, pointer, camera, internal } = state;
|
|
1069
|
+
const unprojectedPoint = new THREE.Vector3(pointer.x, pointer.y, 0).unproject(camera);
|
|
1070
|
+
const hasPointerCapture = (id) => internal.capturedMap.get(id)?.has(hit.eventObject) ?? false;
|
|
1071
|
+
const setPointerCapture = (id) => {
|
|
1072
|
+
const captureData = { intersection: hit, target: event.target };
|
|
1073
|
+
if (internal.capturedMap.has(id)) {
|
|
1074
|
+
// if the pointerId was previously captured, we add the hit to the event capturedMap
|
|
1075
|
+
internal.capturedMap.get(id).set(hit.eventObject, captureData);
|
|
1076
|
+
}
|
|
1077
|
+
else {
|
|
1078
|
+
// if the pointerId was not previously captured, we create a Map containing the hitObject, and the hit. hitObject is used for faster access
|
|
1079
|
+
internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
|
|
1080
|
+
}
|
|
1081
|
+
// call the original event now
|
|
1082
|
+
event.target.setPointerCapture(id);
|
|
1083
|
+
};
|
|
1084
|
+
const releasePointerCapture = (id) => {
|
|
1085
|
+
const captures = internal.capturedMap.get(id);
|
|
1086
|
+
if (captures) {
|
|
1087
|
+
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
// add native event props
|
|
1091
|
+
const extractEventProps = {};
|
|
1092
|
+
// This iterates over the event's properties including the inherited ones. Native PointerEvents have most of their props as getters which are inherited, but polyfilled PointerEvents have them all as their own properties (i.e. not inherited). We can't use Object.keys() or Object.entries() as they only return "own" properties; nor Object.getPrototypeOf(event) as that *doesn't* return "own" properties, only inherited ones.
|
|
1093
|
+
for (const prop in event) {
|
|
1094
|
+
const property = event[prop];
|
|
1095
|
+
// only copy over atomics, leave functions alone as these should be called as event.nativeEvent.fn()
|
|
1096
|
+
if (typeof property !== 'function') {
|
|
1097
|
+
extractEventProps[prop] = property;
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
const raycastEvent = {
|
|
1101
|
+
...hit,
|
|
1102
|
+
...extractEventProps,
|
|
1103
|
+
pointer,
|
|
1104
|
+
intersections,
|
|
1105
|
+
stopped: localState.stopped,
|
|
1106
|
+
delta,
|
|
1107
|
+
unprojectedPoint,
|
|
1108
|
+
ray: raycaster.ray,
|
|
1109
|
+
camera: camera,
|
|
1110
|
+
// Hijack stopPropagation, which just sets a flag
|
|
1111
|
+
stopPropagation() {
|
|
1112
|
+
// https://github.com/pmndrs/react-three-fiber/issues/596
|
|
1113
|
+
// Events are not allowed to stop propagation if the pointer has been captured
|
|
1114
|
+
const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId);
|
|
1115
|
+
// We only authorize stopPropagation...
|
|
1116
|
+
if (
|
|
1117
|
+
// ...if this pointer hasn't been captured
|
|
1118
|
+
!capturesForPointer ||
|
|
1119
|
+
// ... or if the hit object is capturing the pointer
|
|
1120
|
+
capturesForPointer.has(hit.eventObject)) {
|
|
1121
|
+
raycastEvent.stopped = localState.stopped = true;
|
|
1122
|
+
// Propagation is stopped, remove all other hover records
|
|
1123
|
+
// An event handler is only allowed to flush other handlers if it is hovered itself
|
|
1124
|
+
if (internal.hovered.size &&
|
|
1125
|
+
Array.from(internal.hovered.values()).find((i) => i.eventObject === hit.eventObject)) {
|
|
1126
|
+
// Objects cannot flush out higher up objects that have already caught the event
|
|
1127
|
+
const higher = intersections.slice(0, intersections.indexOf(hit));
|
|
1128
|
+
cancelPointer([...higher, hit]);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
},
|
|
1132
|
+
// there should be a distinction between target and currentTarget
|
|
1133
|
+
target: { hasPointerCapture, setPointerCapture, releasePointerCapture },
|
|
1134
|
+
currentTarget: { hasPointerCapture, setPointerCapture, releasePointerCapture },
|
|
1135
|
+
nativeEvent: event,
|
|
1136
|
+
};
|
|
1137
|
+
// call subscribers
|
|
1138
|
+
callback(raycastEvent);
|
|
1139
|
+
// event bubbling may be interupted by stopPropagation
|
|
1140
|
+
if (localState.stopped === true)
|
|
1141
|
+
break;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
return intersections;
|
|
1145
|
+
}
|
|
1146
|
+
function cancelPointer(intersections) {
|
|
1147
|
+
const { internal } = store.get();
|
|
1148
|
+
for (const hoveredObj of internal.hovered.values()) {
|
|
1149
|
+
// When no objects were hit or the hovered object wasn't found underneath the cursor
|
|
1150
|
+
// we call onPointerOut and delete the object from the hovered-elements map
|
|
1151
|
+
if (!intersections.length ||
|
|
1152
|
+
!intersections.find((hit) => hit.object === hoveredObj.object &&
|
|
1153
|
+
hit.index === hoveredObj.index &&
|
|
1154
|
+
hit.instanceId === hoveredObj.instanceId)) {
|
|
1155
|
+
const eventObject = hoveredObj.eventObject;
|
|
1156
|
+
const instance = getLocalState(eventObject);
|
|
1157
|
+
const handlers = instance?.handlers;
|
|
1158
|
+
internal.hovered.delete(makeId(hoveredObj));
|
|
1159
|
+
if (instance?.eventCount) {
|
|
1160
|
+
// Clear out intersects, they are outdated by now
|
|
1161
|
+
const data = { ...hoveredObj, intersections };
|
|
1162
|
+
handlers?.pointerout?.(data);
|
|
1163
|
+
handlers?.pointerleave?.(data);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
function pointerMissed(event, objects) {
|
|
1169
|
+
for (let i = 0; i < objects.length; i++) {
|
|
1170
|
+
const instance = getLocalState(objects[i]);
|
|
1171
|
+
instance?.handlers.pointermissed?.(event);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
function handlePointer(name) {
|
|
1175
|
+
// Deal with cancelation
|
|
1176
|
+
switch (name) {
|
|
1177
|
+
case 'pointerleave':
|
|
1178
|
+
case 'pointercancel':
|
|
1179
|
+
return () => cancelPointer([]);
|
|
1180
|
+
case 'lostpointercapture':
|
|
1181
|
+
return (event) => {
|
|
1182
|
+
const { internal } = store.get();
|
|
1183
|
+
if ('pointerId' in event && !internal.capturedMap.has(event.pointerId)) {
|
|
1184
|
+
// If the object event interface had onLostPointerCapture, we'd call it here on every
|
|
1185
|
+
// object that's getting removed.
|
|
1186
|
+
internal.capturedMap.delete(event.pointerId);
|
|
1187
|
+
cancelPointer([]);
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
// Any other pointer goes here ...
|
|
1192
|
+
return function handleEvent(event) {
|
|
1193
|
+
const { onPointerMissed, internal } = store.get();
|
|
1194
|
+
// prepareRay(event)
|
|
1195
|
+
internal.lastEvent = event;
|
|
1196
|
+
// Get fresh intersects
|
|
1197
|
+
const isPointerMove = name === 'pointermove';
|
|
1198
|
+
const isClickEvent = name === 'click' || name === 'contextmenu' || name === 'dblclick';
|
|
1199
|
+
const filter = isPointerMove ? filterPointerEvents : undefined;
|
|
1200
|
+
// const hits = patchIntersects(intersect(filter), event)
|
|
1201
|
+
const hits = intersect(event, filter);
|
|
1202
|
+
const delta = isClickEvent ? calculateDistance(event) : 0;
|
|
1203
|
+
// Save initial coordinates on pointer-down
|
|
1204
|
+
if (name === 'pointerdown') {
|
|
1205
|
+
internal.initialClick = [event.offsetX, event.offsetY];
|
|
1206
|
+
internal.initialHits = hits.map((hit) => hit.eventObject);
|
|
1207
|
+
}
|
|
1208
|
+
// If a click yields no results, pass it back to the user as a miss
|
|
1209
|
+
// Missed events have to come first in order to establish user-land side-effect clean up
|
|
1210
|
+
if (isClickEvent && !hits.length) {
|
|
1211
|
+
if (delta <= 2) {
|
|
1212
|
+
pointerMissed(event, internal.interaction);
|
|
1213
|
+
if (onPointerMissed)
|
|
1214
|
+
onPointerMissed(event);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
// Take care of unhover
|
|
1218
|
+
if (isPointerMove)
|
|
1219
|
+
cancelPointer(hits);
|
|
1220
|
+
function onIntersect(data) {
|
|
1221
|
+
const eventObject = data.eventObject;
|
|
1222
|
+
const instance = getLocalState(eventObject);
|
|
1223
|
+
const handlers = instance?.handlers;
|
|
1224
|
+
// Check presence of handlers
|
|
1225
|
+
if (!instance?.eventCount)
|
|
1226
|
+
return;
|
|
1227
|
+
if (isPointerMove) {
|
|
1228
|
+
// Move event ...
|
|
1229
|
+
if (handlers?.pointerover ||
|
|
1230
|
+
handlers?.pointerenter ||
|
|
1231
|
+
handlers?.pointerout ||
|
|
1232
|
+
handlers?.pointerleave) {
|
|
1233
|
+
// When enter or out is present take care of hover-state
|
|
1234
|
+
const id = makeId(data);
|
|
1235
|
+
const hoveredItem = internal.hovered.get(id);
|
|
1236
|
+
if (!hoveredItem) {
|
|
1237
|
+
// If the object wasn't previously hovered, book it and call its handler
|
|
1238
|
+
internal.hovered.set(id, data);
|
|
1239
|
+
handlers.pointerover?.(data);
|
|
1240
|
+
handlers.pointerenter?.(data);
|
|
1241
|
+
}
|
|
1242
|
+
else if (hoveredItem.stopped) {
|
|
1243
|
+
// If the object was previously hovered and stopped, we shouldn't allow other items to proceed
|
|
1244
|
+
data.stopPropagation();
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
// Call mouse move
|
|
1248
|
+
handlers?.pointermove?.(data);
|
|
1249
|
+
}
|
|
1250
|
+
else {
|
|
1251
|
+
// All other events ...
|
|
1252
|
+
const handler = handlers?.[name];
|
|
1253
|
+
if (handler) {
|
|
1254
|
+
// Forward all events back to their respective handlers with the exception of click events,
|
|
1255
|
+
// which must use the initial target
|
|
1256
|
+
if (!isClickEvent || internal.initialHits.includes(eventObject)) {
|
|
1257
|
+
// Missed events have to come first
|
|
1258
|
+
pointerMissed(event, internal.interaction.filter((object) => !internal.initialHits.includes(object)));
|
|
1259
|
+
// Now call the handler
|
|
1260
|
+
handler(data);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
else {
|
|
1264
|
+
// Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
|
|
1265
|
+
if (isClickEvent && internal.initialHits.includes(eventObject)) {
|
|
1266
|
+
pointerMissed(event, internal.interaction.filter((object) => !internal.initialHits.includes(object)));
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
handleIntersects(hits, event, delta, onIntersect);
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
return { handlePointer };
|
|
1445
1275
|
}
|
|
1446
1276
|
|
|
1447
|
-
function
|
|
1277
|
+
function attach(object, value, paths = []) {
|
|
1448
1278
|
const [base, ...remaining] = paths;
|
|
1449
1279
|
if (!base)
|
|
1450
1280
|
return;
|
|
@@ -1452,751 +1282,1150 @@ function mutate(object, value, paths = []) {
|
|
|
1452
1282
|
applyProps(object, { [base]: value });
|
|
1453
1283
|
}
|
|
1454
1284
|
else {
|
|
1455
|
-
// assign an empty object in order to spread object if undefined
|
|
1456
1285
|
assignEmpty(object, base);
|
|
1457
|
-
|
|
1458
|
-
|
|
1286
|
+
attach(object[base], value, remaining);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
function detach(parent, child, attachProp) {
|
|
1290
|
+
const childLocalState = getLocalState(child);
|
|
1291
|
+
if (Array.isArray(attachProp)) {
|
|
1292
|
+
attach(parent, childLocalState.previousAttach, attachProp);
|
|
1293
|
+
}
|
|
1294
|
+
else {
|
|
1295
|
+
childLocalState.previousAttach();
|
|
1459
1296
|
}
|
|
1460
1297
|
}
|
|
1461
1298
|
function assignEmpty(obj, base) {
|
|
1462
|
-
if (
|
|
1463
|
-
// @ts-ignore
|
|
1464
|
-
(!Object.hasOwn(obj, base) && Reflect && !!Reflect.has && !Reflect.has(obj, base)) ||
|
|
1465
|
-
obj[base] === undefined) {
|
|
1299
|
+
if ((!Object.hasOwn(obj, base) && Reflect && !!Reflect.has && !Reflect.has(obj, base)) || obj[base] === undefined) {
|
|
1466
1300
|
obj[base] = {};
|
|
1467
1301
|
}
|
|
1468
1302
|
}
|
|
1469
1303
|
|
|
1470
|
-
const
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1304
|
+
const SPECIAL_DOM_TAG = {
|
|
1305
|
+
NGT_PORTAL: 'ngt-portal',
|
|
1306
|
+
NGT_PRIMITIVE: 'ngt-primitive',
|
|
1307
|
+
NGT_VALUE: 'ngt-value',
|
|
1308
|
+
};
|
|
1309
|
+
const SPECIAL_PROPERTIES = {
|
|
1310
|
+
COMPOUND: 'ngtCompound',
|
|
1311
|
+
RENDER_PRIORITY: 'priority',
|
|
1312
|
+
ATTACH: 'attach',
|
|
1313
|
+
VALUE: 'rawValue',
|
|
1314
|
+
REF: 'ref',
|
|
1315
|
+
};
|
|
1316
|
+
const SPECIAL_EVENTS = {
|
|
1317
|
+
BEFORE_RENDER: 'beforeRender',
|
|
1318
|
+
AFTER_UPDATE: 'afterUpdate',
|
|
1319
|
+
AFTER_ATTACH: 'afterAttach',
|
|
1320
|
+
};
|
|
1321
|
+
function attachThreeChild(parent, child) {
|
|
1322
|
+
const pLS = getLocalState(parent);
|
|
1323
|
+
const cLS = getLocalState(child);
|
|
1324
|
+
if (!pLS || !cLS) {
|
|
1325
|
+
throw new Error(`[NGT] THREE instances need to be prepared with local state.`);
|
|
1326
|
+
}
|
|
1327
|
+
// whether the child is added to the parent with parent.add()
|
|
1328
|
+
let added = false;
|
|
1329
|
+
// assign store on child if not already exist
|
|
1330
|
+
if (!cLS.store) {
|
|
1331
|
+
cLS.store = pLS.store;
|
|
1332
|
+
}
|
|
1333
|
+
if (cLS.attach) {
|
|
1334
|
+
const attachProp = cLS.attach;
|
|
1335
|
+
if (typeof attachProp === 'function') {
|
|
1336
|
+
const attachCleanUp = attachProp(parent, child, cLS.store);
|
|
1337
|
+
if (attachCleanUp)
|
|
1338
|
+
cLS.previousAttach = attachCleanUp;
|
|
1339
|
+
}
|
|
1340
|
+
else {
|
|
1341
|
+
// we skip attach none if set explicitly
|
|
1342
|
+
if (attachProp[0] === 'none') {
|
|
1343
|
+
invalidateInstance(child);
|
|
1344
|
+
return;
|
|
1478
1345
|
}
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1346
|
+
// handle material array
|
|
1347
|
+
if (attachProp[0] === 'material' &&
|
|
1348
|
+
attachProp[1] &&
|
|
1349
|
+
typeof Number(attachProp[1]) === 'number' &&
|
|
1350
|
+
is.material(child) &&
|
|
1351
|
+
!Array.isArray(parent['material'])) {
|
|
1352
|
+
parent['material'] = [];
|
|
1353
|
+
}
|
|
1354
|
+
// attach
|
|
1355
|
+
if (cLS.isRaw) {
|
|
1356
|
+
cLS.parent = parent;
|
|
1357
|
+
// at this point we don't have rawValue yet, so we bail and wait until the Renderer recalls attach
|
|
1358
|
+
if (child.__ngt_renderer__[10 /* NgtRendererClassId.rawValue */] === undefined)
|
|
1359
|
+
return;
|
|
1360
|
+
attach(parent, child.__ngt_renderer__[10 /* NgtRendererClassId.rawValue */], attachProp);
|
|
1361
|
+
}
|
|
1362
|
+
else {
|
|
1363
|
+
attach(parent, child, attachProp);
|
|
1364
|
+
}
|
|
1365
|
+
// save value
|
|
1366
|
+
cLS.previousAttach = attachProp.reduce((value, property) => value[property], parent);
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
else if (is.object3D(parent) && is.object3D(child)) {
|
|
1370
|
+
parent.add(child);
|
|
1371
|
+
added = true;
|
|
1372
|
+
}
|
|
1373
|
+
pLS.add(child, added ? 'objects' : 'nonObjects');
|
|
1374
|
+
cLS.parent = parent;
|
|
1375
|
+
if (cLS.afterAttach) {
|
|
1376
|
+
cLS.afterAttach.emit({ parent, node: child });
|
|
1377
|
+
}
|
|
1378
|
+
invalidateInstance(child);
|
|
1379
|
+
invalidateInstance(parent);
|
|
1380
|
+
}
|
|
1381
|
+
function removeThreeChild(parent, child, dispose) {
|
|
1382
|
+
const pLS = getLocalState(parent);
|
|
1383
|
+
const cLS = getLocalState(child);
|
|
1384
|
+
// clear parent ref
|
|
1385
|
+
cLS.parent = null;
|
|
1386
|
+
// remove child from parent
|
|
1387
|
+
if (pLS.objects) {
|
|
1388
|
+
pLS.remove(child, 'objects');
|
|
1389
|
+
}
|
|
1390
|
+
if (pLS.nonObjects) {
|
|
1391
|
+
pLS.remove(child, 'nonObjects');
|
|
1392
|
+
}
|
|
1393
|
+
if (cLS.attach) {
|
|
1394
|
+
detach(parent, child, cLS.attach);
|
|
1395
|
+
}
|
|
1396
|
+
else if (is.object3D(parent) && is.object3D(child)) {
|
|
1397
|
+
parent.remove(child);
|
|
1398
|
+
removeInteractivity(cLS.store || pLS.store, child);
|
|
1399
|
+
}
|
|
1400
|
+
const isPrimitive = cLS.primitive;
|
|
1401
|
+
if (!isPrimitive) {
|
|
1402
|
+
removeThreeRecursive(cLS.objects?.value || [], child, !!dispose);
|
|
1403
|
+
removeThreeRecursive(child.childre, child, !!dispose);
|
|
1404
|
+
}
|
|
1405
|
+
// dispose
|
|
1406
|
+
if (child['dispose'] && !is.scene(child)) {
|
|
1407
|
+
queueMicrotask(() => child['dispose']());
|
|
1408
|
+
}
|
|
1409
|
+
invalidateInstance(parent);
|
|
1410
|
+
}
|
|
1411
|
+
function removeThreeRecursive(array, parent, dispose) {
|
|
1412
|
+
if (array)
|
|
1413
|
+
[...array].forEach((child) => removeThreeChild(parent, child, dispose));
|
|
1414
|
+
}
|
|
1415
|
+
function processThreeEvent(instance, priority, eventName, callback, cdr) {
|
|
1416
|
+
const lS = getLocalState(instance);
|
|
1417
|
+
if (eventName === SPECIAL_EVENTS.BEFORE_RENDER) {
|
|
1418
|
+
return lS.store
|
|
1419
|
+
.get('internal')
|
|
1420
|
+
.subscribe((state) => callback({ state, object: instance }), priority || lS.priority || 0);
|
|
1421
|
+
}
|
|
1422
|
+
if (eventName === SPECIAL_EVENTS.AFTER_UPDATE || eventName === SPECIAL_EVENTS.AFTER_ATTACH) {
|
|
1423
|
+
if (!lS[eventName]) {
|
|
1424
|
+
lS[eventName] = new EventEmitter();
|
|
1425
|
+
}
|
|
1426
|
+
const sub = lS[eventName]?.subscribe(callback);
|
|
1427
|
+
return sub.unsubscribe.bind(sub);
|
|
1428
|
+
}
|
|
1429
|
+
if (!lS.handlers) {
|
|
1430
|
+
lS.handlers = {};
|
|
1431
|
+
}
|
|
1432
|
+
// try to get the previous handler. compound might have one, the THREE object might also have one with the same name
|
|
1433
|
+
const previousHandler = lS.handlers[eventName];
|
|
1434
|
+
// readjust the callback
|
|
1435
|
+
const updatedCallback = (event) => {
|
|
1436
|
+
if (previousHandler)
|
|
1437
|
+
previousHandler(event);
|
|
1438
|
+
callback(event);
|
|
1439
|
+
};
|
|
1440
|
+
lS.handlers = {
|
|
1441
|
+
...lS.handlers,
|
|
1442
|
+
[eventName]: eventToHandler(updatedCallback, cdr),
|
|
1443
|
+
};
|
|
1444
|
+
// increment the count everytime
|
|
1445
|
+
lS.eventCount += 1;
|
|
1446
|
+
// but only add the instance (target) to the interaction array (so that it is handled by the EventManager with Raycast)
|
|
1447
|
+
// the first time eventCount is incremented
|
|
1448
|
+
if (lS.eventCount === 1 && instance['raycast']) {
|
|
1449
|
+
lS.store.get('addInteraction')(instance);
|
|
1450
|
+
}
|
|
1451
|
+
// clean up the event listener by removing the target from the interaction array
|
|
1452
|
+
return () => {
|
|
1453
|
+
const localState = getLocalState(instance);
|
|
1454
|
+
if (localState && localState.eventCount) {
|
|
1455
|
+
localState.store.get('removeInteraction')(instance['uuid']);
|
|
1456
|
+
}
|
|
1482
1457
|
};
|
|
1483
1458
|
}
|
|
1484
|
-
function
|
|
1485
|
-
return
|
|
1459
|
+
function eventToHandler(callback, cdr) {
|
|
1460
|
+
return (event) => {
|
|
1461
|
+
callback(event);
|
|
1462
|
+
cdr.detectChanges();
|
|
1463
|
+
};
|
|
1486
1464
|
}
|
|
1487
|
-
function
|
|
1488
|
-
|
|
1465
|
+
function kebabToPascal(str) {
|
|
1466
|
+
// split the string at each hyphen
|
|
1467
|
+
const parts = str.split('-');
|
|
1468
|
+
// map over the parts, capitalizing the first letter of each part
|
|
1469
|
+
const pascalParts = parts.map((part) => {
|
|
1470
|
+
return part.charAt(0).toUpperCase() + part.slice(1);
|
|
1471
|
+
});
|
|
1472
|
+
// join the parts together to create the final PascalCase string
|
|
1473
|
+
return pascalParts.join('');
|
|
1489
1474
|
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
this.wheel = new EventEmitter();
|
|
1522
|
-
this.zone = inject(NgZone);
|
|
1523
|
-
this.store = inject(NgtStore);
|
|
1524
|
-
this.parentRef = injectInstanceRef({ skipSelf: true, optional: true });
|
|
1525
|
-
this._isRaw = false;
|
|
1526
|
-
this.hasEmittedAlready = false;
|
|
1527
|
-
this.instanceReady = this.effect(tapEffect(() => {
|
|
1528
|
-
this.handleEvents();
|
|
1529
|
-
let attachToParentSubscription;
|
|
1530
|
-
if (this.parentRef) {
|
|
1531
|
-
attachToParentSubscription = this.attachToParent(this.parent.pipe(filter((parent) => !!parent)));
|
|
1532
|
-
const { noAttach, skipWrapper } = this.read();
|
|
1533
|
-
if (!noAttach && !skipWrapper) {
|
|
1534
|
-
const parentInstanceNode = getInstanceLocalState(getInstanceLocalState(this.instanceValue)?.parentRef?.value);
|
|
1535
|
-
if (parentInstanceNode) {
|
|
1536
|
-
const collections = is.object3d(this.instanceValue)
|
|
1537
|
-
? parentInstanceNode.objectsRefs
|
|
1538
|
-
: parentInstanceNode.instancesRefs;
|
|
1539
|
-
collections.set((s) => [...s, this.instanceRef]);
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
let beforeRenderCleanUp;
|
|
1544
|
-
if (this.beforeRender && is.object3d(this.instanceValue) && is.object3d(this.proxyInstance)) {
|
|
1545
|
-
beforeRenderCleanUp = this.store
|
|
1546
|
-
.read((s) => s.internal)
|
|
1547
|
-
.subscribe((state, object) => this.beforeRender(state, object), this.priority, this.store.read, this.proxyInstance);
|
|
1548
|
-
}
|
|
1549
|
-
if (this.readyCallback)
|
|
1550
|
-
this.readyCallback(this.instanceValue);
|
|
1551
|
-
return () => {
|
|
1552
|
-
beforeRenderCleanUp?.();
|
|
1553
|
-
attachToParentSubscription?.unsubscribe();
|
|
1475
|
+
|
|
1476
|
+
class NgtRendererStore {
|
|
1477
|
+
constructor(root) {
|
|
1478
|
+
this.root = root;
|
|
1479
|
+
this.comments = [];
|
|
1480
|
+
this.portals = [];
|
|
1481
|
+
}
|
|
1482
|
+
createNode(type, node) {
|
|
1483
|
+
const state = [
|
|
1484
|
+
type,
|
|
1485
|
+
null,
|
|
1486
|
+
[],
|
|
1487
|
+
false,
|
|
1488
|
+
undefined,
|
|
1489
|
+
undefined,
|
|
1490
|
+
undefined,
|
|
1491
|
+
undefined,
|
|
1492
|
+
undefined,
|
|
1493
|
+
undefined,
|
|
1494
|
+
undefined,
|
|
1495
|
+
undefined,
|
|
1496
|
+
undefined,
|
|
1497
|
+
undefined,
|
|
1498
|
+
];
|
|
1499
|
+
const rendererNode = Object.assign(node, { __ngt_renderer__: state });
|
|
1500
|
+
if (state[0 /* NgtRendererClassId.type */] === 'comment') {
|
|
1501
|
+
state[13 /* NgtRendererClassId.injectorFactory */] = () => getDebugNode(rendererNode).injector;
|
|
1502
|
+
// we attach an arrow function to the Comment node
|
|
1503
|
+
// In our directives, we can call this function to then start tracking the RendererNode
|
|
1504
|
+
rendererNode['__ngt_renderer_add_comment__'] = () => {
|
|
1505
|
+
this.comments.push(rendererNode);
|
|
1554
1506
|
};
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1507
|
+
return rendererNode;
|
|
1508
|
+
}
|
|
1509
|
+
if (state[0 /* NgtRendererClassId.type */] === 'portal') {
|
|
1510
|
+
state[13 /* NgtRendererClassId.injectorFactory */] = () => getDebugNode(rendererNode).injector;
|
|
1511
|
+
this.portals.push(rendererNode);
|
|
1512
|
+
return rendererNode;
|
|
1513
|
+
}
|
|
1514
|
+
if (state[0 /* NgtRendererClassId.type */] === 'compound') {
|
|
1515
|
+
state[7 /* NgtRendererClassId.queueOps */] = new Set();
|
|
1516
|
+
state[8 /* NgtRendererClassId.attributes */] = {};
|
|
1517
|
+
state[9 /* NgtRendererClassId.properties */] = {};
|
|
1518
|
+
return rendererNode;
|
|
1519
|
+
}
|
|
1520
|
+
return rendererNode;
|
|
1521
|
+
}
|
|
1522
|
+
setParent(node, parent) {
|
|
1523
|
+
if (!node.__ngt_renderer__[1 /* NgtRendererClassId.parent */]) {
|
|
1524
|
+
node.__ngt_renderer__[1 /* NgtRendererClassId.parent */] = parent;
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
addChild(node, child) {
|
|
1528
|
+
if (!node.__ngt_renderer__[2 /* NgtRendererClassId.children */].includes(child)) {
|
|
1529
|
+
node.__ngt_renderer__[2 /* NgtRendererClassId.children */].push(child);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
removeChild(node, child) {
|
|
1533
|
+
const index = node.__ngt_renderer__[2 /* NgtRendererClassId.children */].findIndex((c) => child === c);
|
|
1534
|
+
if (index >= 0) {
|
|
1535
|
+
node.__ngt_renderer__[2 /* NgtRendererClassId.children */].splice(index, 1);
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
setCompound(compound, instance) {
|
|
1539
|
+
compound.__ngt_renderer__[6 /* NgtRendererClassId.compounded */] = instance;
|
|
1540
|
+
const attributes = Object.keys(compound.__ngt_renderer__[8 /* NgtRendererClassId.attributes */]);
|
|
1541
|
+
const properties = Object.keys(compound.__ngt_renderer__[9 /* NgtRendererClassId.properties */]);
|
|
1542
|
+
if (attributes.length) {
|
|
1543
|
+
for (const key of attributes) {
|
|
1544
|
+
this.applyAttribute(instance, key, compound.__ngt_renderer__[8 /* NgtRendererClassId.attributes */][key]);
|
|
1572
1545
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
};
|
|
1578
|
-
}));
|
|
1579
|
-
this.attachToParent = this.effect(tap(() => {
|
|
1580
|
-
const attach = this.read((s) => s.attach);
|
|
1581
|
-
let parentInstanceRef = this.__ngt__?.parentRef;
|
|
1582
|
-
// if no parentInstance, try re-run the factory due to late init
|
|
1583
|
-
if (!parentInstanceRef || !parentInstanceRef.value) {
|
|
1584
|
-
// return early if failed to retrieve
|
|
1585
|
-
if (!this.parent?.value)
|
|
1586
|
-
return;
|
|
1587
|
-
// reassign on instance internal state
|
|
1588
|
-
if (this.__ngt__) {
|
|
1589
|
-
this.__ngt__.parentRef = this.parent;
|
|
1590
|
-
}
|
|
1591
|
-
parentInstanceRef = this.parent;
|
|
1546
|
+
}
|
|
1547
|
+
if (properties.length) {
|
|
1548
|
+
for (const key of properties) {
|
|
1549
|
+
this.applyProperty(instance, key, compound.__ngt_renderer__[9 /* NgtRendererClassId.properties */][key]);
|
|
1592
1550
|
}
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1551
|
+
}
|
|
1552
|
+
this.executeOperation(compound);
|
|
1553
|
+
}
|
|
1554
|
+
queueOperation(node, op) {
|
|
1555
|
+
node.__ngt_renderer__[7 /* NgtRendererClassId.queueOps */].add(op);
|
|
1556
|
+
}
|
|
1557
|
+
executeOperation(node, type = 'op') {
|
|
1558
|
+
if (node.__ngt_renderer__[7 /* NgtRendererClassId.queueOps */]?.size) {
|
|
1559
|
+
node.__ngt_renderer__[7 /* NgtRendererClassId.queueOps */].forEach((op) => {
|
|
1560
|
+
if (op[0 /* NgtQueueOpClassId.type */] === type) {
|
|
1561
|
+
op[1 /* NgtQueueOpClassId.op */]();
|
|
1562
|
+
node.__ngt_renderer__[7 /* NgtRendererClassId.queueOps */].delete(op);
|
|
1597
1563
|
}
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
processPortalContainer(portal) {
|
|
1568
|
+
const injectorFactory = portal.__ngt_renderer__[13 /* NgtRendererClassId.injectorFactory */];
|
|
1569
|
+
const injector = injectorFactory?.();
|
|
1570
|
+
if (!injector)
|
|
1571
|
+
return;
|
|
1572
|
+
const portalStore = injector.get(NgtStore, null);
|
|
1573
|
+
if (!portalStore)
|
|
1574
|
+
return;
|
|
1575
|
+
const portalContainer = portalStore.get('scene');
|
|
1576
|
+
if (!portalContainer)
|
|
1577
|
+
return;
|
|
1578
|
+
portal.__ngt_renderer__[12 /* NgtRendererClassId.portalContainer */] = this.createNode('three', portalContainer);
|
|
1579
|
+
}
|
|
1580
|
+
applyAttribute(node, name, value) {
|
|
1581
|
+
if (node.__ngt_renderer__[3 /* NgtRendererClassId.destroyed */])
|
|
1582
|
+
return;
|
|
1583
|
+
if (name === SPECIAL_PROPERTIES.RENDER_PRIORITY) {
|
|
1584
|
+
// priority needs to be set as an attribute string so that they can be set as early as possible
|
|
1585
|
+
// we convert that string to a number. if it's invalid, 0
|
|
1586
|
+
let priority = Number(value);
|
|
1587
|
+
if (isNaN(priority)) {
|
|
1588
|
+
priority = 0;
|
|
1589
|
+
console.warn(`[NGT] "priority" is an invalid number, default to 0`);
|
|
1598
1590
|
}
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
}
|
|
1620
|
-
// retrieve the current value on the parentInstance, so we can reset it later
|
|
1621
|
-
if (this.__ngt__) {
|
|
1622
|
-
this.__ngt__.attachValue = propertyToAttach.reduce((value, property) => value[property], parentInstanceRef.value);
|
|
1623
|
-
}
|
|
1624
|
-
// attach the instance value on the parent
|
|
1625
|
-
mutate(parentInstanceRef.value, this.proxyInstance, propertyToAttach);
|
|
1626
|
-
}
|
|
1627
|
-
// validate on the instance
|
|
1628
|
-
invalidateInstance(this.instanceValue);
|
|
1629
|
-
// validate on the parent
|
|
1630
|
-
if (getInstanceLocalState(parentInstanceRef.value)) {
|
|
1631
|
-
invalidateInstance(parentInstanceRef.value);
|
|
1632
|
-
}
|
|
1633
|
-
// save the attach
|
|
1634
|
-
if (this.__ngt__) {
|
|
1635
|
-
this.__ngt__.attach = propertyToAttach;
|
|
1636
|
-
}
|
|
1637
|
-
this.write({ attach: propertyToAttach });
|
|
1591
|
+
getLocalState(node).priority = priority;
|
|
1592
|
+
}
|
|
1593
|
+
if (name === SPECIAL_PROPERTIES.COMPOUND) {
|
|
1594
|
+
// we set the compound property on instance node now so we know that this instance is being compounded
|
|
1595
|
+
node.__ngt_renderer__[4 /* NgtRendererClassId.compound */] = [value === '' || value === 'first', {}];
|
|
1596
|
+
return;
|
|
1597
|
+
}
|
|
1598
|
+
if (name === SPECIAL_PROPERTIES.ATTACH) {
|
|
1599
|
+
// handle attach as tring
|
|
1600
|
+
const paths = value.split('.');
|
|
1601
|
+
if (paths.length)
|
|
1602
|
+
getLocalState(node).attach = paths;
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
if (name === SPECIAL_PROPERTIES.VALUE) {
|
|
1606
|
+
// TODO the last time we tried this here, this didn't work
|
|
1607
|
+
// coercion
|
|
1608
|
+
let maybeCoerced = value;
|
|
1609
|
+
if (maybeCoerced === '' || maybeCoerced === 'true' || maybeCoerced === 'false') {
|
|
1610
|
+
maybeCoerced = maybeCoerced === 'true' || maybeCoerced === '';
|
|
1638
1611
|
}
|
|
1639
|
-
|
|
1612
|
+
else if (!isNaN(Number(maybeCoerced))) {
|
|
1613
|
+
maybeCoerced = Number(maybeCoerced);
|
|
1614
|
+
}
|
|
1615
|
+
node.__ngt_renderer__[10 /* NgtRendererClassId.rawValue */] = maybeCoerced;
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
applyProps(node, { [name]: value });
|
|
1640
1619
|
}
|
|
1641
|
-
|
|
1642
|
-
|
|
1620
|
+
applyProperty(node, name, value) {
|
|
1621
|
+
if (node.__ngt_renderer__[3 /* NgtRendererClassId.destroyed */])
|
|
1622
|
+
return;
|
|
1623
|
+
// setup [ref] here
|
|
1624
|
+
if (name === SPECIAL_PROPERTIES.REF && is.ref(value)) {
|
|
1625
|
+
node.__ngt_renderer__[11 /* NgtRendererClassId.ref */] = value;
|
|
1626
|
+
value.nativeElement = node;
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1629
|
+
const parent = getLocalState(node).parent || node.__ngt_renderer__[1 /* NgtRendererClassId.parent */];
|
|
1630
|
+
// rawValue
|
|
1631
|
+
if (getLocalState(node).isRaw && name === SPECIAL_PROPERTIES.VALUE) {
|
|
1632
|
+
node.__ngt_renderer__[10 /* NgtRendererClassId.rawValue */] = value;
|
|
1633
|
+
attachThreeChild(parent, node);
|
|
1634
|
+
return;
|
|
1635
|
+
}
|
|
1636
|
+
// attach
|
|
1637
|
+
if (name === SPECIAL_PROPERTIES.ATTACH) {
|
|
1638
|
+
getLocalState(node).attach = Array.isArray(value) ? value.map((v) => v.toString()) : value;
|
|
1639
|
+
attachThreeChild(parent, node);
|
|
1640
|
+
return;
|
|
1641
|
+
}
|
|
1642
|
+
const compound = node.__ngt_renderer__[4 /* NgtRendererClassId.compound */];
|
|
1643
|
+
if (compound?.[1 /* NgtCompoundClassId.props */] &&
|
|
1644
|
+
name in compound[1 /* NgtCompoundClassId.props */] &&
|
|
1645
|
+
!compound[0 /* NgtCompoundClassId.applyFirst */]) {
|
|
1646
|
+
value = compound[1 /* NgtCompoundClassId.props */][name];
|
|
1647
|
+
}
|
|
1648
|
+
applyProps(node, { [name]: value });
|
|
1643
1649
|
}
|
|
1644
|
-
|
|
1645
|
-
this.
|
|
1646
|
-
this.write({ skipWrapperExplicit: true });
|
|
1650
|
+
isCompound(name) {
|
|
1651
|
+
return this.root.compoundPrefixes.some((prefix) => name.startsWith(prefix));
|
|
1647
1652
|
}
|
|
1648
|
-
|
|
1649
|
-
this.
|
|
1650
|
-
this.write({ skipInitExplicit: true });
|
|
1653
|
+
get rootScene() {
|
|
1654
|
+
return this.root.store.get('scene');
|
|
1651
1655
|
}
|
|
1652
|
-
|
|
1653
|
-
this.
|
|
1654
|
-
this.write({ noAttachExplicit: true });
|
|
1656
|
+
get rootCdr() {
|
|
1657
|
+
return this.root.cdr;
|
|
1655
1658
|
}
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
: [value];
|
|
1663
|
-
this.write({ attach, attachExplicit: true });
|
|
1659
|
+
getClosestParentWithInstance(node) {
|
|
1660
|
+
let parent = node.__ngt_renderer__[1 /* NgtRendererClassId.parent */];
|
|
1661
|
+
while (parent && parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] !== 'three') {
|
|
1662
|
+
parent = parent.__ngt_renderer__[12 /* NgtRendererClassId.portalContainer */]
|
|
1663
|
+
? parent.__ngt_renderer__[12 /* NgtRendererClassId.portalContainer */]
|
|
1664
|
+
: parent.__ngt_renderer__[1 /* NgtRendererClassId.parent */];
|
|
1664
1665
|
}
|
|
1666
|
+
return parent;
|
|
1665
1667
|
}
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1668
|
+
getClosestParentWithCompound(node) {
|
|
1669
|
+
if (node.__ngt_renderer__[5 /* NgtRendererClassId.compoundParent */]) {
|
|
1670
|
+
return node.__ngt_renderer__[5 /* NgtRendererClassId.compoundParent */];
|
|
1671
|
+
}
|
|
1672
|
+
let parent = node.__ngt_renderer__[1 /* NgtRendererClassId.parent */];
|
|
1673
|
+
if (parent &&
|
|
1674
|
+
parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'compound' &&
|
|
1675
|
+
!parent.__ngt_renderer__[6 /* NgtRendererClassId.compounded */]) {
|
|
1676
|
+
return parent;
|
|
1677
|
+
}
|
|
1678
|
+
while (parent &&
|
|
1679
|
+
(parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three' ||
|
|
1680
|
+
!parent.__ngt_renderer__[5 /* NgtRendererClassId.compoundParent */] ||
|
|
1681
|
+
parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] !== 'compound')) {
|
|
1682
|
+
parent = parent.__ngt_renderer__[1 /* NgtRendererClassId.parent */];
|
|
1683
|
+
}
|
|
1684
|
+
if (!parent)
|
|
1685
|
+
return;
|
|
1686
|
+
if (parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three' &&
|
|
1687
|
+
parent.__ngt_renderer__[5 /* NgtRendererClassId.compoundParent */]) {
|
|
1688
|
+
return parent.__ngt_renderer__[5 /* NgtRendererClassId.compoundParent */];
|
|
1689
|
+
}
|
|
1690
|
+
if (!parent.__ngt_renderer__[6 /* NgtRendererClassId.compounded */]) {
|
|
1691
|
+
return parent;
|
|
1692
|
+
}
|
|
1693
|
+
return null;
|
|
1678
1694
|
}
|
|
1679
|
-
|
|
1680
|
-
this.
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
});
|
|
1684
|
-
});
|
|
1695
|
+
getCreationState() {
|
|
1696
|
+
const injectedArgs = this.firstNonInjectedDirective(NgtArgs)?.args || [];
|
|
1697
|
+
const store = this.tryGetPortalStore();
|
|
1698
|
+
return { injectedArgs, store };
|
|
1685
1699
|
}
|
|
1686
|
-
|
|
1687
|
-
|
|
1700
|
+
destroy(node, parent) {
|
|
1701
|
+
const state = node.__ngt_renderer__;
|
|
1702
|
+
if (state[3 /* NgtRendererClassId.destroyed */])
|
|
1703
|
+
return;
|
|
1704
|
+
if (state[0 /* NgtRendererClassId.type */] === 'three') {
|
|
1705
|
+
state[4 /* NgtRendererClassId.compound */] = undefined;
|
|
1706
|
+
state[5 /* NgtRendererClassId.compoundParent */] = undefined;
|
|
1707
|
+
const localState = getLocalState(node);
|
|
1708
|
+
if (localState.objects) {
|
|
1709
|
+
localState.objects.value.forEach((obj) => this.destroy(obj, parent));
|
|
1710
|
+
localState.objects.complete();
|
|
1711
|
+
}
|
|
1712
|
+
if (localState.nonObjects) {
|
|
1713
|
+
localState.nonObjects.value.forEach((obj) => this.destroy(obj, parent));
|
|
1714
|
+
localState.nonObjects.complete();
|
|
1715
|
+
}
|
|
1716
|
+
if (localState.afterUpdate)
|
|
1717
|
+
localState.afterUpdate.complete();
|
|
1718
|
+
if (localState.afterAttach)
|
|
1719
|
+
localState.afterAttach.complete();
|
|
1720
|
+
delete localState['objects'];
|
|
1721
|
+
delete localState['nonObjects'];
|
|
1722
|
+
delete localState['add'];
|
|
1723
|
+
delete localState['remove'];
|
|
1724
|
+
delete localState['afterUpdate'];
|
|
1725
|
+
delete localState['afterAttach'];
|
|
1726
|
+
delete localState['store'];
|
|
1727
|
+
delete localState['handlers'];
|
|
1728
|
+
if (!localState.primitive) {
|
|
1729
|
+
delete node['__ngt__'];
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
if (state[0 /* NgtRendererClassId.type */] === 'comment') {
|
|
1733
|
+
state[13 /* NgtRendererClassId.injectorFactory */] = null;
|
|
1734
|
+
delete node['__ngt_renderer_add_comment__'];
|
|
1735
|
+
const index = this.comments.findIndex((comment) => comment === node);
|
|
1736
|
+
if (index > -1) {
|
|
1737
|
+
this.comments.splice(index, 1);
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
if (state[0 /* NgtRendererClassId.type */] === 'portal') {
|
|
1741
|
+
state[13 /* NgtRendererClassId.injectorFactory */] = null;
|
|
1742
|
+
const index = this.portals.findIndex((portal) => portal === node);
|
|
1743
|
+
if (index > -1) {
|
|
1744
|
+
this.portals.splice(index, 1);
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
if (state[0 /* NgtRendererClassId.type */] === 'compound') {
|
|
1748
|
+
state[6 /* NgtRendererClassId.compounded */] = undefined;
|
|
1749
|
+
state[8 /* NgtRendererClassId.attributes */] = null;
|
|
1750
|
+
state[9 /* NgtRendererClassId.properties */] = null;
|
|
1751
|
+
this.executeOperation(node, 'cleanUp');
|
|
1752
|
+
state[7 /* NgtRendererClassId.queueOps */].clear();
|
|
1753
|
+
state[7 /* NgtRendererClassId.queueOps */] = null;
|
|
1754
|
+
}
|
|
1755
|
+
if (state[11 /* NgtRendererClassId.ref */]) {
|
|
1756
|
+
// nullify ref
|
|
1757
|
+
state[11 /* NgtRendererClassId.ref */].nativeElement = null;
|
|
1758
|
+
state[11 /* NgtRendererClassId.ref */] = undefined;
|
|
1759
|
+
}
|
|
1760
|
+
// nullify parent
|
|
1761
|
+
state[1 /* NgtRendererClassId.parent */] = null;
|
|
1762
|
+
for (const renderChild of state[2 /* NgtRendererClassId.children */] || []) {
|
|
1763
|
+
if (renderChild.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three' && parent) {
|
|
1764
|
+
removeThreeChild(parent, renderChild, true);
|
|
1765
|
+
}
|
|
1766
|
+
this.destroy(renderChild, parent);
|
|
1767
|
+
}
|
|
1768
|
+
state[2 /* NgtRendererClassId.children */] = [];
|
|
1769
|
+
state[3 /* NgtRendererClassId.destroyed */] = true;
|
|
1770
|
+
if (parent) {
|
|
1771
|
+
this.removeChild(parent, node);
|
|
1772
|
+
}
|
|
1688
1773
|
}
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1774
|
+
firstNonInjectedDirective(dir) {
|
|
1775
|
+
let directive;
|
|
1776
|
+
let i = this.comments.length - 1;
|
|
1777
|
+
while (i >= 0) {
|
|
1778
|
+
const comment = this.comments[i];
|
|
1779
|
+
if (comment.__ngt_renderer__[3 /* NgtRendererClassId.destroyed */]) {
|
|
1780
|
+
i--;
|
|
1781
|
+
continue;
|
|
1782
|
+
}
|
|
1783
|
+
const injector = comment.__ngt_renderer__[13 /* NgtRendererClassId.injectorFactory */]();
|
|
1784
|
+
if (!injector) {
|
|
1785
|
+
i--;
|
|
1786
|
+
continue;
|
|
1787
|
+
}
|
|
1788
|
+
const instance = injector.get(dir, null);
|
|
1789
|
+
if (instance && instance.validate()) {
|
|
1790
|
+
directive = instance;
|
|
1791
|
+
break;
|
|
1792
|
+
}
|
|
1793
|
+
i--;
|
|
1794
|
+
}
|
|
1795
|
+
return directive;
|
|
1796
|
+
}
|
|
1797
|
+
tryGetPortalStore() {
|
|
1798
|
+
let store;
|
|
1799
|
+
// we only care about the portal states because NgtStore only differs per Portal
|
|
1800
|
+
let i = this.portals.length - 1;
|
|
1801
|
+
while (i >= 0) {
|
|
1802
|
+
// loop through the portal state backwards to find the closest NgtStore
|
|
1803
|
+
const injector = this.portals[i].__ngt_renderer__[13 /* NgtRendererClassId.injectorFactory */]();
|
|
1804
|
+
if (!injector) {
|
|
1805
|
+
i--;
|
|
1806
|
+
continue;
|
|
1807
|
+
}
|
|
1808
|
+
const instance = injector.get(NgtStore, null);
|
|
1809
|
+
if (instance) {
|
|
1810
|
+
store = instance;
|
|
1811
|
+
break;
|
|
1812
|
+
}
|
|
1813
|
+
i--;
|
|
1814
|
+
}
|
|
1815
|
+
return store || this.root.store;
|
|
1693
1816
|
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
class NgtRendererFactory {
|
|
1820
|
+
constructor() {
|
|
1821
|
+
this.domRendererFactory = inject(ɵDomRendererFactory2);
|
|
1822
|
+
this.cdr = inject(ChangeDetectorRef);
|
|
1823
|
+
this.store = inject(NgtStore);
|
|
1824
|
+
this.catalogue = inject(NGT_CATALOGUE);
|
|
1825
|
+
this.compoundPrefixes = inject(NGT_COMPOUND_PREFIXES);
|
|
1826
|
+
this.rendererStore = new NgtRendererStore({
|
|
1827
|
+
store: this.store,
|
|
1828
|
+
cdr: this.cdr,
|
|
1829
|
+
compoundPrefixes: this.compoundPrefixes,
|
|
1830
|
+
});
|
|
1696
1831
|
}
|
|
1697
|
-
|
|
1698
|
-
return
|
|
1832
|
+
createRenderer(hostElement, type) {
|
|
1833
|
+
// TODO we might need to check on "type" to return DomRenderer for that particular type to support HTML
|
|
1834
|
+
if (!this.renderer) {
|
|
1835
|
+
const domRenderer = this.domRendererFactory.createRenderer(hostElement, type);
|
|
1836
|
+
this.renderer = new NgtRenderer(domRenderer, this.rendererStore, this.catalogue);
|
|
1837
|
+
}
|
|
1838
|
+
return this.renderer;
|
|
1699
1839
|
}
|
|
1700
|
-
|
|
1701
|
-
|
|
1840
|
+
}
|
|
1841
|
+
NgtRendererFactory.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRendererFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1842
|
+
NgtRendererFactory.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRendererFactory });
|
|
1843
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRendererFactory, decorators: [{
|
|
1844
|
+
type: Injectable
|
|
1845
|
+
}] });
|
|
1846
|
+
class NgtRenderer {
|
|
1847
|
+
constructor(domRenderer, store, catalogue) {
|
|
1848
|
+
this.domRenderer = domRenderer;
|
|
1849
|
+
this.store = store;
|
|
1850
|
+
this.catalogue = catalogue;
|
|
1851
|
+
this.first = false;
|
|
1852
|
+
this.createText = this.domRenderer.createText.bind(this.domRenderer);
|
|
1853
|
+
this.destroy = this.domRenderer.destroy.bind(this.domRenderer);
|
|
1854
|
+
this.destroyNode = null;
|
|
1855
|
+
this.selectRootElement = this.domRenderer.selectRootElement.bind(this.domRenderer);
|
|
1856
|
+
this.nextSibling = this.domRenderer.nextSibling.bind(this.domRenderer);
|
|
1857
|
+
this.removeAttribute = this.domRenderer.removeAttribute.bind(this.domRenderer);
|
|
1858
|
+
this.addClass = this.domRenderer.addClass.bind(this.domRenderer);
|
|
1859
|
+
this.removeClass = this.domRenderer.removeClass.bind(this.domRenderer);
|
|
1860
|
+
this.setStyle = this.domRenderer.setStyle.bind(this.domRenderer);
|
|
1861
|
+
this.removeStyle = this.domRenderer.removeStyle.bind(this.domRenderer);
|
|
1862
|
+
this.setValue = this.domRenderer.setValue.bind(this.domRenderer);
|
|
1863
|
+
}
|
|
1864
|
+
createElement(name, namespace) {
|
|
1865
|
+
const element = this.domRenderer.createElement(name, namespace);
|
|
1866
|
+
// on first pass, we return the Root Scene as the root node
|
|
1867
|
+
if (!this.first) {
|
|
1868
|
+
this.first = true;
|
|
1869
|
+
return this.store.createNode('three', this.store.rootScene);
|
|
1870
|
+
}
|
|
1871
|
+
// handle compound
|
|
1872
|
+
if (this.store.isCompound(name))
|
|
1873
|
+
return this.store.createNode('compound', element);
|
|
1874
|
+
// handle portal
|
|
1875
|
+
if (name === SPECIAL_DOM_TAG.NGT_PORTAL) {
|
|
1876
|
+
return this.store.createNode('portal', element);
|
|
1877
|
+
}
|
|
1878
|
+
// handle raw value
|
|
1879
|
+
if (name === SPECIAL_DOM_TAG.NGT_VALUE) {
|
|
1880
|
+
return this.store.createNode('three', Object.assign({ __ngt_renderer__: { rawValue: undefined } }, { __ngt__: { isRaw: true } }));
|
|
1881
|
+
}
|
|
1882
|
+
const { injectedArgs, store } = this.store.getCreationState();
|
|
1883
|
+
// handle primitive
|
|
1884
|
+
if (name === SPECIAL_DOM_TAG.NGT_PRIMITIVE) {
|
|
1885
|
+
if (!injectedArgs[0])
|
|
1886
|
+
throw new Error(`[NGT] ngt-primitive without args is invalid`);
|
|
1887
|
+
const object = injectedArgs[0];
|
|
1888
|
+
let localState = getLocalState(object);
|
|
1889
|
+
if (!Object.keys(localState).length) {
|
|
1890
|
+
prepare(object, { store, args: injectedArgs, primitive: true });
|
|
1891
|
+
localState = getLocalState(object);
|
|
1892
|
+
}
|
|
1893
|
+
if (!localState.store)
|
|
1894
|
+
localState.store = store;
|
|
1895
|
+
return this.store.createNode('three', object);
|
|
1896
|
+
}
|
|
1897
|
+
const threeTag = name.startsWith('ngt') ? name.slice(4) : name;
|
|
1898
|
+
const threeName = kebabToPascal(threeTag);
|
|
1899
|
+
const threeTarget = this.catalogue[threeName];
|
|
1900
|
+
// we have the THREE constructor here, handle it
|
|
1901
|
+
if (threeTarget) {
|
|
1902
|
+
const instance = prepare(new threeTarget(...injectedArgs), { store, args: injectedArgs });
|
|
1903
|
+
const node = this.store.createNode('three', instance);
|
|
1904
|
+
const localState = getLocalState(instance);
|
|
1905
|
+
if (is.geometry(instance)) {
|
|
1906
|
+
localState.attach = ['geometry'];
|
|
1907
|
+
}
|
|
1908
|
+
else if (is.material(instance)) {
|
|
1909
|
+
localState.attach = ['material'];
|
|
1910
|
+
}
|
|
1911
|
+
return node;
|
|
1912
|
+
}
|
|
1913
|
+
return this.store.createNode('dom', element);
|
|
1702
1914
|
}
|
|
1703
|
-
|
|
1704
|
-
this.
|
|
1705
|
-
|
|
1706
|
-
});
|
|
1707
|
-
super.ngOnDestroy();
|
|
1915
|
+
createComment(value) {
|
|
1916
|
+
const comment = this.domRenderer.createComment(value);
|
|
1917
|
+
return this.store.createNode('comment', comment);
|
|
1708
1918
|
}
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1919
|
+
appendChild(parent, newChild) {
|
|
1920
|
+
// TODO: just ignore text node for now
|
|
1921
|
+
if (newChild instanceof Text)
|
|
1922
|
+
return;
|
|
1923
|
+
if (newChild.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'comment') {
|
|
1924
|
+
this.store.setParent(newChild, parent);
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1927
|
+
this.store.setParent(newChild, parent);
|
|
1928
|
+
this.store.addChild(parent, newChild);
|
|
1929
|
+
// if new chlid is a portal
|
|
1930
|
+
if (newChild.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'portal') {
|
|
1931
|
+
this.store.processPortalContainer(newChild);
|
|
1932
|
+
if (newChild.__ngt_renderer__[12 /* NgtRendererClassId.portalContainer */]) {
|
|
1933
|
+
this.appendChild(parent, newChild.__ngt_renderer__[12 /* NgtRendererClassId.portalContainer */]);
|
|
1934
|
+
}
|
|
1935
|
+
return;
|
|
1936
|
+
}
|
|
1937
|
+
// if parent is a portal
|
|
1938
|
+
if (parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'portal') {
|
|
1939
|
+
this.store.processPortalContainer(parent);
|
|
1940
|
+
if (parent.__ngt_renderer__[12 /* NgtRendererClassId.portalContainer */]) {
|
|
1941
|
+
this.appendChild(parent.__ngt_renderer__[12 /* NgtRendererClassId.portalContainer */], newChild);
|
|
1942
|
+
}
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
// if both are three instances, straightforward case
|
|
1946
|
+
if (parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three' &&
|
|
1947
|
+
newChild.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three') {
|
|
1948
|
+
attachThreeChild(parent, newChild);
|
|
1949
|
+
// here, we handle the special case of if the parent has a compoundParent, which means this child is part of a compound parent template
|
|
1950
|
+
if (!newChild.__ngt_renderer__[4 /* NgtRendererClassId.compound */])
|
|
1951
|
+
return;
|
|
1952
|
+
const closestGrandparentWithCompound = this.store.getClosestParentWithCompound(parent);
|
|
1953
|
+
if (!closestGrandparentWithCompound)
|
|
1954
|
+
return;
|
|
1955
|
+
this.appendChild(closestGrandparentWithCompound, newChild);
|
|
1956
|
+
return;
|
|
1957
|
+
}
|
|
1958
|
+
// if only the parent is the THREE instance
|
|
1959
|
+
if (parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three') {
|
|
1960
|
+
if (newChild.__ngt_renderer__[2 /* NgtRendererClassId.children */].length) {
|
|
1961
|
+
for (const renderChild of newChild.__ngt_renderer__[2 /* NgtRendererClassId.children */]) {
|
|
1962
|
+
this.appendChild(parent, renderChild);
|
|
1720
1963
|
}
|
|
1721
1964
|
}
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
if (this.__ngt__.parentRef && this.__ngt__.parentRef.value) {
|
|
1737
|
-
invalidateInstance(this.__ngt__.parentRef.value);
|
|
1738
|
-
}
|
|
1965
|
+
}
|
|
1966
|
+
// if parent is a compound
|
|
1967
|
+
if (parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'compound') {
|
|
1968
|
+
// if compound doesn't have a THREE instance set yet
|
|
1969
|
+
if (!parent.__ngt_renderer__[6 /* NgtRendererClassId.compounded */] &&
|
|
1970
|
+
newChild.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three') {
|
|
1971
|
+
// if child is indeed an ngtCompound
|
|
1972
|
+
if (newChild.__ngt_renderer__[4 /* NgtRendererClassId.compound */]) {
|
|
1973
|
+
this.store.setCompound(parent, newChild);
|
|
1974
|
+
}
|
|
1975
|
+
else {
|
|
1976
|
+
// if not, we track the parent (that is supposedly the compound component) on this three instance
|
|
1977
|
+
if (!newChild.__ngt_renderer__[5 /* NgtRendererClassId.compoundParent */]) {
|
|
1978
|
+
newChild.__ngt_renderer__[5 /* NgtRendererClassId.compoundParent */] = parent;
|
|
1739
1979
|
}
|
|
1740
1980
|
}
|
|
1741
1981
|
}
|
|
1742
|
-
|
|
1743
|
-
if (
|
|
1744
|
-
|
|
1982
|
+
// reset the compound if it's changed
|
|
1983
|
+
if (parent.__ngt_renderer__[6 /* NgtRendererClassId.compounded */] &&
|
|
1984
|
+
newChild.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three' &&
|
|
1985
|
+
newChild.__ngt_renderer__[4 /* NgtRendererClassId.compound */] &&
|
|
1986
|
+
parent.__ngt_renderer__[6 /* NgtRendererClassId.compounded */] !== newChild) {
|
|
1987
|
+
this.store.setCompound(parent, newChild);
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
if (newChild.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three' && !getLocalState(newChild).parent) {
|
|
1991
|
+
// we'll try to get the grandparent instance here so that we can run appendChild with both instances
|
|
1992
|
+
const closestGrandparentInstance = this.store.getClosestParentWithInstance(parent);
|
|
1993
|
+
if (closestGrandparentInstance) {
|
|
1994
|
+
this.appendChild(closestGrandparentInstance, newChild);
|
|
1995
|
+
}
|
|
1996
|
+
return;
|
|
1997
|
+
}
|
|
1998
|
+
if (parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'dom' &&
|
|
1999
|
+
newChild.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'dom') {
|
|
2000
|
+
const closestGrandparentInstance = this.store.getClosestParentWithInstance(parent);
|
|
2001
|
+
if (closestGrandparentInstance) {
|
|
2002
|
+
this.appendChild(closestGrandparentInstance, newChild);
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
insertBefore(parent, newChild
|
|
2007
|
+
// TODO we might need these?
|
|
2008
|
+
// refChild: NgtRendererNode,
|
|
2009
|
+
// isMove?: boolean | undefined
|
|
2010
|
+
) {
|
|
2011
|
+
if (!parent.__ngt_renderer__)
|
|
2012
|
+
return;
|
|
2013
|
+
this.appendChild(parent, newChild);
|
|
2014
|
+
}
|
|
2015
|
+
removeChild(parent, oldChild, isHostElement) {
|
|
2016
|
+
if (parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three' &&
|
|
2017
|
+
oldChild.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three') {
|
|
2018
|
+
removeThreeChild(parent, oldChild, true);
|
|
2019
|
+
this.store.destroy(oldChild, parent);
|
|
2020
|
+
return;
|
|
2021
|
+
}
|
|
2022
|
+
if (parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'compound' &&
|
|
2023
|
+
parent.__ngt_renderer__[1 /* NgtRendererClassId.parent */]) {
|
|
2024
|
+
this.removeChild(parent.__ngt_renderer__[1 /* NgtRendererClassId.parent */], oldChild, isHostElement);
|
|
2025
|
+
return;
|
|
2026
|
+
}
|
|
2027
|
+
if (parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three') {
|
|
2028
|
+
this.store.destroy(oldChild, parent);
|
|
2029
|
+
return;
|
|
2030
|
+
}
|
|
2031
|
+
const closestGrandparentInstance = this.store.getClosestParentWithInstance(parent);
|
|
2032
|
+
if (closestGrandparentInstance) {
|
|
2033
|
+
this.removeChild(closestGrandparentInstance, oldChild, isHostElement);
|
|
2034
|
+
}
|
|
2035
|
+
this.store.destroy(oldChild, closestGrandparentInstance);
|
|
2036
|
+
}
|
|
2037
|
+
parentNode(node) {
|
|
2038
|
+
if (node.__ngt_renderer__?.[1 /* NgtRendererClassId.parent */])
|
|
2039
|
+
return node.__ngt_renderer__[1 /* NgtRendererClassId.parent */];
|
|
2040
|
+
return this.domRenderer.parentNode(node);
|
|
2041
|
+
}
|
|
2042
|
+
setAttribute(el, name, value, namespace) {
|
|
2043
|
+
if (el.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'compound') {
|
|
2044
|
+
// we don't have the compound instance yet
|
|
2045
|
+
el.__ngt_renderer__[8 /* NgtRendererClassId.attributes */][name] = value;
|
|
2046
|
+
if (!el.__ngt_renderer__[6 /* NgtRendererClassId.compounded */]) {
|
|
2047
|
+
this.store.queueOperation(el, ['op', () => this.setAttribute(el, name, value, namespace)]);
|
|
2048
|
+
return;
|
|
2049
|
+
}
|
|
2050
|
+
this.setAttribute(el.__ngt_renderer__[6 /* NgtRendererClassId.compounded */], name, value, namespace);
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
2053
|
+
if (el.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three') {
|
|
2054
|
+
this.store.applyAttribute(el, name, value);
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
setProperty(el, name, value) {
|
|
2058
|
+
if (el.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'compound') {
|
|
2059
|
+
// we don't have the compound instance yet
|
|
2060
|
+
el.__ngt_renderer__[9 /* NgtRendererClassId.properties */][name] = value;
|
|
2061
|
+
if (!el.__ngt_renderer__[6 /* NgtRendererClassId.compounded */]) {
|
|
2062
|
+
this.store.queueOperation(el, ['op', () => this.setProperty(el, name, value)]);
|
|
2063
|
+
return;
|
|
2064
|
+
}
|
|
2065
|
+
if (el.__ngt_renderer__[6 /* NgtRendererClassId.compounded */].__ngt_renderer__[4 /* NgtRendererClassId.compound */]) {
|
|
2066
|
+
Object.assign(el.__ngt_renderer__[6 /* NgtRendererClassId.compounded */].__ngt_renderer__[4 /* NgtRendererClassId.compound */], {
|
|
2067
|
+
props: {
|
|
2068
|
+
...el.__ngt_renderer__[6 /* NgtRendererClassId.compounded */].__ngt_renderer__[4 /* NgtRendererClassId.compound */],
|
|
2069
|
+
[name]: value,
|
|
2070
|
+
},
|
|
2071
|
+
});
|
|
1745
2072
|
}
|
|
2073
|
+
this.setProperty(el.__ngt_renderer__[6 /* NgtRendererClassId.compounded */], name, value);
|
|
2074
|
+
return;
|
|
2075
|
+
}
|
|
2076
|
+
if (el.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three') {
|
|
2077
|
+
this.store.applyProperty(el, name, value);
|
|
1746
2078
|
}
|
|
1747
|
-
this.write({ attach: [] });
|
|
1748
|
-
this.instanceRef.complete();
|
|
1749
2079
|
}
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
2080
|
+
listen(target, eventName, callback) {
|
|
2081
|
+
if (target.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three' ||
|
|
2082
|
+
(target.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'compound' &&
|
|
2083
|
+
target.__ngt_renderer__[6 /* NgtRendererClassId.compounded */])) {
|
|
2084
|
+
const instance = target.__ngt_renderer__[6 /* NgtRendererClassId.compounded */] || target;
|
|
2085
|
+
const priority = getLocalState(target).priority;
|
|
2086
|
+
return processThreeEvent(instance, priority || 0, eventName, callback, this.store.rootCdr);
|
|
2087
|
+
}
|
|
2088
|
+
if (target.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'compound' &&
|
|
2089
|
+
!target.__ngt_renderer__[6 /* NgtRendererClassId.compounded */]) {
|
|
2090
|
+
this.store.queueOperation(target, [
|
|
2091
|
+
'op',
|
|
2092
|
+
() => this.store.queueOperation(target, ['cleanUp', this.listen(target, eventName, callback)]),
|
|
2093
|
+
]);
|
|
2094
|
+
}
|
|
2095
|
+
return () => { };
|
|
1757
2096
|
}
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
NgtInstance.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.0", type: NgtInstance, isStandalone: true, selector: "[ngtInstance]", inputs: { ref: "ref", skipWrapper: "skipWrapper", skipInit: "skipInit", noAttach: "noAttach", attach: "attach", priority: "priority", beforeRender: "beforeRender", readyCallback: "readyCallback", updateCallback: "updateCallback" }, outputs: { click: "click", contextmenu: "contextmenu", dblclick: "dblclick", pointerup: "pointerup", pointerdown: "pointerdown", pointerover: "pointerover", pointerout: "pointerout", pointerenter: "pointerenter", pointerleave: "pointerleave", pointermove: "pointermove", pointermissed: "pointermissed", pointercancel: "pointercancel", wheel: "wheel" }, exportAs: ["ngtInstance"], usesInheritance: true, ngImport: i0 });
|
|
1761
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtInstance, decorators: [{
|
|
1762
|
-
type: Directive,
|
|
1763
|
-
args: [{
|
|
1764
|
-
selector: '[ngtInstance]',
|
|
1765
|
-
exportAs: 'ngtInstance',
|
|
1766
|
-
standalone: true,
|
|
1767
|
-
}]
|
|
1768
|
-
}], propDecorators: { ref: [{
|
|
1769
|
-
type: Input
|
|
1770
|
-
}], skipWrapper: [{
|
|
1771
|
-
type: Input
|
|
1772
|
-
}], skipInit: [{
|
|
1773
|
-
type: Input
|
|
1774
|
-
}], noAttach: [{
|
|
1775
|
-
type: Input
|
|
1776
|
-
}], attach: [{
|
|
1777
|
-
type: Input
|
|
1778
|
-
}], priority: [{
|
|
1779
|
-
type: Input
|
|
1780
|
-
}], beforeRender: [{
|
|
1781
|
-
type: Input
|
|
1782
|
-
}], readyCallback: [{
|
|
1783
|
-
type: Input
|
|
1784
|
-
}], updateCallback: [{
|
|
1785
|
-
type: Input
|
|
1786
|
-
}], click: [{
|
|
1787
|
-
type: Output
|
|
1788
|
-
}], contextmenu: [{
|
|
1789
|
-
type: Output
|
|
1790
|
-
}], dblclick: [{
|
|
1791
|
-
type: Output
|
|
1792
|
-
}], pointerup: [{
|
|
1793
|
-
type: Output
|
|
1794
|
-
}], pointerdown: [{
|
|
1795
|
-
type: Output
|
|
1796
|
-
}], pointerover: [{
|
|
1797
|
-
type: Output
|
|
1798
|
-
}], pointerout: [{
|
|
1799
|
-
type: Output
|
|
1800
|
-
}], pointerenter: [{
|
|
1801
|
-
type: Output
|
|
1802
|
-
}], pointerleave: [{
|
|
1803
|
-
type: Output
|
|
1804
|
-
}], pointermove: [{
|
|
1805
|
-
type: Output
|
|
1806
|
-
}], pointermissed: [{
|
|
1807
|
-
type: Output
|
|
1808
|
-
}], pointercancel: [{
|
|
1809
|
-
type: Output
|
|
1810
|
-
}], wheel: [{
|
|
1811
|
-
type: Output
|
|
1812
|
-
}] } });
|
|
1813
|
-
const NGT_INSTANCE_INPUTS = [
|
|
1814
|
-
'ref',
|
|
1815
|
-
'attach',
|
|
1816
|
-
'skipWrapper',
|
|
1817
|
-
'skipInit',
|
|
1818
|
-
'noAttach',
|
|
1819
|
-
'beforeRender',
|
|
1820
|
-
'priority',
|
|
1821
|
-
'updateCallback',
|
|
1822
|
-
'readyCallback',
|
|
1823
|
-
];
|
|
1824
|
-
const NGT_INSTANCE_OUTPUTS = [...supportedEvents];
|
|
1825
|
-
|
|
1826
|
-
const defaultResizeOptions = {
|
|
1827
|
-
box: 'content-box',
|
|
1828
|
-
scroll: false,
|
|
1829
|
-
offsetSize: false,
|
|
1830
|
-
debounce: { scroll: 50, resize: 0 },
|
|
1831
|
-
};
|
|
1832
|
-
const [injectResizeOptions, provideResizeOptions] = createInjection('ngtResize Options', {
|
|
1833
|
-
defaultValueOrFactory: defaultResizeOptions,
|
|
1834
|
-
provideValueFactory: (value) => ({ ...defaultResizeOptions, ...value }),
|
|
1835
|
-
});
|
|
1836
|
-
const [injectResizeObserverSupport] = createInjection('Resize Observer API support', {
|
|
1837
|
-
defaultValueOrFactory: () => {
|
|
1838
|
-
const window = injectWindow();
|
|
1839
|
-
return 'ResizeObserver' in window && window['ResizeObserver'] != null;
|
|
1840
|
-
},
|
|
1841
|
-
});
|
|
1842
|
-
|
|
1843
|
-
class NgtResize extends Observable {
|
|
1844
|
-
constructor() {
|
|
1845
|
-
const { nativeElement } = inject(ElementRef);
|
|
1846
|
-
const zone = inject(NgZone);
|
|
1847
|
-
const document = inject(DOCUMENT);
|
|
1848
|
-
const window = injectWindow();
|
|
1849
|
-
const isSupport = injectResizeObserverSupport();
|
|
1850
|
-
const { box, offsetSize, scroll, debounce } = injectResizeOptions();
|
|
1851
|
-
let observer;
|
|
1852
|
-
let lastBounds;
|
|
1853
|
-
let lastEntries = [];
|
|
1854
|
-
const torndown$ = new Subject();
|
|
1855
|
-
const scrollContainers = findScrollContainers(nativeElement, document.body);
|
|
1856
|
-
// set actual debounce values early, so effects know if they should react accordingly
|
|
1857
|
-
const scrollDebounce = debounce ? (typeof debounce === 'number' ? debounce : debounce.scroll) : null;
|
|
1858
|
-
const resizeDebounce = debounce ? (typeof debounce === 'number' ? debounce : debounce.resize) : null;
|
|
1859
|
-
const debounceAndDestroy = (debounce) => {
|
|
1860
|
-
return pipe(debounceTime(debounce ?? 0), takeUntil(torndown$));
|
|
1861
|
-
};
|
|
1862
|
-
super((subscriber) => {
|
|
1863
|
-
if (!isSupport) {
|
|
1864
|
-
subscriber.error('ResizeObserver is not supported in your browser. Please use a polyfill');
|
|
1865
|
-
return;
|
|
1866
|
-
}
|
|
1867
|
-
zone.runOutsideAngular(() => {
|
|
1868
|
-
const callback = (entries) => {
|
|
1869
|
-
lastEntries = entries;
|
|
1870
|
-
const { left, top, width, height, bottom, right, x, y } = nativeElement.getBoundingClientRect();
|
|
1871
|
-
const size = {
|
|
1872
|
-
left,
|
|
1873
|
-
top,
|
|
1874
|
-
width,
|
|
1875
|
-
height,
|
|
1876
|
-
bottom,
|
|
1877
|
-
right,
|
|
1878
|
-
x,
|
|
1879
|
-
y,
|
|
1880
|
-
};
|
|
1881
|
-
if (nativeElement instanceof HTMLElement && offsetSize) {
|
|
1882
|
-
size.height = nativeElement.offsetHeight;
|
|
1883
|
-
size.width = nativeElement.offsetWidth;
|
|
1884
|
-
}
|
|
1885
|
-
Object.freeze(size);
|
|
1886
|
-
subscriber.next({
|
|
1887
|
-
entries,
|
|
1888
|
-
dpr: window.devicePixelRatio,
|
|
1889
|
-
...size,
|
|
1890
|
-
});
|
|
1891
|
-
if (!areBoundsEqual(lastBounds || {}, size)) {
|
|
1892
|
-
lastBounds = size;
|
|
1893
|
-
}
|
|
1894
|
-
};
|
|
1895
|
-
const boundEntriesCallback = () => {
|
|
1896
|
-
callback(lastEntries);
|
|
1897
|
-
};
|
|
1898
|
-
observer = new ResizeObserver(callback);
|
|
1899
|
-
observer.observe(nativeElement, { box });
|
|
1900
|
-
if (scroll) {
|
|
1901
|
-
if (scrollContainers) {
|
|
1902
|
-
scrollContainers.forEach((scrollContainer) => {
|
|
1903
|
-
fromEvent(scrollContainer, 'scroll', {
|
|
1904
|
-
capture: true,
|
|
1905
|
-
passive: true,
|
|
1906
|
-
})
|
|
1907
|
-
.pipe(debounceAndDestroy(scrollDebounce))
|
|
1908
|
-
.subscribe(boundEntriesCallback);
|
|
1909
|
-
});
|
|
1910
|
-
}
|
|
1911
|
-
fromEvent(window, 'scroll', {
|
|
1912
|
-
capture: true,
|
|
1913
|
-
passive: true,
|
|
1914
|
-
})
|
|
1915
|
-
.pipe(debounceAndDestroy(scrollDebounce))
|
|
1916
|
-
.subscribe(boundEntriesCallback);
|
|
1917
|
-
}
|
|
1918
|
-
fromEvent(window, 'resize').pipe(debounceAndDestroy(resizeDebounce)).subscribe(boundEntriesCallback);
|
|
1919
|
-
});
|
|
1920
|
-
return () => {
|
|
1921
|
-
if (observer) {
|
|
1922
|
-
observer.unobserve(nativeElement);
|
|
1923
|
-
observer.disconnect();
|
|
1924
|
-
}
|
|
1925
|
-
torndown$.next();
|
|
1926
|
-
torndown$.complete();
|
|
1927
|
-
};
|
|
1928
|
-
});
|
|
1929
|
-
return this.pipe(debounceTime(scrollDebounce || 0), share({
|
|
1930
|
-
connector: () => new ReplaySubject(1),
|
|
1931
|
-
resetOnRefCountZero: true,
|
|
1932
|
-
resetOnComplete: true,
|
|
1933
|
-
}));
|
|
2097
|
+
get data() {
|
|
2098
|
+
return this.domRenderer.data;
|
|
1934
2099
|
}
|
|
1935
2100
|
}
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
2101
|
+
|
|
2102
|
+
function provideNgtRenderer({ store, changeDetectorRef, compoundPrefixes = [] }) {
|
|
2103
|
+
if (!compoundPrefixes.includes('ngts')) {
|
|
2104
|
+
compoundPrefixes.push('ngts');
|
|
2105
|
+
}
|
|
2106
|
+
if (!compoundPrefixes.includes('ngtp')) {
|
|
2107
|
+
compoundPrefixes.push('ngtp');
|
|
2108
|
+
}
|
|
2109
|
+
return [
|
|
2110
|
+
{ provide: RendererFactory2, useClass: NgtRendererFactory },
|
|
2111
|
+
{ provide: NgtStore, useValue: store },
|
|
2112
|
+
{ provide: ChangeDetectorRef, useValue: changeDetectorRef },
|
|
2113
|
+
{ provide: NGT_COMPOUND_PREFIXES, useValue: compoundPrefixes },
|
|
2114
|
+
];
|
|
1950
2115
|
}
|
|
1951
|
-
// Checks if element boundaries are equal
|
|
1952
|
-
const keys = [
|
|
1953
|
-
'x',
|
|
1954
|
-
'y',
|
|
1955
|
-
'top',
|
|
1956
|
-
'bottom',
|
|
1957
|
-
'left',
|
|
1958
|
-
'right',
|
|
1959
|
-
'width',
|
|
1960
|
-
'height',
|
|
1961
|
-
];
|
|
1962
|
-
const areBoundsEqual = (a, b) => keys.every((key) => a[key] === b[key]);
|
|
1963
2116
|
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
2117
|
+
const DOM_EVENTS = {
|
|
2118
|
+
click: false,
|
|
2119
|
+
contextmenu: false,
|
|
2120
|
+
dblclick: false,
|
|
2121
|
+
wheel: false,
|
|
2122
|
+
pointerdown: true,
|
|
2123
|
+
pointerup: true,
|
|
2124
|
+
pointerleave: true,
|
|
2125
|
+
pointermove: true,
|
|
2126
|
+
pointercancel: true,
|
|
2127
|
+
lostpointercapture: true,
|
|
2128
|
+
};
|
|
2129
|
+
const supportedEvents = [
|
|
2130
|
+
'click',
|
|
2131
|
+
'contextmenu',
|
|
2132
|
+
'dblclick',
|
|
2133
|
+
'pointerup',
|
|
2134
|
+
'pointerdown',
|
|
2135
|
+
'pointerover',
|
|
2136
|
+
'pointerout',
|
|
2137
|
+
'pointerenter',
|
|
2138
|
+
'pointerleave',
|
|
2139
|
+
'pointermove',
|
|
2140
|
+
'pointermissed',
|
|
2141
|
+
'pointercancel',
|
|
2142
|
+
'wheel',
|
|
2143
|
+
];
|
|
2144
|
+
function createPointerEvents(store) {
|
|
2145
|
+
const { handlePointer } = createEvents(store);
|
|
2146
|
+
return {
|
|
2147
|
+
priority: 1,
|
|
2148
|
+
enabled: true,
|
|
2149
|
+
compute: (event, root) => {
|
|
2150
|
+
const state = root.get();
|
|
2151
|
+
// https://github.com/pmndrs/react-three-fiber/pull/782
|
|
2152
|
+
// Events trigger outside of canvas when moved, use offsetX/Y by default and allow overrides
|
|
2153
|
+
state.pointer.set((event.offsetX / state.size.width) * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
2154
|
+
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
2155
|
+
},
|
|
2156
|
+
connected: undefined,
|
|
2157
|
+
handlers: Object.keys(DOM_EVENTS).reduce((handlers, supportedEventName) => {
|
|
2158
|
+
handlers[supportedEventName] = handlePointer(supportedEventName);
|
|
2159
|
+
return handlers;
|
|
2160
|
+
}, {}),
|
|
2161
|
+
connect: (target) => {
|
|
2162
|
+
const state = store.get();
|
|
2163
|
+
state.events.disconnect?.();
|
|
2164
|
+
state.setEvents({ connected: target });
|
|
2165
|
+
Object.entries(state.events.handlers ?? {}).forEach(([eventName, eventHandler]) => {
|
|
2166
|
+
const passive = DOM_EVENTS[eventName];
|
|
2167
|
+
target.addEventListener(eventName, eventHandler, { passive });
|
|
2168
|
+
});
|
|
2169
|
+
},
|
|
2170
|
+
disconnect: () => {
|
|
2171
|
+
const { events, setEvents } = store.get();
|
|
2172
|
+
if (events.connected) {
|
|
2173
|
+
Object.entries(events.handlers ?? {}).forEach(([eventName, eventHandler]) => {
|
|
2174
|
+
if (events.connected instanceof HTMLElement) {
|
|
2175
|
+
events.connected.removeEventListener(eventName, eventHandler);
|
|
2176
|
+
}
|
|
2177
|
+
});
|
|
2178
|
+
setEvents({ connected: undefined });
|
|
1973
2179
|
}
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
return data;
|
|
2180
|
+
},
|
|
2181
|
+
};
|
|
1977
2182
|
}
|
|
1978
2183
|
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
const
|
|
1985
|
-
const loader = new loadConstructor();
|
|
2184
|
+
const cached = new Map();
|
|
2185
|
+
function injectLoader(loaderConstructorFactory, input, extensions, onProgress) {
|
|
2186
|
+
const urls$ = isObservable(input) ? input : of(input);
|
|
2187
|
+
return urls$.pipe(map((inputs) => {
|
|
2188
|
+
const loaderConstructor = loaderConstructorFactory(inputs);
|
|
2189
|
+
const loader = new loaderConstructor();
|
|
1986
2190
|
if (extensions) {
|
|
1987
2191
|
extensions(loader);
|
|
1988
2192
|
}
|
|
1989
|
-
const
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
}
|
|
2193
|
+
const urls = Array.isArray(inputs) ? inputs : typeof inputs === 'string' ? [inputs] : Object.values(inputs);
|
|
2194
|
+
return [
|
|
2195
|
+
urls.map((url) => {
|
|
2196
|
+
if (!cached.has(url)) {
|
|
2197
|
+
cached.set(url, from(loader.loadAsync(url, onProgress)).pipe(tap((data) => {
|
|
2198
|
+
if (data.scene) {
|
|
2199
|
+
Object.assign(data, makeObjectGraph(data.scene));
|
|
2200
|
+
}
|
|
2201
|
+
}), retry(2), catchError((err) => {
|
|
2202
|
+
console.error(`[NGT] Error loading ${url}: ${err.message}`);
|
|
2203
|
+
return of([]);
|
|
2204
|
+
}), share({
|
|
2205
|
+
connector: () => new ReplaySubject(1),
|
|
2206
|
+
resetOnComplete: true,
|
|
2207
|
+
resetOnError: true,
|
|
2208
|
+
resetOnRefCountZero: true,
|
|
2209
|
+
})));
|
|
2210
|
+
}
|
|
2211
|
+
return cached.get(url);
|
|
2212
|
+
}),
|
|
2213
|
+
inputs,
|
|
2214
|
+
];
|
|
2215
|
+
}), switchMap(([observables$, inputs]) => {
|
|
2216
|
+
return forkJoin(observables$).pipe(map((results) => {
|
|
2217
|
+
if (Array.isArray(inputs))
|
|
2218
|
+
return results;
|
|
2219
|
+
if (typeof inputs === 'string')
|
|
2220
|
+
return results[0];
|
|
2221
|
+
const keys = Object.keys(inputs);
|
|
2222
|
+
return keys.reduce((result, key) => {
|
|
2223
|
+
result[key] = results[keys.indexOf(key)];
|
|
2224
|
+
return result;
|
|
2225
|
+
}, {});
|
|
2226
|
+
}));
|
|
2227
|
+
}));
|
|
2012
2228
|
}
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2229
|
+
injectLoader.destroy = () => {
|
|
2230
|
+
cached.clear();
|
|
2231
|
+
};
|
|
2232
|
+
injectLoader.preLoad = (loaderConstructorFactory, inputs, extensions) => {
|
|
2233
|
+
injectLoader(loaderConstructorFactory, inputs, extensions).pipe(take(1)).subscribe();
|
|
2234
|
+
};
|
|
2235
|
+
const injectNgtLoader = injectLoader;
|
|
2019
2236
|
|
|
2020
2237
|
class NgtCanvasContainer {
|
|
2021
2238
|
constructor() {
|
|
2022
|
-
this.
|
|
2239
|
+
this.canvasResize = injectNgxResize();
|
|
2023
2240
|
}
|
|
2024
2241
|
}
|
|
2025
|
-
NgtCanvasContainer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.
|
|
2026
|
-
NgtCanvasContainer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.
|
|
2027
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.
|
|
2242
|
+
NgtCanvasContainer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtCanvasContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2243
|
+
NgtCanvasContainer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.1.1", type: NgtCanvasContainer, isStandalone: true, selector: "ngt-canvas-container", outputs: { canvasResize: "canvasResize" }, providers: [provideNgxResizeOptions({ emitInZone: false })], ngImport: i0, template: '<ng-content />', isInline: true, styles: [":host{display:block;width:100%;height:100%}\n"] });
|
|
2244
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtCanvasContainer, decorators: [{
|
|
2028
2245
|
type: Component,
|
|
2029
|
-
args: [{ selector: 'ngt-canvas-container', standalone: true, template: '<ng-content
|
|
2030
|
-
}], propDecorators: {
|
|
2246
|
+
args: [{ selector: 'ngt-canvas-container', standalone: true, template: '<ng-content />', providers: [provideNgxResizeOptions({ emitInZone: false })], styles: [":host{display:block;width:100%;height:100%}\n"] }]
|
|
2247
|
+
}], propDecorators: { canvasResize: [{
|
|
2031
2248
|
type: Output
|
|
2032
2249
|
}] } });
|
|
2033
|
-
class NgtCanvas extends
|
|
2250
|
+
class NgtCanvas extends NgtRxStore {
|
|
2034
2251
|
constructor() {
|
|
2035
2252
|
super(...arguments);
|
|
2253
|
+
this.cdr = inject(ChangeDetectorRef);
|
|
2254
|
+
this.envInjector = inject(EnvironmentInjector);
|
|
2255
|
+
this.host = inject(ElementRef);
|
|
2256
|
+
this.store = inject(NgtStore);
|
|
2036
2257
|
this.hostClass = true;
|
|
2258
|
+
this.compoundPrefixes = [];
|
|
2037
2259
|
this.created = new EventEmitter();
|
|
2038
|
-
this.
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
this.
|
|
2260
|
+
this.pointerMissed = new EventEmitter();
|
|
2261
|
+
}
|
|
2262
|
+
initialize() {
|
|
2263
|
+
super.initialize();
|
|
2264
|
+
this.set({
|
|
2265
|
+
shadows: false,
|
|
2266
|
+
linear: false,
|
|
2267
|
+
flat: false,
|
|
2268
|
+
legacy: false,
|
|
2269
|
+
orthographic: false,
|
|
2270
|
+
frameloop: 'always',
|
|
2271
|
+
dpr: [1, 2],
|
|
2272
|
+
events: createPointerEvents,
|
|
2273
|
+
});
|
|
2043
2274
|
}
|
|
2044
2275
|
get pointerEvents() {
|
|
2045
|
-
return this.
|
|
2276
|
+
return this.get('eventSource') !== this.host.nativeElement ? 'none' : 'auto';
|
|
2046
2277
|
}
|
|
2047
2278
|
set linear(linear) {
|
|
2048
|
-
this.
|
|
2279
|
+
this.set({ linear });
|
|
2049
2280
|
}
|
|
2050
2281
|
set legacy(legacy) {
|
|
2051
|
-
this.
|
|
2282
|
+
this.set({ legacy });
|
|
2052
2283
|
}
|
|
2053
2284
|
set flat(flat) {
|
|
2054
|
-
this.
|
|
2285
|
+
this.set({ flat });
|
|
2055
2286
|
}
|
|
2056
2287
|
set orthographic(orthographic) {
|
|
2057
|
-
this.
|
|
2288
|
+
this.set({ orthographic });
|
|
2058
2289
|
}
|
|
2059
2290
|
set frameloop(frameloop) {
|
|
2060
|
-
this.
|
|
2291
|
+
this.set({ frameloop });
|
|
2061
2292
|
}
|
|
2062
2293
|
set dpr(dpr) {
|
|
2063
|
-
this.
|
|
2294
|
+
this.set({ dpr });
|
|
2064
2295
|
}
|
|
2065
2296
|
set raycaster(raycaster) {
|
|
2066
|
-
this.
|
|
2297
|
+
this.set({ raycaster });
|
|
2067
2298
|
}
|
|
2068
2299
|
set shadows(shadows) {
|
|
2069
|
-
this.
|
|
2300
|
+
this.set({
|
|
2070
2301
|
shadows: typeof shadows === 'object' ? shadows : shadows,
|
|
2071
2302
|
});
|
|
2072
2303
|
}
|
|
2073
2304
|
set camera(camera) {
|
|
2074
|
-
this.
|
|
2305
|
+
this.set({ camera });
|
|
2075
2306
|
}
|
|
2076
2307
|
set gl(gl) {
|
|
2077
|
-
this.
|
|
2308
|
+
this.set({ gl });
|
|
2078
2309
|
}
|
|
2079
2310
|
set eventSource(eventSource) {
|
|
2080
|
-
this.
|
|
2311
|
+
this.set({ eventSource });
|
|
2081
2312
|
}
|
|
2082
2313
|
set eventPrefix(eventPrefix) {
|
|
2083
|
-
this.
|
|
2314
|
+
this.set({ eventPrefix });
|
|
2084
2315
|
}
|
|
2085
2316
|
set lookAt(lookAt) {
|
|
2086
|
-
this.
|
|
2317
|
+
this.set({ lookAt });
|
|
2087
2318
|
}
|
|
2088
2319
|
set performance(performance) {
|
|
2089
|
-
this.
|
|
2090
|
-
}
|
|
2091
|
-
get sceneRef() {
|
|
2092
|
-
return this.store.read((s) => s.sceneRef);
|
|
2093
|
-
}
|
|
2094
|
-
get isConfigured() {
|
|
2095
|
-
return this.store.isConfigured;
|
|
2096
|
-
}
|
|
2097
|
-
initialize() {
|
|
2098
|
-
super.initialize();
|
|
2099
|
-
this.write({
|
|
2100
|
-
shadows: false,
|
|
2101
|
-
linear: false,
|
|
2102
|
-
flat: false,
|
|
2103
|
-
legacy: false,
|
|
2104
|
-
orthographic: false,
|
|
2105
|
-
frameloop: 'always',
|
|
2106
|
-
dpr: [1, 2],
|
|
2107
|
-
events: createPointerEvents,
|
|
2108
|
-
});
|
|
2320
|
+
this.set({ performance });
|
|
2109
2321
|
}
|
|
2110
2322
|
ngOnInit() {
|
|
2111
|
-
this.
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
this.canvasPointerMissed.emit(event);
|
|
2122
|
-
});
|
|
2123
|
-
},
|
|
2124
|
-
});
|
|
2125
|
-
}
|
|
2126
|
-
// set rootStateMap
|
|
2127
|
-
rootStateMap.set(this.glCanvas.nativeElement, this.store.read);
|
|
2128
|
-
// setup canvas state
|
|
2129
|
-
this.store.init();
|
|
2130
|
-
this.store.onReady(() => {
|
|
2131
|
-
const state = this.store.read();
|
|
2132
|
-
const inputs = this.read();
|
|
2133
|
-
// canvas is ready
|
|
2134
|
-
this.store.write((s) => ({ internal: { ...s.internal, active: true } }));
|
|
2135
|
-
// Connect to eventsource
|
|
2136
|
-
state.events.connect?.(inputs.eventSource instanceof ElementRef ? inputs.eventSource.nativeElement : inputs.eventSource);
|
|
2137
|
-
// Set up compute function
|
|
2138
|
-
if (inputs.eventPrefix) {
|
|
2139
|
-
state.setEvents({
|
|
2140
|
-
compute: (event, stateGetter) => {
|
|
2141
|
-
const innerState = stateGetter();
|
|
2142
|
-
const x = event[(inputs.eventPrefix + 'X')];
|
|
2143
|
-
const y = event[(inputs.eventPrefix + 'Y')];
|
|
2144
|
-
innerState.pointer.set((x / innerState.size.width) * 2 - 1, -(y / innerState.size.height) * 2 + 1);
|
|
2145
|
-
innerState.raycaster.setFromCamera(innerState.pointer, innerState.camera);
|
|
2146
|
-
},
|
|
2147
|
-
});
|
|
2148
|
-
}
|
|
2149
|
-
if (this.created.observed) {
|
|
2150
|
-
this.zone.run(() => {
|
|
2151
|
-
requestAnimationFrame(() => {
|
|
2152
|
-
this.created.emit(this.store.read());
|
|
2153
|
-
});
|
|
2154
|
-
});
|
|
2155
|
-
}
|
|
2323
|
+
if (!this.get('eventSource')) {
|
|
2324
|
+
// set default event source to the host element
|
|
2325
|
+
this.eventSource = this.host.nativeElement;
|
|
2326
|
+
}
|
|
2327
|
+
if (this.pointerMissed.observed) {
|
|
2328
|
+
this.store.set({
|
|
2329
|
+
onPointerMissed: (event) => {
|
|
2330
|
+
this.pointerMissed.emit(event);
|
|
2331
|
+
this.cdr.detectChanges();
|
|
2332
|
+
},
|
|
2156
2333
|
});
|
|
2334
|
+
}
|
|
2335
|
+
// setup NgtStore
|
|
2336
|
+
this.store.init();
|
|
2337
|
+
// set rootStateMap
|
|
2338
|
+
rootStateMap.set(this.glCanvas.nativeElement, this.store);
|
|
2339
|
+
// subscribe to store to listen for ready state
|
|
2340
|
+
this.hold(this.store.select('ready').pipe(filter((ready) => ready)), () => {
|
|
2341
|
+
this.storeReady();
|
|
2157
2342
|
});
|
|
2158
2343
|
}
|
|
2159
|
-
onResize(
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2344
|
+
onResize({ width, height }) {
|
|
2345
|
+
if (width > 0 && height > 0) {
|
|
2346
|
+
if (!this.store.isInit)
|
|
2347
|
+
this.store.init();
|
|
2348
|
+
this.store.configure(this.get(), this.glCanvas.nativeElement);
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
storeReady() {
|
|
2352
|
+
// canvas is ready, let's activate the loop
|
|
2353
|
+
this.store.set((state) => ({ internal: { ...state.internal, active: true } }));
|
|
2354
|
+
const inputs = this.get();
|
|
2355
|
+
const state = this.store.get();
|
|
2356
|
+
// connect to event source
|
|
2357
|
+
state.events.connect?.(is.ref(inputs.eventSource) ? inputs.eventSource.nativeElement : inputs.eventSource);
|
|
2358
|
+
// setup compute function for events
|
|
2359
|
+
if (inputs.eventPrefix) {
|
|
2360
|
+
state.setEvents({
|
|
2361
|
+
compute: (event, store) => {
|
|
2362
|
+
const innerState = store.get();
|
|
2363
|
+
const x = event[(inputs.eventPrefix + 'X')];
|
|
2364
|
+
const y = event[(inputs.eventPrefix + 'Y')];
|
|
2365
|
+
innerState.pointer.set((x / innerState.size.width) * 2 - 1, -(y / innerState.size.height) * 2 + 1);
|
|
2366
|
+
innerState.raycaster.setFromCamera(innerState.pointer, innerState.camera);
|
|
2367
|
+
},
|
|
2368
|
+
});
|
|
2369
|
+
}
|
|
2370
|
+
// emit created event if observed
|
|
2371
|
+
if (this.created.observed) {
|
|
2372
|
+
this.created.emit(this.store.get());
|
|
2373
|
+
this.cdr.detectChanges();
|
|
2374
|
+
}
|
|
2375
|
+
// render
|
|
2376
|
+
if (this.glRef) {
|
|
2377
|
+
this.glRef.destroy();
|
|
2378
|
+
}
|
|
2379
|
+
requestAnimationFrame(() => {
|
|
2380
|
+
this.glEnvInjector = createEnvironmentInjector([
|
|
2381
|
+
provideNgtRenderer({
|
|
2382
|
+
store: this.store,
|
|
2383
|
+
changeDetectorRef: this.cdr,
|
|
2384
|
+
compoundPrefixes: this.compoundPrefixes,
|
|
2385
|
+
}),
|
|
2386
|
+
], this.envInjector);
|
|
2387
|
+
this.glRef = this.glAnchor.createComponent(this.scene, { environmentInjector: this.glEnvInjector });
|
|
2388
|
+
this.glRef.changeDetectorRef.detectChanges();
|
|
2389
|
+
this.glRef.changeDetectorRef.detach();
|
|
2390
|
+
this.cdr.detectChanges();
|
|
2168
2391
|
});
|
|
2169
2392
|
}
|
|
2170
2393
|
ngOnDestroy() {
|
|
2171
|
-
this.
|
|
2394
|
+
if (this.glRef) {
|
|
2395
|
+
this.glRef.destroy();
|
|
2396
|
+
}
|
|
2397
|
+
if (this.glEnvInjector) {
|
|
2398
|
+
this.glEnvInjector.destroy();
|
|
2399
|
+
}
|
|
2400
|
+
injectNgtLoader.destroy();
|
|
2172
2401
|
super.ngOnDestroy();
|
|
2173
2402
|
}
|
|
2174
2403
|
}
|
|
2175
|
-
NgtCanvas.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.
|
|
2176
|
-
NgtCanvas.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.
|
|
2177
|
-
<ngt-canvas-container (
|
|
2178
|
-
<canvas #glCanvas style="display: block">
|
|
2179
|
-
|
|
2180
|
-
<ng-content></ng-content>
|
|
2181
|
-
</canvas>
|
|
2404
|
+
NgtCanvas.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtCanvas, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2405
|
+
NgtCanvas.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.1.1", type: NgtCanvas, isStandalone: true, selector: "ngt-canvas", inputs: { scene: "scene", compoundPrefixes: "compoundPrefixes", linear: "linear", legacy: "legacy", flat: "flat", orthographic: "orthographic", frameloop: "frameloop", dpr: "dpr", raycaster: "raycaster", shadows: "shadows", camera: "camera", gl: "gl", eventSource: "eventSource", eventPrefix: "eventPrefix", lookAt: "lookAt", performance: "performance" }, outputs: { created: "created", pointerMissed: "pointerMissed" }, host: { properties: { "class.ngt-canvas": "this.hostClass", "style.pointerEvents": "this.pointerEvents" } }, providers: [NgtStore], viewQueries: [{ propertyName: "glCanvas", first: true, predicate: ["glCanvas"], descendants: true, static: true }, { propertyName: "glAnchor", first: true, predicate: ["glAnchor"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
2406
|
+
<ngt-canvas-container (canvasResize)="onResize($event)">
|
|
2407
|
+
<canvas #glCanvas style="display: block;"></canvas>
|
|
2408
|
+
<ng-container #glAnchor />
|
|
2182
2409
|
</ngt-canvas-container>
|
|
2183
|
-
`, isInline: true, styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}\n"], dependencies: [{ kind: "component", type: NgtCanvasContainer, selector: "ngt-canvas-container", outputs: ["
|
|
2184
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.
|
|
2410
|
+
`, isInline: true, styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}\n"], dependencies: [{ kind: "component", type: NgtCanvasContainer, selector: "ngt-canvas-container", outputs: ["canvasResize"] }] });
|
|
2411
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtCanvas, decorators: [{
|
|
2185
2412
|
type: Component,
|
|
2186
2413
|
args: [{ selector: 'ngt-canvas', standalone: true, template: `
|
|
2187
|
-
<ngt-canvas-container (
|
|
2188
|
-
<canvas #glCanvas style="display: block">
|
|
2189
|
-
|
|
2190
|
-
<ng-content></ng-content>
|
|
2191
|
-
</canvas>
|
|
2414
|
+
<ngt-canvas-container (canvasResize)="onResize($event)">
|
|
2415
|
+
<canvas #glCanvas style="display: block;"></canvas>
|
|
2416
|
+
<ng-container #glAnchor />
|
|
2192
2417
|
</ngt-canvas-container>
|
|
2193
|
-
`,
|
|
2418
|
+
`, imports: [NgtCanvasContainer], providers: [NgtStore], styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}\n"] }]
|
|
2194
2419
|
}], propDecorators: { hostClass: [{
|
|
2195
2420
|
type: HostBinding,
|
|
2196
2421
|
args: ['class.ngt-canvas']
|
|
2197
2422
|
}], pointerEvents: [{
|
|
2198
2423
|
type: HostBinding,
|
|
2199
2424
|
args: ['style.pointerEvents']
|
|
2425
|
+
}], scene: [{
|
|
2426
|
+
type: Input
|
|
2427
|
+
}], compoundPrefixes: [{
|
|
2428
|
+
type: Input
|
|
2200
2429
|
}], linear: [{
|
|
2201
2430
|
type: Input
|
|
2202
2431
|
}], legacy: [{
|
|
@@ -2227,249 +2456,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImpor
|
|
|
2227
2456
|
type: Input
|
|
2228
2457
|
}], created: [{
|
|
2229
2458
|
type: Output
|
|
2230
|
-
}],
|
|
2459
|
+
}], pointerMissed: [{
|
|
2231
2460
|
type: Output
|
|
2232
2461
|
}], glCanvas: [{
|
|
2233
2462
|
type: ViewChild,
|
|
2234
2463
|
args: ['glCanvas', { static: true }]
|
|
2235
|
-
}],
|
|
2236
|
-
type:
|
|
2237
|
-
args: [
|
|
2238
|
-
}] } });
|
|
2239
|
-
|
|
2240
|
-
const NGT_ARGS = new InjectionToken('NgtArgs');
|
|
2241
|
-
function injectArgs(options = {}) {
|
|
2242
|
-
return inject(NGT_ARGS, options);
|
|
2243
|
-
}
|
|
2244
|
-
class NgtArgs {
|
|
2245
|
-
constructor() {
|
|
2246
|
-
this.templateRef = inject(TemplateRef);
|
|
2247
|
-
this.vcr = inject(ViewContainerRef);
|
|
2248
|
-
}
|
|
2249
|
-
set args(args) {
|
|
2250
|
-
if (this.view) {
|
|
2251
|
-
this.view.destroy();
|
|
2252
|
-
}
|
|
2253
|
-
this.view = this.vcr.createEmbeddedView(this.templateRef, {}, { injector: Injector.create({ providers: [{ provide: NGT_ARGS, useValue: args }] }) });
|
|
2254
|
-
}
|
|
2255
|
-
}
|
|
2256
|
-
NgtArgs.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtArgs, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2257
|
-
NgtArgs.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.0", type: NgtArgs, isStandalone: true, selector: "[args]", inputs: { args: "args" }, ngImport: i0 });
|
|
2258
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtArgs, decorators: [{
|
|
2259
|
-
type: Directive,
|
|
2260
|
-
args: [{
|
|
2261
|
-
selector: '[args]',
|
|
2262
|
-
standalone: true,
|
|
2263
|
-
}]
|
|
2264
|
-
}], propDecorators: { args: [{
|
|
2265
|
-
type: Input
|
|
2464
|
+
}], glAnchor: [{
|
|
2465
|
+
type: ViewChild,
|
|
2466
|
+
args: ['glAnchor', { static: true, read: ViewContainerRef }]
|
|
2266
2467
|
}] } });
|
|
2267
2468
|
|
|
2268
|
-
class NgtCursor {
|
|
2269
|
-
constructor(instance, document) {
|
|
2270
|
-
if (!instance)
|
|
2271
|
-
return;
|
|
2272
|
-
merge(instance.pointerover.pipe(map(() => true)), instance.pointerout.pipe(map(() => false)))
|
|
2273
|
-
.pipe(takeUntil(instance.destroy$))
|
|
2274
|
-
.subscribe((hovered) => {
|
|
2275
|
-
document.body.style.cursor = hovered ? 'pointer' : 'auto';
|
|
2276
|
-
});
|
|
2277
|
-
}
|
|
2278
|
-
}
|
|
2279
|
-
NgtCursor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtCursor, deps: [{ token: NgtInstance, optional: true, self: true }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive });
|
|
2280
|
-
NgtCursor.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.0", type: NgtCursor, isStandalone: true, selector: "[ngtCursor]", exportAs: ["ngtCursor"], ngImport: i0 });
|
|
2281
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtCursor, decorators: [{
|
|
2282
|
-
type: Directive,
|
|
2283
|
-
args: [{
|
|
2284
|
-
selector: '[ngtCursor]',
|
|
2285
|
-
standalone: true,
|
|
2286
|
-
exportAs: 'ngtCursor',
|
|
2287
|
-
}]
|
|
2288
|
-
}], ctorParameters: function () { return [{ type: NgtInstance, decorators: [{
|
|
2289
|
-
type: Optional
|
|
2290
|
-
}, {
|
|
2291
|
-
type: Self
|
|
2292
|
-
}] }, { type: Document, decorators: [{
|
|
2293
|
-
type: Inject,
|
|
2294
|
-
args: [DOCUMENT]
|
|
2295
|
-
}] }]; } });
|
|
2296
|
-
|
|
2297
2469
|
class NgtRepeat extends NgForOf {
|
|
2298
2470
|
set ngForRepeat(count) {
|
|
2299
2471
|
this.ngForOf = Number.isInteger(count) ? Array.from({ length: count }, (_, i) => i) : [];
|
|
2300
2472
|
}
|
|
2301
2473
|
}
|
|
2302
|
-
NgtRepeat.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.
|
|
2303
|
-
NgtRepeat.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.
|
|
2304
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.
|
|
2474
|
+
NgtRepeat.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRepeat, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
2475
|
+
NgtRepeat.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.1", type: NgtRepeat, isStandalone: true, selector: "[ngFor][ngForRepeat]", inputs: { ngForRepeat: "ngForRepeat" }, usesInheritance: true, ngImport: i0 });
|
|
2476
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRepeat, decorators: [{
|
|
2305
2477
|
type: Directive,
|
|
2306
|
-
args: [{
|
|
2307
|
-
selector: '[ngFor][ngForRepeat]',
|
|
2308
|
-
standalone: true,
|
|
2309
|
-
}]
|
|
2478
|
+
args: [{ selector: '[ngFor][ngForRepeat]', standalone: true }]
|
|
2310
2479
|
}], propDecorators: { ngForRepeat: [{
|
|
2311
2480
|
type: Input
|
|
2312
2481
|
}] } });
|
|
2313
2482
|
|
|
2314
|
-
class NgtPiPipe {
|
|
2315
|
-
transform(value) {
|
|
2316
|
-
return value * Math.PI;
|
|
2317
|
-
}
|
|
2318
|
-
}
|
|
2319
|
-
NgtPiPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtPiPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
2320
|
-
NgtPiPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.0.0", ngImport: i0, type: NgtPiPipe, isStandalone: true, name: "pi" });
|
|
2321
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtPiPipe, decorators: [{
|
|
2322
|
-
type: Pipe,
|
|
2323
|
-
args: [{ name: 'pi', standalone: true }]
|
|
2324
|
-
}] });
|
|
2325
|
-
|
|
2326
|
-
class NgtMathPipe {
|
|
2327
|
-
transform(value, keyOfMath) {
|
|
2328
|
-
const params = Array.isArray(value) ? value : [value];
|
|
2329
|
-
return Math[keyOfMath](...params);
|
|
2330
|
-
}
|
|
2331
|
-
}
|
|
2332
|
-
NgtMathPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtMathPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
2333
|
-
NgtMathPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.0.0", ngImport: i0, type: NgtMathPipe, isStandalone: true, name: "math" });
|
|
2334
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtMathPipe, decorators: [{
|
|
2335
|
-
type: Pipe,
|
|
2336
|
-
args: [{ name: 'math', standalone: true }]
|
|
2337
|
-
}] });
|
|
2338
|
-
|
|
2339
|
-
class NgtRadianPipe {
|
|
2340
|
-
transform(degree) {
|
|
2341
|
-
return (degree * Math.PI) / 180;
|
|
2342
|
-
}
|
|
2343
|
-
}
|
|
2344
|
-
NgtRadianPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtRadianPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
2345
|
-
NgtRadianPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.0.0", ngImport: i0, type: NgtRadianPipe, isStandalone: true, name: "radian" });
|
|
2346
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtRadianPipe, decorators: [{
|
|
2347
|
-
type: Pipe,
|
|
2348
|
-
args: [{ name: 'radian', standalone: true }]
|
|
2349
|
-
}] });
|
|
2350
|
-
|
|
2351
|
-
class NgtSidePipe {
|
|
2352
|
-
transform(side) {
|
|
2353
|
-
switch (side) {
|
|
2354
|
-
case 'front':
|
|
2355
|
-
return THREE.FrontSide;
|
|
2356
|
-
case 'back':
|
|
2357
|
-
return THREE.BackSide;
|
|
2358
|
-
case 'double':
|
|
2359
|
-
return THREE.DoubleSide;
|
|
2360
|
-
}
|
|
2361
|
-
}
|
|
2362
|
-
}
|
|
2363
|
-
NgtSidePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtSidePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
2364
|
-
NgtSidePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.0.0", ngImport: i0, type: NgtSidePipe, isStandalone: true, name: "side" });
|
|
2365
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NgtSidePipe, decorators: [{
|
|
2366
|
-
type: Pipe,
|
|
2367
|
-
args: [{ name: 'side', standalone: true }]
|
|
2368
|
-
}] });
|
|
2369
|
-
|
|
2370
|
-
function capitalize(str) {
|
|
2371
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
2372
|
-
}
|
|
2373
|
-
|
|
2374
|
-
function proxify(instance, proxifyOptions = {}) {
|
|
2375
|
-
const ngtInstance = injectInstance({ host: true });
|
|
2376
|
-
const store = inject(NgtStore);
|
|
2377
|
-
const zone = inject(NgZone);
|
|
2378
|
-
const parentInstance = injectInstanceRef({ skipSelf: true, optional: true });
|
|
2379
|
-
return zone.runOutsideAngular(() => {
|
|
2380
|
-
// prep the instance w/ local state
|
|
2381
|
-
instance = prepare(instance, store.read, store.rootStateFactory, parentInstance?.(), ngtInstance.instanceValue ? ngtInstance.instanceRef : undefined, !!proxifyOptions.primitive);
|
|
2382
|
-
let storeReadySubscription;
|
|
2383
|
-
const newValueSubscriptionMap = new Map();
|
|
2384
|
-
function setProp(obj, prop, newValue) {
|
|
2385
|
-
const capitalizedProp = `set${capitalize(prop)}`;
|
|
2386
|
-
if (isObservable(newValue)) {
|
|
2387
|
-
const sub = newValue.subscribe((val) => {
|
|
2388
|
-
if (obj[capitalizedProp] && typeof obj[capitalizedProp] === 'function') {
|
|
2389
|
-
obj[capitalizedProp](val);
|
|
2390
|
-
}
|
|
2391
|
-
else {
|
|
2392
|
-
applyProps(obj, { [prop]: val });
|
|
2393
|
-
}
|
|
2394
|
-
ngtInstance.write({ [prop]: val });
|
|
2395
|
-
});
|
|
2396
|
-
return () => sub.unsubscribe();
|
|
2397
|
-
}
|
|
2398
|
-
if (obj[capitalizedProp] && typeof obj[capitalizedProp] === 'function') {
|
|
2399
|
-
obj[capitalizedProp](newValue);
|
|
2400
|
-
}
|
|
2401
|
-
else {
|
|
2402
|
-
applyProps(obj, { [prop]: newValue });
|
|
2403
|
-
}
|
|
2404
|
-
ngtInstance.write({ [prop]: newValue });
|
|
2405
|
-
return;
|
|
2406
|
-
}
|
|
2407
|
-
const handler = {
|
|
2408
|
-
get(target, p, receiver) {
|
|
2409
|
-
if (p === 'instanceRef')
|
|
2410
|
-
return ngtInstance.instanceRef;
|
|
2411
|
-
if (p === 'instance')
|
|
2412
|
-
return ngtInstance;
|
|
2413
|
-
if (p === NGT_PROXY_INSTANCE)
|
|
2414
|
-
return target;
|
|
2415
|
-
const capitalizedProp = `get${capitalize(p)}`;
|
|
2416
|
-
if (target[capitalizedProp] && typeof target[capitalizedProp] === 'function') {
|
|
2417
|
-
return target[capitalizedProp]();
|
|
2418
|
-
}
|
|
2419
|
-
return Reflect.get(target, p, receiver);
|
|
2420
|
-
},
|
|
2421
|
-
set(target, p, newValue, receiver) {
|
|
2422
|
-
const prop = p;
|
|
2423
|
-
if (storeReadySubscription)
|
|
2424
|
-
storeReadySubscription.unsubscribe();
|
|
2425
|
-
if (newValueSubscriptionMap.has(prop))
|
|
2426
|
-
newValueSubscriptionMap.get(prop)();
|
|
2427
|
-
// Angular sets this property
|
|
2428
|
-
if (p === '__ngContext__')
|
|
2429
|
-
return Reflect.set(target, p, newValue, receiver);
|
|
2430
|
-
return zone.runOutsideAngular(() => {
|
|
2431
|
-
// TODO: figure out what else we need to handle
|
|
2432
|
-
// we should handle if newValue is an Observable as well
|
|
2433
|
-
if (store.read((s) => s.ready)) {
|
|
2434
|
-
const cleanUp = setProp(instance, prop, newValue);
|
|
2435
|
-
if (cleanUp)
|
|
2436
|
-
newValueSubscriptionMap.set(prop, cleanUp);
|
|
2437
|
-
}
|
|
2438
|
-
else {
|
|
2439
|
-
storeReadySubscription = store.onReady(() => setProp(instance, prop, newValue));
|
|
2440
|
-
}
|
|
2441
|
-
// schedule updateCallback on next event loop
|
|
2442
|
-
queueMicrotask(() => {
|
|
2443
|
-
if (ngtInstance.updateCallback)
|
|
2444
|
-
ngtInstance.updateCallback(instance);
|
|
2445
|
-
});
|
|
2446
|
-
return true;
|
|
2447
|
-
});
|
|
2448
|
-
},
|
|
2449
|
-
};
|
|
2450
|
-
ngtInstance.effect(tapEffect(() => () => {
|
|
2451
|
-
if (storeReadySubscription)
|
|
2452
|
-
storeReadySubscription.unsubscribe();
|
|
2453
|
-
newValueSubscriptionMap.forEach((cleanUp) => cleanUp());
|
|
2454
|
-
}))();
|
|
2455
|
-
const proxied = new Proxy(instance, handler);
|
|
2456
|
-
if (proxifyOptions.attach)
|
|
2457
|
-
ngtInstance.attach = proxifyOptions.attach;
|
|
2458
|
-
if (proxifyOptions.created)
|
|
2459
|
-
proxifyOptions.created(proxied, store.read, ngtInstance);
|
|
2460
|
-
ngtInstance.instanceRef.set(proxied);
|
|
2461
|
-
return proxied;
|
|
2462
|
-
});
|
|
2463
|
-
}
|
|
2464
|
-
|
|
2465
|
-
/**
|
|
2466
|
-
* main exports
|
|
2467
|
-
*/
|
|
2468
|
-
|
|
2469
2483
|
/**
|
|
2470
2484
|
* Generated bundle index. Do not edit.
|
|
2471
2485
|
*/
|
|
2472
2486
|
|
|
2473
|
-
export {
|
|
2474
|
-
//# sourceMappingURL=angular-three.mjs.map
|
|
2487
|
+
export { NGT_CATALOGUE, NgtArgs, NgtCanvas, NgtCanvasContainer, NgtRepeat, extend };
|
|
2475
2488
|
//# sourceMappingURL=angular-three.mjs.map
|