@needle-tools/engine 3.28.6-beta → 3.28.7-beta.1
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/CHANGELOG.md +2259 -2253
- package/LICENSE.md +10 -10
- package/README.md +52 -52
- package/dist/needle-engine.js +7 -10
- package/dist/needle-engine.light.js +7 -10
- package/dist/needle-engine.light.min.js +7 -10
- package/dist/needle-engine.light.umd.cjs +7 -10
- package/dist/needle-engine.min.js +7 -10
- package/dist/needle-engine.umd.cjs +7 -10
- package/lib/engine/api.d.ts +52 -52
- package/lib/engine/api.js +51 -51
- package/lib/engine/assets/index.d.ts +1 -1
- package/lib/engine/assets/index.js +4 -4
- package/lib/engine/codegen/register_types.d.ts +1 -1
- package/lib/engine/codegen/register_types.js +439 -439
- package/lib/engine/debug/debug.d.ts +12 -12
- package/lib/engine/debug/debug.js +26 -26
- package/lib/engine/debug/debug_console.d.ts +2 -2
- package/lib/engine/debug/debug_console.js +204 -204
- package/lib/engine/debug/debug_overlay.d.ts +10 -10
- package/lib/engine/debug/debug_overlay.js +277 -277
- package/lib/engine/debug/index.d.ts +1 -1
- package/lib/engine/debug/index.js +1 -1
- package/lib/engine/engine_addressables.d.ts +75 -75
- package/lib/engine/engine_addressables.js +441 -441
- package/lib/engine/engine_application.d.ts +19 -19
- package/lib/engine/engine_application.js +45 -45
- package/lib/engine/engine_assetdatabase.d.ts +25 -25
- package/lib/engine/engine_assetdatabase.js +341 -341
- package/lib/engine/engine_camera.d.ts +6 -6
- package/lib/engine/engine_camera.js +23 -23
- package/lib/engine/engine_components.d.ts +17 -17
- package/lib/engine/engine_components.js +273 -273
- package/lib/engine/engine_components_internal.d.ts +11 -11
- package/lib/engine/engine_components_internal.js +41 -41
- package/lib/engine/engine_constants.d.ts +5 -5
- package/lib/engine/engine_constants.js +32 -32
- package/lib/engine/engine_context.d.ts +269 -269
- package/lib/engine/engine_context.js +1242 -1242
- package/lib/engine/engine_context_registry.d.ts +50 -50
- package/lib/engine/engine_context_registry.js +89 -89
- package/lib/engine/engine_coroutine.d.ts +4 -4
- package/lib/engine/engine_coroutine.js +21 -21
- package/lib/engine/engine_create_objects.d.ts +13 -13
- package/lib/engine/engine_create_objects.js +33 -33
- package/lib/engine/engine_default_parameters.d.ts +2 -2
- package/lib/engine/engine_default_parameters.js +3 -3
- package/lib/engine/engine_editor-sync.d.ts +17 -17
- package/lib/engine/engine_editor-sync.js +7 -7
- package/lib/engine/engine_element.d.ts +55 -55
- package/lib/engine/engine_element.js +559 -559
- package/lib/engine/engine_element_attributes.d.ts +49 -49
- package/lib/engine/engine_element_attributes.js +1 -1
- package/lib/engine/engine_element_extras.d.ts +6 -6
- package/lib/engine/engine_element_extras.js +13 -13
- package/lib/engine/engine_element_loading.d.ts +40 -40
- package/lib/engine/engine_element_loading.js +312 -312
- package/lib/engine/engine_element_overlay.d.ts +19 -19
- package/lib/engine/engine_element_overlay.js +143 -143
- package/lib/engine/engine_fileloader.d.ts +3 -3
- package/lib/engine/engine_fileloader.js +7 -7
- package/lib/engine/engine_gameobject.d.ts +39 -39
- package/lib/engine/engine_gameobject.js +559 -559
- package/lib/engine/engine_generic_utils.d.ts +1 -1
- package/lib/engine/engine_generic_utils.js +13 -13
- package/lib/engine/engine_gizmos.d.ts +26 -26
- package/lib/engine/engine_gizmos.js +282 -282
- package/lib/engine/engine_gltf.d.ts +13 -13
- package/lib/engine/engine_gltf.js +15 -15
- package/lib/engine/engine_gltf_builtin_components.d.ts +7 -7
- package/lib/engine/engine_gltf_builtin_components.js +298 -298
- package/lib/engine/engine_hot_reload.d.ts +5 -5
- package/lib/engine/engine_hot_reload.js +182 -182
- package/lib/engine/engine_input.d.ts +129 -129
- package/lib/engine/engine_input.js +799 -799
- package/lib/engine/engine_input_utils.d.ts +2 -2
- package/lib/engine/engine_input_utils.js +22 -22
- package/lib/engine/engine_instancing.d.ts +16 -16
- package/lib/engine/engine_instancing.js +36 -36
- package/lib/engine/engine_license.d.ts +4 -4
- package/lib/engine/engine_license.js +398 -398
- package/lib/engine/engine_lifecycle_api.d.ts +14 -14
- package/lib/engine/engine_lifecycle_api.js +24 -24
- package/lib/engine/engine_lifecycle_functions_internal.d.ts +6 -6
- package/lib/engine/engine_lifecycle_functions_internal.js +28 -28
- package/lib/engine/engine_lightdata.d.ts +23 -23
- package/lib/engine/engine_lightdata.js +86 -86
- package/lib/engine/engine_loaders.d.ts +7 -7
- package/lib/engine/engine_loaders.js +69 -69
- package/lib/engine/engine_mainloop_utils.d.ts +13 -13
- package/lib/engine/engine_mainloop_utils.js +426 -426
- package/lib/engine/engine_math.d.ts +43 -43
- package/lib/engine/engine_math.js +147 -147
- package/lib/engine/engine_networking.d.ts +176 -176
- package/lib/engine/engine_networking.js +649 -649
- package/lib/engine/engine_networking_auto.d.ts +24 -24
- package/lib/engine/engine_networking_auto.js +324 -324
- package/lib/engine/engine_networking_files.d.ts +23 -23
- package/lib/engine/engine_networking_files.js +176 -176
- package/lib/engine/engine_networking_files_default_components.d.ts +3 -3
- package/lib/engine/engine_networking_files_default_components.js +39 -39
- package/lib/engine/engine_networking_instantiate.d.ts +39 -39
- package/lib/engine/engine_networking_instantiate.js +302 -302
- package/lib/engine/engine_networking_peer.d.ts +15 -15
- package/lib/engine/engine_networking_peer.js +132 -132
- package/lib/engine/engine_networking_streams.d.ts +90 -90
- package/lib/engine/engine_networking_streams.js +428 -428
- package/lib/engine/engine_networking_types.d.ts +14 -14
- package/lib/engine/engine_networking_types.js +7 -7
- package/lib/engine/engine_networking_utils.d.ts +2 -2
- package/lib/engine/engine_networking_utils.js +20 -20
- package/lib/engine/engine_patcher.d.ts +10 -10
- package/lib/engine/engine_patcher.js +142 -142
- package/lib/engine/engine_physics.d.ts +115 -115
- package/lib/engine/engine_physics.js +228 -228
- package/lib/engine/engine_physics.types.d.ts +37 -37
- package/lib/engine/engine_physics.types.js +33 -33
- package/lib/engine/engine_physics_rapier.d.ts +112 -112
- package/lib/engine/engine_physics_rapier.js +1266 -1266
- package/lib/engine/engine_playerview.d.ts +26 -26
- package/lib/engine/engine_playerview.js +64 -64
- package/lib/engine/engine_scenelighting.d.ts +74 -74
- package/lib/engine/engine_scenelighting.js +285 -285
- package/lib/engine/engine_scenetools.d.ts +35 -35
- package/lib/engine/engine_scenetools.js +212 -212
- package/lib/engine/engine_serialization.d.ts +4 -4
- package/lib/engine/engine_serialization.js +4 -4
- package/lib/engine/engine_serialization_builtin_serializer.d.ts +62 -62
- package/lib/engine/engine_serialization_builtin_serializer.js +369 -369
- package/lib/engine/engine_serialization_core.d.ts +84 -84
- package/lib/engine/engine_serialization_core.js +576 -576
- package/lib/engine/engine_serialization_decorator.d.ts +15 -15
- package/lib/engine/engine_serialization_decorator.js +54 -54
- package/lib/engine/engine_setup.d.ts +1 -1
- package/lib/engine/engine_setup.js +2 -2
- package/lib/engine/engine_shaders.d.ts +31 -31
- package/lib/engine/engine_shaders.js +229 -229
- package/lib/engine/engine_shims.d.ts +3 -3
- package/lib/engine/engine_shims.js +22 -22
- package/lib/engine/engine_texture.d.ts +20 -20
- package/lib/engine/engine_texture.js +57 -57
- package/lib/engine/engine_three_utils.d.ts +51 -51
- package/lib/engine/engine_three_utils.js +342 -342
- package/lib/engine/engine_time.d.ts +19 -19
- package/lib/engine/engine_time.js +47 -47
- package/lib/engine/engine_types.d.ts +358 -358
- package/lib/engine/engine_types.js +72 -72
- package/lib/engine/engine_typestore.d.ts +16 -16
- package/lib/engine/engine_typestore.js +35 -35
- package/lib/engine/engine_util_decorator.d.ts +12 -12
- package/lib/engine/engine_util_decorator.js +115 -115
- package/lib/engine/engine_utils.d.ts +104 -104
- package/lib/engine/engine_utils.js +518 -518
- package/lib/engine/engine_utils_screenshot.d.ts +10 -10
- package/lib/engine/engine_utils_screenshot.js +70 -70
- package/lib/engine/engine_web_api.d.ts +12 -12
- package/lib/engine/engine_web_api.js +112 -112
- package/lib/engine/extensions/EXT_texture_exr.d.ts +8 -8
- package/lib/engine/extensions/EXT_texture_exr.js +32 -32
- package/lib/engine/extensions/NEEDLE_animator_controller_model.d.ts +116 -116
- package/lib/engine/extensions/NEEDLE_animator_controller_model.js +91 -91
- package/lib/engine/extensions/NEEDLE_components.d.ts +33 -33
- package/lib/engine/extensions/NEEDLE_components.js +206 -206
- package/lib/engine/extensions/NEEDLE_gameobject_data.d.ts +10 -10
- package/lib/engine/extensions/NEEDLE_gameobject_data.js +57 -57
- package/lib/engine/extensions/NEEDLE_lighting_settings.d.ts +38 -38
- package/lib/engine/extensions/NEEDLE_lighting_settings.js +183 -183
- package/lib/engine/extensions/NEEDLE_lightmaps.d.ts +18 -18
- package/lib/engine/extensions/NEEDLE_lightmaps.js +108 -108
- package/lib/engine/extensions/NEEDLE_persistent_assets.d.ts +11 -11
- package/lib/engine/extensions/NEEDLE_persistent_assets.js +63 -63
- package/lib/engine/extensions/NEEDLE_progressive.d.ts +41 -41
- package/lib/engine/extensions/NEEDLE_progressive.js +366 -366
- package/lib/engine/extensions/NEEDLE_render_objects.d.ts +13 -13
- package/lib/engine/extensions/NEEDLE_render_objects.js +159 -159
- package/lib/engine/extensions/NEEDLE_techniques_webgl.d.ts +39 -39
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +544 -544
- package/lib/engine/extensions/extension_resolver.d.ts +4 -4
- package/lib/engine/extensions/extension_resolver.js +1 -1
- package/lib/engine/extensions/extension_utils.d.ts +2 -2
- package/lib/engine/extensions/extension_utils.js +140 -140
- package/lib/engine/extensions/extensions.d.ts +21 -21
- package/lib/engine/extensions/extensions.js +94 -94
- package/lib/engine/extensions/index.d.ts +5 -5
- package/lib/engine/extensions/index.js +5 -5
- package/lib/engine/extensions/usage_tracker.d.ts +13 -13
- package/lib/engine/extensions/usage_tracker.js +61 -61
- package/lib/engine/js-extensions/Camera.d.ts +1 -1
- package/lib/engine/js-extensions/Camera.js +36 -36
- package/lib/engine/js-extensions/Layers.d.ts +3 -3
- package/lib/engine/js-extensions/Layers.js +19 -19
- package/lib/engine/js-extensions/index.d.ts +2 -2
- package/lib/engine/js-extensions/index.js +2 -2
- package/lib/engine/shaders/shaderData.d.ts +55 -55
- package/lib/engine/shaders/shaderData.js +58 -58
- package/lib/engine/tests/test_utils.d.ts +2 -2
- package/lib/engine/tests/test_utils.js +53 -53
- package/lib/engine-components/AlignmentConstraint.d.ts +10 -10
- package/lib/engine-components/AlignmentConstraint.js +39 -39
- package/lib/engine-components/Animation.d.ts +53 -53
- package/lib/engine-components/Animation.js +333 -333
- package/lib/engine-components/AnimationCurve.d.ts +16 -16
- package/lib/engine-components/AnimationCurve.js +97 -97
- package/lib/engine-components/AnimationUtils.d.ts +8 -8
- package/lib/engine-components/AnimationUtils.js +110 -110
- package/lib/engine-components/Animator.d.ts +81 -81
- package/lib/engine-components/Animator.js +229 -229
- package/lib/engine-components/AnimatorController.d.ts +57 -57
- package/lib/engine-components/AnimatorController.js +887 -887
- package/lib/engine-components/AudioListener.d.ts +7 -7
- package/lib/engine-components/AudioListener.js +30 -30
- package/lib/engine-components/AudioSource.d.ts +61 -61
- package/lib/engine-components/AudioSource.js +422 -422
- package/lib/engine-components/AvatarLoader.d.ts +19 -19
- package/lib/engine-components/AvatarLoader.js +173 -173
- package/lib/engine-components/AxesHelper.d.ts +9 -9
- package/lib/engine-components/AxesHelper.js +44 -44
- package/lib/engine-components/BasicIKConstraint.d.ts +9 -9
- package/lib/engine-components/BasicIKConstraint.js +43 -43
- package/lib/engine-components/BoxHelperComponent.d.ts +16 -16
- package/lib/engine-components/BoxHelperComponent.js +89 -89
- package/lib/engine-components/Camera.d.ts +70 -70
- package/lib/engine-components/Camera.js +450 -450
- package/lib/engine-components/CameraUtils.d.ts +1 -1
- package/lib/engine-components/CameraUtils.js +77 -77
- package/lib/engine-components/CharacterController.d.ts +46 -46
- package/lib/engine-components/CharacterController.js +227 -227
- package/lib/engine-components/Collider.d.ts +46 -46
- package/lib/engine-components/Collider.js +153 -153
- package/lib/engine-components/Component.d.ts +228 -228
- package/lib/engine-components/Component.js +541 -541
- package/lib/engine-components/ContactShadows.d.ts +23 -23
- package/lib/engine-components/ContactShadows.js +233 -233
- package/lib/engine-components/DeleteBox.d.ts +9 -9
- package/lib/engine-components/DeleteBox.js +30 -30
- package/lib/engine-components/DeviceFlag.d.ts +12 -12
- package/lib/engine-components/DeviceFlag.js +43 -43
- package/lib/engine-components/DragControls.d.ts +51 -51
- package/lib/engine-components/DragControls.js +516 -516
- package/lib/engine-components/DropListener.d.ts +15 -15
- package/lib/engine-components/DropListener.js +120 -120
- package/lib/engine-components/Duplicatable.d.ts +16 -16
- package/lib/engine-components/Duplicatable.js +150 -150
- package/lib/engine-components/EventList.d.ts +28 -28
- package/lib/engine-components/EventList.js +105 -105
- package/lib/engine-components/EventTrigger.d.ts +12 -12
- package/lib/engine-components/EventTrigger.js +50 -50
- package/lib/engine-components/EventType.d.ts +19 -19
- package/lib/engine-components/EventType.js +71 -71
- package/lib/engine-components/FlyControls.d.ts +7 -7
- package/lib/engine-components/FlyControls.js +25 -25
- package/lib/engine-components/Fog.d.ts +20 -20
- package/lib/engine-components/Fog.js +60 -60
- package/lib/engine-components/Gizmos.d.ts +12 -12
- package/lib/engine-components/Gizmos.js +60 -60
- package/lib/engine-components/GridHelper.d.ts +12 -12
- package/lib/engine-components/GridHelper.js +47 -47
- package/lib/engine-components/GroundProjection.d.ts +21 -21
- package/lib/engine-components/GroundProjection.js +97 -97
- package/lib/engine-components/Interactable.d.ts +10 -10
- package/lib/engine-components/Interactable.js +11 -11
- package/lib/engine-components/Joints.d.ts +19 -19
- package/lib/engine-components/Joints.js +51 -51
- package/lib/engine-components/LODGroup.d.ts +30 -30
- package/lib/engine-components/LODGroup.js +145 -145
- package/lib/engine-components/Light.d.ts +75 -75
- package/lib/engine-components/Light.js +475 -475
- package/lib/engine-components/LookAtConstraint.d.ts +7 -7
- package/lib/engine-components/LookAtConstraint.js +17 -17
- package/lib/engine-components/NestedGltf.d.ts +11 -11
- package/lib/engine-components/NestedGltf.js +74 -74
- package/lib/engine-components/Networking.d.ts +11 -11
- package/lib/engine-components/Networking.js +70 -70
- package/lib/engine-components/OffsetConstraint.d.ts +14 -14
- package/lib/engine-components/OffsetConstraint.js +65 -65
- package/lib/engine-components/OrbitControls.d.ts +111 -111
- package/lib/engine-components/OrbitControls.js +646 -646
- package/lib/engine-components/ParticleSystem.d.ts +145 -145
- package/lib/engine-components/ParticleSystem.js +1077 -1077
- package/lib/engine-components/ParticleSystemModules.d.ts +489 -489
- package/lib/engine-components/ParticleSystemModules.js +1667 -1667
- package/lib/engine-components/ParticleSystemSubEmitter.d.ts +25 -25
- package/lib/engine-components/ParticleSystemSubEmitter.js +86 -86
- package/lib/engine-components/PlayerColor.d.ts +13 -13
- package/lib/engine-components/PlayerColor.js +83 -83
- package/lib/engine-components/ReflectionProbe.d.ts +22 -22
- package/lib/engine-components/ReflectionProbe.js +181 -181
- package/lib/engine-components/Renderer.d.ts +112 -112
- package/lib/engine-components/Renderer.js +1029 -1029
- package/lib/engine-components/RendererLightmap.d.ts +19 -19
- package/lib/engine-components/RendererLightmap.js +127 -127
- package/lib/engine-components/RigidBody.d.ts +120 -120
- package/lib/engine-components/RigidBody.js +452 -452
- package/lib/engine-components/SceneSwitcher.d.ts +72 -72
- package/lib/engine-components/SceneSwitcher.js +583 -583
- package/lib/engine-components/ScreenCapture.d.ts +64 -64
- package/lib/engine-components/ScreenCapture.js +405 -405
- package/lib/engine-components/ShadowCatcher.d.ts +18 -18
- package/lib/engine-components/ShadowCatcher.js +144 -144
- package/lib/engine-components/Skybox.d.ts +23 -23
- package/lib/engine-components/Skybox.js +287 -287
- package/lib/engine-components/SmoothFollow.d.ts +14 -14
- package/lib/engine-components/SmoothFollow.js +63 -63
- package/lib/engine-components/SpatialTrigger.d.ts +27 -27
- package/lib/engine-components/SpatialTrigger.js +144 -144
- package/lib/engine-components/SpectatorCamera.d.ts +45 -45
- package/lib/engine-components/SpectatorCamera.js +593 -593
- package/lib/engine-components/SpriteRenderer.d.ts +48 -48
- package/lib/engine-components/SpriteRenderer.js +257 -257
- package/lib/engine-components/SyncedCamera.d.ts +27 -27
- package/lib/engine-components/SyncedCamera.js +187 -187
- package/lib/engine-components/SyncedRoom.d.ts +24 -24
- package/lib/engine-components/SyncedRoom.js +162 -162
- package/lib/engine-components/SyncedTransform.d.ts +35 -35
- package/lib/engine-components/SyncedTransform.js +265 -265
- package/lib/engine-components/TestRunner.d.ts +13 -13
- package/lib/engine-components/TestRunner.js +99 -99
- package/lib/engine-components/TransformGizmo.d.ts +16 -16
- package/lib/engine-components/TransformGizmo.js +148 -148
- package/lib/engine-components/VideoPlayer.d.ts +86 -86
- package/lib/engine-components/VideoPlayer.js +792 -792
- package/lib/engine-components/Voip.d.ts +29 -29
- package/lib/engine-components/Voip.js +203 -203
- package/lib/engine-components/XRFlag.d.ts +33 -33
- package/lib/engine-components/XRFlag.js +128 -128
- package/lib/engine-components/api.d.ts +15 -15
- package/lib/engine-components/api.js +15 -15
- package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +10 -10
- package/lib/engine-components/avatar/AvatarBlink_Simple.js +75 -75
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +13 -13
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +74 -74
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +27 -27
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +119 -119
- package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +13 -13
- package/lib/engine-components/avatar/Avatar_MouthShapes.js +78 -78
- package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +8 -8
- package/lib/engine-components/avatar/Avatar_MustacheShake.js +28 -28
- package/lib/engine-components/codegen/components.d.ts +216 -216
- package/lib/engine-components/codegen/components.js +217 -217
- package/lib/engine-components/debug/LogStats.d.ts +5 -5
- package/lib/engine-components/debug/LogStats.js +18 -18
- package/lib/engine-components/export/gltf/GltfExport.d.ts +25 -25
- package/lib/engine-components/export/gltf/GltfExport.js +215 -215
- package/lib/engine-components/export/index.d.ts +1 -1
- package/lib/engine-components/export/index.js +1 -1
- package/lib/engine-components/export/usdz/Extension.d.ts +10 -10
- package/lib/engine-components/export/usdz/Extension.js +1 -1
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.d.ts +114 -114
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +1211 -1211
- package/lib/engine-components/export/usdz/USDZExporter.d.ts +59 -59
- package/lib/engine-components/export/usdz/USDZExporter.js +450 -450
- package/lib/engine-components/export/usdz/extensions/Animation.d.ts +69 -69
- package/lib/engine-components/export/usdz/extensions/Animation.js +650 -650
- package/lib/engine-components/export/usdz/extensions/DocumentExtension.d.ts +5 -5
- package/lib/engine-components/export/usdz/extensions/DocumentExtension.js +6 -6
- package/lib/engine-components/export/usdz/extensions/USDZText.d.ts +55 -55
- package/lib/engine-components/export/usdz/extensions/USDZText.js +246 -246
- package/lib/engine-components/export/usdz/extensions/USDZUI.d.ts +8 -8
- package/lib/engine-components/export/usdz/extensions/USDZUI.js +100 -100
- package/lib/engine-components/export/usdz/extensions/behavior/Actions.d.ts +30 -30
- package/lib/engine-components/export/usdz/extensions/behavior/Actions.js +88 -88
- package/lib/engine-components/export/usdz/extensions/behavior/AudioExtension.d.ts +9 -9
- package/lib/engine-components/export/usdz/extensions/behavior/AudioExtension.js +52 -52
- package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.d.ts +22 -22
- package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js +134 -134
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.d.ts +126 -126
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js +824 -824
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.d.ts +133 -133
- package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js +464 -464
- package/lib/engine-components/export/usdz/index.d.ts +3 -3
- package/lib/engine-components/export/usdz/index.js +2 -2
- package/lib/engine-components/export/usdz/utils/animationutils.d.ts +3 -3
- package/lib/engine-components/export/usdz/utils/animationutils.js +85 -85
- package/lib/engine-components/export/usdz/utils/quicklook.d.ts +2 -2
- package/lib/engine-components/export/usdz/utils/quicklook.js +35 -35
- package/lib/engine-components/export/usdz/utils/timeutils.d.ts +1 -1
- package/lib/engine-components/export/usdz/utils/timeutils.js +14 -14
- package/lib/engine-components/js-extensions/ExtensionUtils.d.ts +6 -6
- package/lib/engine-components/js-extensions/ExtensionUtils.js +65 -65
- package/lib/engine-components/js-extensions/Object3D.d.ts +2 -2
- package/lib/engine-components/js-extensions/Object3D.js +140 -140
- package/lib/engine-components/js-extensions/RGBAColor.d.ts +14 -14
- package/lib/engine-components/js-extensions/RGBAColor.js +49 -49
- package/lib/engine-components/js-extensions/index.d.ts +3 -3
- package/lib/engine-components/js-extensions/index.js +3 -3
- package/lib/engine-components/postprocessing/Effects/Antialiasing.d.ts +13 -13
- package/lib/engine-components/postprocessing/Effects/Antialiasing.js +45 -45
- package/lib/engine-components/postprocessing/Effects/Bloom.d.ts +12 -12
- package/lib/engine-components/postprocessing/Effects/Bloom.js +77 -77
- package/lib/engine-components/postprocessing/Effects/ChromaticAberration.d.ts +8 -8
- package/lib/engine-components/postprocessing/Effects/ChromaticAberration.js +38 -38
- package/lib/engine-components/postprocessing/Effects/ColorAdjustments.d.ts +12 -12
- package/lib/engine-components/postprocessing/Effects/ColorAdjustments.js +81 -81
- package/lib/engine-components/postprocessing/Effects/DepthOfField.d.ts +21 -21
- package/lib/engine-components/postprocessing/Effects/DepthOfField.js +97 -97
- package/lib/engine-components/postprocessing/Effects/Pixelation.d.ts +7 -7
- package/lib/engine-components/postprocessing/Effects/Pixelation.js +28 -28
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.d.ts +13 -13
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.js +86 -86
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.d.ts +24 -24
- package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.js +94 -94
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.d.ts +13 -13
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.js +62 -62
- package/lib/engine-components/postprocessing/Effects/Tonemapping.d.ts +16 -16
- package/lib/engine-components/postprocessing/Effects/Tonemapping.js +51 -51
- package/lib/engine-components/postprocessing/Effects/Vignette.d.ts +11 -11
- package/lib/engine-components/postprocessing/Effects/Vignette.js +56 -56
- package/lib/engine-components/postprocessing/PostProcessingEffect.d.ts +33 -33
- package/lib/engine-components/postprocessing/PostProcessingEffect.js +126 -126
- package/lib/engine-components/postprocessing/PostProcessingHandler.d.ts +22 -22
- package/lib/engine-components/postprocessing/PostProcessingHandler.js +201 -201
- package/lib/engine-components/postprocessing/Volume.d.ts +25 -25
- package/lib/engine-components/postprocessing/Volume.js +193 -193
- package/lib/engine-components/postprocessing/VolumeParameter.d.ts +22 -22
- package/lib/engine-components/postprocessing/VolumeParameter.js +80 -80
- package/lib/engine-components/postprocessing/VolumeProfile.d.ts +7 -7
- package/lib/engine-components/postprocessing/VolumeProfile.js +41 -41
- package/lib/engine-components/postprocessing/index.d.ts +4 -4
- package/lib/engine-components/postprocessing/index.js +4 -4
- package/lib/engine-components/timeline/PlayableDirector.d.ts +107 -107
- package/lib/engine-components/timeline/PlayableDirector.js +624 -624
- package/lib/engine-components/timeline/SignalAsset.d.ts +18 -18
- package/lib/engine-components/timeline/SignalAsset.js +124 -124
- package/lib/engine-components/timeline/TimelineModels.d.ts +88 -88
- package/lib/engine-components/timeline/TimelineModels.js +22 -22
- package/lib/engine-components/timeline/TimelineTracks.d.ts +90 -90
- package/lib/engine-components/timeline/TimelineTracks.js +825 -825
- package/lib/engine-components/timeline/index.d.ts +4 -4
- package/lib/engine-components/timeline/index.js +3 -3
- package/lib/engine-components/ui/BaseUIComponent.d.ts +31 -31
- package/lib/engine-components/ui/BaseUIComponent.js +161 -161
- package/lib/engine-components/ui/Button.d.ts +56 -56
- package/lib/engine-components/ui/Button.js +282 -282
- package/lib/engine-components/ui/Canvas.d.ts +67 -67
- package/lib/engine-components/ui/Canvas.js +382 -382
- package/lib/engine-components/ui/CanvasGroup.d.ts +15 -15
- package/lib/engine-components/ui/CanvasGroup.js +53 -53
- package/lib/engine-components/ui/EventSystem.d.ts +102 -102
- package/lib/engine-components/ui/EventSystem.js +641 -641
- package/lib/engine-components/ui/Graphic.d.ts +45 -45
- package/lib/engine-components/ui/Graphic.js +236 -236
- package/lib/engine-components/ui/Image.d.ts +27 -27
- package/lib/engine-components/ui/Image.js +107 -107
- package/lib/engine-components/ui/InputField.d.ts +34 -34
- package/lib/engine-components/ui/InputField.js +234 -234
- package/lib/engine-components/ui/Interfaces.d.ts +38 -38
- package/lib/engine-components/ui/Interfaces.js +12 -12
- package/lib/engine-components/ui/Layout.d.ts +72 -72
- package/lib/engine-components/ui/Layout.js +318 -318
- package/lib/engine-components/ui/Outline.d.ts +7 -7
- package/lib/engine-components/ui/Outline.js +20 -20
- package/lib/engine-components/ui/PointerEvents.d.ts +64 -64
- package/lib/engine-components/ui/PointerEvents.js +68 -68
- package/lib/engine-components/ui/RaycastUtils.d.ts +11 -11
- package/lib/engine-components/ui/RaycastUtils.js +67 -67
- package/lib/engine-components/ui/Raycaster.d.ts +18 -18
- package/lib/engine-components/ui/Raycaster.js +69 -69
- package/lib/engine-components/ui/RectTransform.d.ts +61 -61
- package/lib/engine-components/ui/RectTransform.js +343 -343
- package/lib/engine-components/ui/SpatialHtml.d.ts +6 -6
- package/lib/engine-components/ui/SpatialHtml.js +57 -57
- package/lib/engine-components/ui/Text.d.ts +74 -74
- package/lib/engine-components/ui/Text.js +534 -534
- package/lib/engine-components/ui/Utils.d.ts +23 -23
- package/lib/engine-components/ui/Utils.js +90 -90
- package/lib/engine-components/ui/index.d.ts +1 -1
- package/lib/engine-components/ui/index.js +1 -1
- package/lib/engine-components/utils/LookAt.d.ts +13 -13
- package/lib/engine-components/utils/LookAt.js +59 -59
- package/lib/engine-components/utils/OpenURL.d.ts +21 -21
- package/lib/engine-components/utils/OpenURL.js +124 -124
- package/lib/engine-components/webxr/WebARCameraBackground.d.ts +19 -19
- package/lib/engine-components/webxr/WebARCameraBackground.js +193 -193
- package/lib/engine-components/webxr/WebARSessionRoot.d.ts +38 -38
- package/lib/engine-components/webxr/WebARSessionRoot.js +407 -407
- package/lib/engine-components/webxr/WebXR.d.ts +110 -110
- package/lib/engine-components/webxr/WebXR.js +672 -672
- package/lib/engine-components/webxr/WebXRAvatar.d.ts +61 -61
- package/lib/engine-components/webxr/WebXRAvatar.js +289 -289
- package/lib/engine-components/webxr/WebXRController.d.ts +154 -154
- package/lib/engine-components/webxr/WebXRController.js +1028 -1028
- package/lib/engine-components/webxr/WebXRGrabRendering.d.ts +42 -42
- package/lib/engine-components/webxr/WebXRGrabRendering.js +137 -137
- package/lib/engine-components/webxr/WebXRImageTracking.d.ts +49 -49
- package/lib/engine-components/webxr/WebXRImageTracking.js +336 -336
- package/lib/engine-components/webxr/WebXRPlaneTracking.d.ts +49 -49
- package/lib/engine-components/webxr/WebXRPlaneTracking.js +372 -372
- package/lib/engine-components/webxr/WebXRRig.d.ts +4 -4
- package/lib/engine-components/webxr/WebXRRig.js +19 -19
- package/lib/engine-components/webxr/WebXRSync.d.ts +54 -54
- package/lib/engine-components/webxr/WebXRSync.js +410 -410
- package/lib/engine-components/webxr/index.d.ts +4 -4
- package/lib/engine-components/webxr/index.js +4 -4
- package/lib/engine-components-experimental/Presentation.d.ts +6 -6
- package/lib/engine-components-experimental/Presentation.js +9 -9
- package/lib/engine-components-experimental/api.d.ts +1 -1
- package/lib/engine-components-experimental/api.js +1 -1
- package/lib/engine-components-experimental/networking/PlayerSync.d.ts +50 -50
- package/lib/engine-components-experimental/networking/PlayerSync.js +200 -200
- package/lib/engine-schemes/api.d.ts +1 -1
- package/lib/engine-schemes/api.js +1 -1
- package/lib/engine-schemes/schemes.d.ts +7 -7
- package/lib/engine-schemes/schemes.js +19 -19
- package/lib/engine-schemes/synced-camera-model.d.ts +25 -25
- package/lib/engine-schemes/synced-camera-model.js +67 -67
- package/lib/engine-schemes/synced-transform-model.d.ts +31 -31
- package/lib/engine-schemes/synced-transform-model.js +66 -66
- package/lib/engine-schemes/transform.d.ts +12 -12
- package/lib/engine-schemes/transform.js +39 -39
- package/lib/engine-schemes/vec3.d.ts +11 -11
- package/lib/engine-schemes/vec3.js +29 -29
- package/lib/engine-schemes/vec4.d.ts +12 -12
- package/lib/engine-schemes/vec4.js +33 -33
- package/lib/engine-schemes/vr-user-state-buffer.d.ts +36 -36
- package/lib/engine-schemes/vr-user-state-buffer.js +103 -103
- package/lib/include/three/ARButton.d.ts +3 -3
- package/lib/include/three/ARButton.js +151 -151
- package/lib/include/three/EXT_mesh_gpu_instancing_exporter.d.ts +6 -6
- package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js +45 -45
- package/lib/include/three/VRButton.d.ts +5 -5
- package/lib/include/three/VRButton.js +118 -118
- package/lib/needle-engine.d.ts +6 -6
- package/lib/needle-engine.js +49 -49
- package/package.json +1 -1
- package/plugins/common/config.cjs +14 -14
- package/plugins/common/config.js +19 -19
- package/plugins/common/generator.js +10 -10
- package/plugins/common/license.cjs +30 -30
- package/plugins/common/version.js +11 -11
- package/plugins/next/license.cjs +4 -4
- package/plugins/next/next.js +70 -70
- package/plugins/types/index.d.ts +1 -1
- package/plugins/types/needleConfig.d.ts +21 -21
- package/plugins/types/userconfig.d.ts +42 -42
- package/plugins/vite/alias.js +70 -70
- package/plugins/vite/build.js +19 -19
- package/plugins/vite/config.js +73 -73
- package/plugins/vite/copyfiles.js +134 -134
- package/plugins/vite/defines.js +45 -45
- package/plugins/vite/dependency-watcher.js +224 -224
- package/plugins/vite/drop-client.js +76 -76
- package/plugins/vite/drop.js +82 -82
- package/plugins/vite/editor-connection.js +121 -121
- package/plugins/vite/facebook-instant-games.js +99 -99
- package/plugins/vite/gzip.js +5 -5
- package/plugins/vite/imports-logger.js +143 -143
- package/plugins/vite/index.js +81 -81
- package/plugins/vite/license.js +42 -42
- package/plugins/vite/meta.js +149 -149
- package/plugins/vite/peer.js +31 -31
- package/plugins/vite/poster-client.js +59 -59
- package/plugins/vite/poster.js +73 -73
- package/plugins/vite/reload-client.js +15 -15
- package/plugins/vite/reload.js +363 -363
- package/plugins/vite/transform-codegen.js +55 -55
- package/plugins/vite/vite-4.4-hack.js +31 -31
- package/src/engine/api.ts +54 -54
- package/src/engine/assets/index.ts +4 -4
- package/src/engine/codegen/register_types.ts +441 -441
- package/src/engine/debug/debug.ts +29 -29
- package/src/engine/debug/debug_console.ts +213 -213
- package/src/engine/debug/debug_overlay.ts +283 -283
- package/src/engine/engine.ts +13 -13
- package/src/engine/engine_addressables.ts +494 -494
- package/src/engine/engine_application.ts +53 -53
- package/src/engine/engine_assetdatabase.ts +383 -383
- package/src/engine/engine_camera.ts +32 -32
- package/src/engine/engine_components.ts +266 -266
- package/src/engine/engine_components_internal.ts +42 -42
- package/src/engine/engine_constants.ts +42 -42
- package/src/engine/engine_context.ts +1386 -1386
- package/src/engine/engine_context_registry.ts +103 -103
- package/src/engine/engine_coroutine.ts +24 -24
- package/src/engine/engine_create_objects.ts +39 -39
- package/src/engine/engine_default_parameters.ts +3 -3
- package/src/engine/engine_editor-sync.ts +29 -29
- package/src/engine/engine_element.ts +592 -592
- package/src/engine/engine_element_attributes.ts +61 -61
- package/src/engine/engine_element_extras.ts +16 -16
- package/src/engine/engine_element_loading.ts +341 -341
- package/src/engine/engine_element_overlay.ts +160 -160
- package/src/engine/engine_fileloader.js +8 -8
- package/src/engine/engine_gameobject.ts +621 -621
- package/src/engine/engine_generic_utils.js +13 -13
- package/src/engine/engine_gizmos.ts +321 -321
- package/src/engine/engine_gltf.ts +30 -30
- package/src/engine/engine_gltf_builtin_components.ts +350 -350
- package/src/engine/engine_hot_reload.ts +196 -196
- package/src/engine/engine_input.ts +879 -879
- package/src/engine/engine_input_utils.ts +23 -23
- package/src/engine/engine_instancing.ts +42 -42
- package/src/engine/engine_license.ts +413 -413
- package/src/engine/engine_lifecycle_api.ts +29 -29
- package/src/engine/engine_lifecycle_functions_internal.ts +36 -36
- package/src/engine/engine_lightdata.ts +113 -113
- package/src/engine/engine_loaders.ts +77 -77
- package/src/engine/engine_mainloop_utils.ts +431 -431
- package/src/engine/engine_math.ts +174 -174
- package/src/engine/engine_networking.ts +742 -742
- package/src/engine/engine_networking_auto.ts +373 -373
- package/src/engine/engine_networking_files.ts +206 -206
- package/src/engine/engine_networking_files_default_components.ts +54 -54
- package/src/engine/engine_networking_instantiate.ts +362 -362
- package/src/engine/engine_networking_peer.ts +158 -158
- package/src/engine/engine_networking_streams.ts +489 -489
- package/src/engine/engine_networking_types.ts +18 -18
- package/src/engine/engine_networking_utils.ts +23 -23
- package/src/engine/engine_networking_websocket.ts +2 -2
- package/src/engine/engine_patcher.ts +199 -199
- package/src/engine/engine_physics.ts +287 -287
- package/src/engine/engine_physics.types.ts +43 -43
- package/src/engine/engine_physics_rapier.ts +1385 -1385
- package/src/engine/engine_playerview.ts +79 -79
- package/src/engine/engine_scenelighting.ts +313 -313
- package/src/engine/engine_scenetools.ts +242 -242
- package/src/engine/engine_serialization.ts +6 -6
- package/src/engine/engine_serialization_builtin_serializer.ts +415 -415
- package/src/engine/engine_serialization_core.ts +680 -680
- package/src/engine/engine_serialization_decorator.ts +68 -68
- package/src/engine/engine_setup.ts +1 -1
- package/src/engine/engine_shaders.ts +242 -242
- package/src/engine/engine_shims.ts +28 -28
- package/src/engine/engine_texture.ts +70 -70
- package/src/engine/engine_three_utils.ts +382 -382
- package/src/engine/engine_time.ts +55 -55
- package/src/engine/engine_types.ts +489 -489
- package/src/engine/engine_typestore.ts +41 -41
- package/src/engine/engine_util_decorator.ts +134 -134
- package/src/engine/engine_utils.ts +605 -605
- package/src/engine/engine_utils_screenshot.ts +84 -84
- package/src/engine/engine_web_api.ts +119 -119
- package/src/engine/extensions/EXT_texture_exr.ts +49 -49
- package/src/engine/extensions/NEEDLE_animator_controller_model.ts +193 -193
- package/src/engine/extensions/NEEDLE_components.ts +250 -250
- package/src/engine/extensions/NEEDLE_gameobject_data.ts +82 -82
- package/src/engine/extensions/NEEDLE_lighting_settings.ts +210 -210
- package/src/engine/extensions/NEEDLE_lightmaps.ts +130 -130
- package/src/engine/extensions/NEEDLE_persistent_assets.ts +75 -75
- package/src/engine/extensions/NEEDLE_progressive.ts +412 -412
- package/src/engine/extensions/NEEDLE_render_objects.ts +209 -209
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +618 -618
- package/src/engine/extensions/extension_resolver.ts +4 -4
- package/src/engine/extensions/extension_utils.ts +149 -149
- package/src/engine/extensions/extensions.ts +118 -118
- package/src/engine/extensions/index.ts +4 -4
- package/src/engine/extensions/usage_tracker.ts +95 -95
- package/src/engine/js-extensions/Camera.ts +34 -34
- package/src/engine/js-extensions/Layers.ts +19 -19
- package/src/engine/js-extensions/index.ts +1 -1
- package/src/engine/shaders/shaderData.ts +67 -67
- package/src/engine/tests/test_utils.ts +63 -63
- package/src/engine-components/AlignmentConstraint.ts +35 -35
- package/src/engine-components/Animation.ts +345 -345
- package/src/engine-components/AnimationCurve.ts +83 -83
- package/src/engine-components/AnimationUtils.ts +117 -117
- package/src/engine-components/Animator.ts +243 -243
- package/src/engine-components/AnimatorController.ts +1020 -1020
- package/src/engine-components/AudioListener.ts +32 -32
- package/src/engine-components/AudioSource.ts +419 -419
- package/src/engine-components/AvatarLoader.ts +204 -204
- package/src/engine-components/AxesHelper.ts +33 -33
- package/src/engine-components/BasicIKConstraint.ts +53 -53
- package/src/engine-components/BoxCollider.ts +1 -1
- package/src/engine-components/BoxHelperComponent.ts +100 -100
- package/src/engine-components/Camera.ts +454 -454
- package/src/engine-components/CameraUtils.ts +89 -89
- package/src/engine-components/CharacterController.ts +243 -243
- package/src/engine-components/Collider.ts +160 -160
- package/src/engine-components/Component.ts +670 -670
- package/src/engine-components/ContactShadows.ts +265 -265
- package/src/engine-components/DeleteBox.ts +35 -35
- package/src/engine-components/DeviceFlag.ts +42 -42
- package/src/engine-components/DragControls.ts +574 -574
- package/src/engine-components/DropListener.ts +112 -112
- package/src/engine-components/Duplicatable.ts +146 -146
- package/src/engine-components/EventList.ts +125 -125
- package/src/engine-components/EventTrigger.ts +47 -47
- package/src/engine-components/EventType.ts +87 -87
- package/src/engine-components/FlyControls.ts +31 -31
- package/src/engine-components/Fog.ts +59 -59
- package/src/engine-components/Gizmos.ts +52 -52
- package/src/engine-components/GridHelper.ts +40 -40
- package/src/engine-components/GroundProjection.ts +97 -97
- package/src/engine-components/Interactable.ts +18 -18
- package/src/engine-components/Joints.ts +51 -51
- package/src/engine-components/LODGroup.ts +145 -145
- package/src/engine-components/Light.ts +493 -493
- package/src/engine-components/LookAtConstraint.ts +11 -11
- package/src/engine-components/NestedGltf.ts +70 -70
- package/src/engine-components/Networking.ts +72 -72
- package/src/engine-components/OffsetConstraint.ts +59 -59
- package/src/engine-components/OrbitControls.ts +653 -653
- package/src/engine-components/ParticleSystem.ts +1192 -1192
- package/src/engine-components/ParticleSystemModules.ts +1481 -1481
- package/src/engine-components/ParticleSystemSubEmitter.ts +110 -110
- package/src/engine-components/PlayerColor.ts +93 -93
- package/src/engine-components/ReflectionProbe.ts +192 -192
- package/src/engine-components/Renderer.ts +1125 -1125
- package/src/engine-components/RendererLightmap.ts +145 -145
- package/src/engine-components/RigidBody.ts +453 -453
- package/src/engine-components/SceneSwitcher.ts +594 -594
- package/src/engine-components/ScreenCapture.ts +437 -437
- package/src/engine-components/ShadowCatcher.ts +149 -149
- package/src/engine-components/Skybox.ts +281 -281
- package/src/engine-components/SmoothFollow.ts +57 -57
- package/src/engine-components/SpatialTrigger.ts +142 -142
- package/src/engine-components/SpectatorCamera.ts +675 -675
- package/src/engine-components/SphereCollider.ts +1 -1
- package/src/engine-components/SpriteRenderer.ts +244 -244
- package/src/engine-components/SyncedCamera.ts +208 -208
- package/src/engine-components/SyncedRoom.ts +166 -166
- package/src/engine-components/SyncedTransform.ts +336 -336
- package/src/engine-components/TestRunner.ts +114 -114
- package/src/engine-components/TransformGizmo.ts +157 -157
- package/src/engine-components/VideoPlayer.ts +831 -831
- package/src/engine-components/Voip.ts +214 -214
- package/src/engine-components/XRFlag.ts +138 -138
- package/src/engine-components/api.ts +22 -22
- package/src/engine-components/avatar/AvatarBlink_Simple.ts +67 -67
- package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +68 -68
- package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +136 -136
- package/src/engine-components/avatar/Avatar_MouthShapes.ts +81 -81
- package/src/engine-components/avatar/Avatar_MustacheShake.ts +28 -28
- package/src/engine-components/codegen/components.ts +216 -216
- package/src/engine-components/debug/LogStats.ts +21 -21
- package/src/engine-components/export/gltf/GltfExport.ts +231 -231
- package/src/engine-components/export/usdz/Extension.ts +11 -11
- package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +1773 -1773
- package/src/engine-components/export/usdz/USDZExporter.ts +477 -477
- package/src/engine-components/export/usdz/extensions/Animation.ts +774 -774
- package/src/engine-components/export/usdz/extensions/DocumentExtension.ts +9 -9
- package/src/engine-components/export/usdz/extensions/USDZText.ts +287 -287
- package/src/engine-components/export/usdz/extensions/USDZUI.ts +119 -119
- package/src/engine-components/export/usdz/extensions/behavior/Actions.ts +98 -98
- package/src/engine-components/export/usdz/extensions/behavior/AudioExtension.ts +67 -67
- package/src/engine-components/export/usdz/extensions/behavior/Behaviour.ts +202 -202
- package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +963 -963
- package/src/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.ts +517 -517
- package/src/engine-components/export/usdz/index.ts +2 -2
- package/src/engine-components/export/usdz/utils/animationutils.ts +100 -100
- package/src/engine-components/export/usdz/utils/quicklook.ts +42 -42
- package/src/engine-components/export/usdz/utils/timeutils.ts +19 -19
- package/src/engine-components/js-extensions/ExtensionUtils.ts +81 -81
- package/src/engine-components/js-extensions/Object3D.ts +181 -181
- package/src/engine-components/js-extensions/RGBAColor.ts +54 -54
- package/src/engine-components/js-extensions/Vector.ts +16 -16
- package/src/engine-components/js-extensions/index.ts +2 -2
- package/src/engine-components/postprocessing/Effects/Antialiasing.ts +51 -51
- package/src/engine-components/postprocessing/Effects/Bloom.ts +76 -76
- package/src/engine-components/postprocessing/Effects/ChromaticAberration.ts +35 -35
- package/src/engine-components/postprocessing/Effects/ColorAdjustments.ts +96 -96
- package/src/engine-components/postprocessing/Effects/DepthOfField.ts +93 -93
- package/src/engine-components/postprocessing/Effects/Pixelation.ts +26 -26
- package/src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.ts +84 -84
- package/src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.ts +98 -98
- package/src/engine-components/postprocessing/Effects/TiltShiftEffect.ts +55 -55
- package/src/engine-components/postprocessing/Effects/Tonemapping.ts +54 -54
- package/src/engine-components/postprocessing/Effects/Vignette.ts +54 -54
- package/src/engine-components/postprocessing/PostProcessingEffect.ts +148 -148
- package/src/engine-components/postprocessing/PostProcessingHandler.ts +232 -232
- package/src/engine-components/postprocessing/Volume.ts +216 -216
- package/src/engine-components/postprocessing/VolumeParameter.ts +92 -92
- package/src/engine-components/postprocessing/VolumeProfile.ts +40 -40
- package/src/engine-components/postprocessing/index.ts +3 -3
- package/src/engine-components/timeline/PlayableDirector.ts +666 -666
- package/src/engine-components/timeline/SignalAsset.ts +138 -138
- package/src/engine-components/timeline/TimelineModels.ts +93 -93
- package/src/engine-components/timeline/TimelineTracks.ts +906 -906
- package/src/engine-components/timeline/index.ts +3 -3
- package/src/engine-components/ui/BaseUIComponent.ts +195 -195
- package/src/engine-components/ui/Button.ts +283 -283
- package/src/engine-components/ui/Canvas.ts +390 -390
- package/src/engine-components/ui/CanvasGroup.ts +49 -49
- package/src/engine-components/ui/EventSystem.ts +736 -736
- package/src/engine-components/ui/Graphic.ts +255 -255
- package/src/engine-components/ui/Image.ts +102 -102
- package/src/engine-components/ui/InputField.ts +290 -290
- package/src/engine-components/ui/Interfaces.ts +57 -57
- package/src/engine-components/ui/Layout.ts +322 -322
- package/src/engine-components/ui/Outline.ts +12 -12
- package/src/engine-components/ui/PointerEvents.ts +118 -118
- package/src/engine-components/ui/RaycastUtils.ts +68 -68
- package/src/engine-components/ui/Raycaster.ts +73 -73
- package/src/engine-components/ui/RectTransform.ts +364 -364
- package/src/engine-components/ui/SpatialHtml.ts +63 -63
- package/src/engine-components/ui/Text.ts +572 -572
- package/src/engine-components/ui/Utils.ts +110 -110
- package/src/engine-components/utils/LookAt.ts +65 -65
- package/src/engine-components/utils/OpenURL.ts +118 -118
- package/src/engine-components/webxr/WebARCameraBackground.ts +224 -224
- package/src/engine-components/webxr/WebARSessionRoot.ts +446 -446
- package/src/engine-components/webxr/WebXR.ts +761 -761
- package/src/engine-components/webxr/WebXRAvatar.ts +356 -356
- package/src/engine-components/webxr/WebXRController.ts +1168 -1168
- package/src/engine-components/webxr/WebXRGrabRendering.ts +150 -150
- package/src/engine-components/webxr/WebXRImageTracking.ts +371 -371
- package/src/engine-components/webxr/WebXRPlaneTracking.ts +429 -429
- package/src/engine-components/webxr/WebXRRig.ts +21 -21
- package/src/engine-components/webxr/WebXRSync.ts +463 -463
- package/src/engine-components/webxr/index.ts +3 -3
- package/src/engine-components-experimental/Presentation.ts +12 -12
- package/src/engine-components-experimental/networking/PlayerSync.ts +217 -217
- package/src/engine-schemes/COMPILE_SCHEMES.bat +3 -3
- package/src/engine-schemes/COMPILE_TS.bat +11 -11
- package/src/engine-schemes/schemes.ts +27 -27
- package/src/engine-schemes/synced-camera-model.ts +92 -92
- package/src/engine-schemes/synced-transform-model.ts +90 -90
- package/src/engine-schemes/syncedCamera.fbs +10 -10
- package/src/engine-schemes/transform.ts +50 -50
- package/src/engine-schemes/transforms.fbs +25 -25
- package/src/engine-schemes/vec.fbs +19 -19
- package/src/engine-schemes/vec2.ts +33 -33
- package/src/engine-schemes/vec3.ts +38 -38
- package/src/engine-schemes/vec4.ts +43 -43
- package/src/engine-schemes/vr-user-state-buffer.ts +138 -138
- package/src/engine-schemes/vrUserStateBuffer.fbs +16 -16
- package/src/include/draco/draco_decoder.js +34 -34
- package/src/include/draco/draco_wasm_wrapper.js +117 -117
- package/src/include/ktx2/basis_transcoder.js +21 -21
- package/src/include/needle/arial-msdf.json +1471 -1471
- package/src/include/three/ARButton.js +231 -231
- package/src/include/three/DragControls.js +231 -231
- package/src/include/three/EXT_mesh_gpu_instancing_exporter.js +66 -66
- package/src/include/three/VRButton.js +194 -194
- package/src/needle-engine.ts +55 -55
- package/src/engine/dist/api.js +0 -73
- package/src/engine/dist/api.js.meta +0 -7
- package/src/engine/dist/engine_networking_streams.js +0 -474
- package/src/engine/dist/engine_networking_streams.js.meta +0 -7
- package/src/engine-schemes/dist/api.js +0 -17
- package/src/engine-schemes/dist/api.js.meta +0 -7
- package/src/engine-schemes/dist/schemes.js +0 -25
- package/src/engine-schemes/dist/schemes.js.meta +0 -7
- package/src/engine-schemes/dist/synced-camera-model.js +0 -74
- package/src/engine-schemes/dist/synced-camera-model.js.meta +0 -7
- package/src/engine-schemes/dist/synced-transform-model.js +0 -73
- package/src/engine-schemes/dist/synced-transform-model.js.meta +0 -7
- package/src/engine-schemes/dist/transform.js +0 -46
- package/src/engine-schemes/dist/transform.js.meta +0 -7
- package/src/engine-schemes/dist/vec2.js +0 -32
- package/src/engine-schemes/dist/vec2.js.meta +0 -7
- package/src/engine-schemes/dist/vec3.js +0 -36
- package/src/engine-schemes/dist/vec3.js.meta +0 -7
- package/src/engine-schemes/dist/vec4.js +0 -40
- package/src/engine-schemes/dist/vec4.js.meta +0 -7
- package/src/engine-schemes/dist/vr-user-state-buffer.js +0 -110
- package/src/engine-schemes/dist/vr-user-state-buffer.js.meta +0 -7
- package/src/engine-schemes/flatc.exe +0 -0
|
@@ -1,762 +1,762 @@
|
|
|
1
|
-
import { Color, Euler, EventDispatcher, Group, Matrix4, Mesh, MeshBasicMaterial, Object3D, Quaternion, RingGeometry, Texture, Vector3, type WebXRArrayCamera } from 'three';
|
|
2
|
-
import { ARButton } from '../../include/three/ARButton.js';
|
|
3
|
-
import { VRButton } from '../../include/three/VRButton.js';
|
|
4
|
-
|
|
5
|
-
import { AssetReference } from "../../engine/engine_addressables.js";
|
|
6
|
-
import { serializable } from "../../engine/engine_serialization_decorator.js";
|
|
7
|
-
import { XRSessionMode } from "../../engine/engine_setup.js";
|
|
8
|
-
import { getWorldPosition, getWorldQuaternion, setWorldPosition, setWorldQuaternion } from "../../engine/engine_three_utils.js";
|
|
9
|
-
import type { INeedleEngineComponent } from "../../engine/engine_types.js";
|
|
10
|
-
import { getParam, isMozillaXR, isQuest, setOrAddParamsToUrl } from "../../engine/engine_utils.js";
|
|
11
|
-
|
|
12
|
-
import { Behaviour, GameObject } from "../Component.js";
|
|
13
|
-
import { noVoip } from "../Voip.js";
|
|
14
|
-
import { WebARSessionRoot } from "./WebARSessionRoot.js";
|
|
15
|
-
import { ControllerType, WebXRController } from "./WebXRController.js";
|
|
16
|
-
import { XRRig } from "./WebXRRig.js";
|
|
17
|
-
import { WebXRSync } from "./WebXRSync.js";
|
|
18
|
-
import { XRState, XRStateFlag } from "../XRFlag.js";
|
|
19
|
-
import { showBalloonWarning } from '../../engine/debug/index.js';
|
|
20
|
-
import { isDestroyed } from '../../engine/engine_gameobject.js';
|
|
21
|
-
|
|
22
|
-
const debugWebXR = getParam("debugwebxr");
|
|
23
|
-
|
|
24
|
-
export async function detectARSupport() {
|
|
25
|
-
if (isMozillaXR()) return true;
|
|
26
|
-
if ("xr" in navigator) {
|
|
27
|
-
//@ts-ignore
|
|
28
|
-
return (await navigator["xr"].isSessionSupported('immersive-ar')) === true;
|
|
29
|
-
}
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
export async function detectVRSupport() {
|
|
33
|
-
if ("xr" in navigator) {
|
|
34
|
-
//@ts-ignore
|
|
35
|
-
return (await navigator["xr"].isSessionSupported('immersive-vr')) === true;
|
|
36
|
-
}
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
let arSupported = false;
|
|
41
|
-
let vrSupported = false;
|
|
42
|
-
detectARSupport().then(res => arSupported = res);
|
|
43
|
-
detectVRSupport().then(res => vrSupported = res);
|
|
44
|
-
|
|
45
|
-
// import TeleportVR from "teleportvr.js";
|
|
46
|
-
|
|
47
|
-
export enum WebXREvent {
|
|
48
|
-
XRStarted = "xrStarted",
|
|
49
|
-
XRStopped = "xrStopped",
|
|
50
|
-
XRUpdate = "xrUpdate",
|
|
51
|
-
RequestVRSession = "requestVRSession",
|
|
52
|
-
ModifyAROptions = "modify-ar-options",
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export declare type CreateButtonOptions = {
|
|
56
|
-
registerClick: boolean
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export class WebXR extends Behaviour {
|
|
60
|
-
|
|
61
|
-
@serializable()
|
|
62
|
-
enableVR = true;
|
|
63
|
-
@serializable()
|
|
64
|
-
enableAR = true;
|
|
65
|
-
|
|
66
|
-
@serializable(AssetReference)
|
|
67
|
-
defaultAvatar?: AssetReference;
|
|
68
|
-
@serializable()
|
|
69
|
-
handModelPath: string = "";
|
|
70
|
-
|
|
71
|
-
@serializable()
|
|
72
|
-
createVRButton: boolean = true;
|
|
73
|
-
@serializable()
|
|
74
|
-
createARButton: boolean = true;
|
|
75
|
-
|
|
76
|
-
private static _isInXr: boolean = false;
|
|
77
|
-
private static events: EventDispatcher = new EventDispatcher();
|
|
78
|
-
|
|
79
|
-
public static get IsInWebXR(): boolean { return this._isInXr; }
|
|
80
|
-
public static get XRSupported(): boolean { return 'xr' in navigator && (arSupported || vrSupported); }
|
|
81
|
-
public static get IsARSupported(): boolean { return arSupported; }
|
|
82
|
-
public static get IsVRSupported(): boolean { return vrSupported; }
|
|
83
|
-
|
|
84
|
-
private static _optionalFeatures_VR: string[] = ['local-floor', 'bounded-floor', 'hand-tracking', 'high-fixed-foveation-level', 'layers'];
|
|
85
|
-
private static _optionalFeatures_AR: string[] = ['anchors', 'local-floor', 'hand-tracking', 'layers'];
|
|
86
|
-
public static get OptionalFeatures_VR(): string[] { return this._optionalFeatures_VR; }
|
|
87
|
-
public static get OptionalFeatures_AR(): string[] { return this._optionalFeatures_AR; }
|
|
88
|
-
|
|
89
|
-
public static addEventListener(type: string, listener: any): any {
|
|
90
|
-
this.events.addEventListener(type, listener);
|
|
91
|
-
return listener;
|
|
92
|
-
}
|
|
93
|
-
public static removeEventListener(type: string, listener: any): any {
|
|
94
|
-
this.events.removeEventListener(type, listener);
|
|
95
|
-
return listener;
|
|
96
|
-
}
|
|
97
|
-
private static dispatchEvent(type: string, event: any): void {
|
|
98
|
-
this.events.dispatchEvent({ type, detail: event });
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
public static createVRButton(webXR: WebXR, opts?: CreateButtonOptions): HTMLButtonElement | HTMLAnchorElement {
|
|
102
|
-
if (!WebXR.XRSupported) {
|
|
103
|
-
console.warn("WebXR is not supported on this device");
|
|
104
|
-
}
|
|
105
|
-
else
|
|
106
|
-
webXR.__internalAwake();
|
|
107
|
-
const options = { optionalFeatures: WebXR.OptionalFeatures_VR };
|
|
108
|
-
const vrButton = VRButton.createButton(webXR.context.renderer, options);
|
|
109
|
-
vrButton.classList.add('webxr-ar-button');
|
|
110
|
-
vrButton.classList.add('webxr-button');
|
|
111
|
-
this.resetButtonStyles(vrButton);
|
|
112
|
-
// if (this.enableAR) vrButton.style.marginLeft = "60px";
|
|
113
|
-
if (opts?.registerClick ?? true)
|
|
114
|
-
vrButton.addEventListener('click', webXR.onClickedVRButton.bind(webXR));
|
|
115
|
-
return vrButton;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
public static createARButton(webXR: WebXR, opts?: CreateButtonOptions): HTMLButtonElement | HTMLAnchorElement {
|
|
119
|
-
webXR.__internalAwake();
|
|
120
|
-
const domOverlayRoot = webXR.webAR?.getAROverlayContainer();
|
|
121
|
-
const options: any = { optionalFeatures: [...this.OptionalFeatures_AR] };
|
|
122
|
-
if (domOverlayRoot) {
|
|
123
|
-
options.domOverlay = { root: domOverlayRoot };
|
|
124
|
-
options.optionalFeatures.push('dom-overlay')
|
|
125
|
-
options.optionalFeatures.push('hit-test');
|
|
126
|
-
options.optionalFeatures.push('anchors');
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
console.warn("No dom overlay root found, HTML overlays on top of screen-based AR will not work.");
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const arButton = ARButton.createButton(webXR.context.renderer, options, this.onModifyAROptions.bind(this));
|
|
133
|
-
arButton.classList.add('webxr-ar-button');
|
|
134
|
-
arButton.classList.add('webxr-button');
|
|
135
|
-
WebXR.resetButtonStyles(arButton);
|
|
136
|
-
if (opts?.registerClick ?? true)
|
|
137
|
-
arButton.addEventListener('click', webXR.onClickedARButton.bind(webXR));
|
|
138
|
-
return arButton;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
private static onModifyAROptions(options) {
|
|
142
|
-
WebXR.dispatchEvent(WebXREvent.ModifyAROptions, options);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
public static resetButtonStyles(button) {
|
|
146
|
-
if (!button) return;
|
|
147
|
-
button.style.position = "";
|
|
148
|
-
button.style.bottom = "";
|
|
149
|
-
button.style.left = "";
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
public endSession() {
|
|
153
|
-
const session = this.context.renderer.xr.getSession();
|
|
154
|
-
if (session) session.end();
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
public get Rig(): Object3D {
|
|
158
|
-
this.ensureRig();
|
|
159
|
-
return this.rig;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
private controllers: WebXRController[] = [];
|
|
164
|
-
public get Controllers(): WebXRController[] {
|
|
165
|
-
return this.controllers;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
public get LeftController(): WebXRController | null {
|
|
169
|
-
if (this.controllers.length > 0 && this.controllers[0].input?.handedness === "left") return this.controllers[0];
|
|
170
|
-
if (this.controllers.length > 1 && this.controllers[1].input?.handedness === "left") return this.controllers[1];
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
public get RightController(): WebXRController | null {
|
|
175
|
-
if (this.controllers.length > 0 && this.controllers[0].input?.handedness === "right") return this.controllers[0];
|
|
176
|
-
if (this.controllers.length > 1 && this.controllers[1].input?.handedness === "right") return this.controllers[1];
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
public get ARButton(): HTMLButtonElement | undefined {
|
|
181
|
-
return this._arButton;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
public get VRButton(): HTMLButtonElement | undefined {
|
|
185
|
-
return this._vrButton;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
public get IsInVR() { return this._isInVR; }
|
|
189
|
-
public get IsInAR() { return this._isInAR; }
|
|
190
|
-
|
|
191
|
-
/** When enabled */
|
|
192
|
-
allowARPlacementReticle: boolean = true;
|
|
193
|
-
|
|
194
|
-
private rig!: Object3D;
|
|
195
|
-
private isInit: boolean = false;
|
|
196
|
-
|
|
197
|
-
private _requestedAR: boolean = false;
|
|
198
|
-
private _requestedVR: boolean = false;
|
|
199
|
-
private _isInAR: boolean = false;
|
|
200
|
-
private _isInVR: boolean = false;
|
|
201
|
-
|
|
202
|
-
private _arButton?: HTMLButtonElement;
|
|
203
|
-
private _vrButton?: HTMLButtonElement;
|
|
204
|
-
|
|
205
|
-
private webAR: WebAR | null = null;
|
|
206
|
-
|
|
207
|
-
awake(): void {
|
|
208
|
-
// as the webxr component is most of the times currently loaded as part of the scene
|
|
209
|
-
// and not part of the glTF directly and thus does not go through the whole serialization process currently
|
|
210
|
-
// we need to to manuall make sure it is of the correct type here
|
|
211
|
-
if (this.defaultAvatar) {
|
|
212
|
-
if (typeof (this.defaultAvatar) === "string") {
|
|
213
|
-
this.defaultAvatar = AssetReference.getOrCreate(this.sourceId ?? "/", this.defaultAvatar, this.context);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
if (!GameObject.findObjectOfType(WebXRSync, this.context)) {
|
|
217
|
-
const sync = GameObject.addNewComponent(this.gameObject, WebXRSync, false) as WebXRSync;
|
|
218
|
-
sync.webXR = this;
|
|
219
|
-
}
|
|
220
|
-
this.webAR = new WebAR(this);
|
|
221
|
-
|
|
222
|
-
if (location.protocol == 'http:' && location.host.indexOf('localhost') < 0) {
|
|
223
|
-
showBalloonWarning("WebXR only works on https");
|
|
224
|
-
console.warn("WebXR only works on https. https://engine.needle.tools/docs/xr.html");
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
onEnable() {
|
|
229
|
-
if (this.isInit) return;
|
|
230
|
-
if (!this.enableAR && !this.enableVR) return;
|
|
231
|
-
this.isInit = true;
|
|
232
|
-
|
|
233
|
-
this.context.renderer.xr.enabled = true;
|
|
234
|
-
|
|
235
|
-
// TODO: move the whole buttons positioning out of here and make it configureable from css
|
|
236
|
-
// better set proper classes so user code can react to it instead
|
|
237
|
-
// of this hardcoded stuff
|
|
238
|
-
let arButton, vrButton;
|
|
239
|
-
const buttonsContainer = document.createElement('div');
|
|
240
|
-
buttonsContainer.classList.add("webxr-buttons");
|
|
241
|
-
buttonsContainer.style.cssText = `
|
|
242
|
-
position: absolute;
|
|
243
|
-
bottom: 21px;
|
|
244
|
-
left: 50%;
|
|
245
|
-
transform: translate(-50%, 0%);
|
|
246
|
-
z-index: 1000;
|
|
247
|
-
|
|
248
|
-
display: flex;
|
|
249
|
-
flex-direction: row;
|
|
250
|
-
justify-content: center;
|
|
251
|
-
align-items: flex-start;
|
|
252
|
-
gap: 10px;
|
|
253
|
-
`;
|
|
254
|
-
this.context.appendHTMLElement(buttonsContainer);
|
|
255
|
-
|
|
256
|
-
const forceButtons = debugWebXR;
|
|
257
|
-
if (debugWebXR) console.log("ARSupported?", arSupported, "VRSupported?", vrSupported);
|
|
258
|
-
|
|
259
|
-
// AR support
|
|
260
|
-
if (forceButtons || (this.createARButton && this.enableAR && arSupported)) {
|
|
261
|
-
arButton = WebXR.createARButton(this);
|
|
262
|
-
this._arButton = arButton;
|
|
263
|
-
buttonsContainer.appendChild(arButton);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// VR support
|
|
267
|
-
if (forceButtons || (this.createVRButton && this.enableVR && vrSupported)) {
|
|
268
|
-
vrButton = WebXR.createVRButton(this);
|
|
269
|
-
this._vrButton = vrButton;
|
|
270
|
-
buttonsContainer.appendChild(vrButton);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
setTimeout(() => {
|
|
274
|
-
WebXR.resetButtonStyles(vrButton);
|
|
275
|
-
WebXR.resetButtonStyles(arButton);
|
|
276
|
-
}, 1000);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
private _transformOrientation: Quaternion = new Quaternion();
|
|
280
|
-
public get TransformOrientation(): Quaternion { return this._transformOrientation; }
|
|
281
|
-
|
|
282
|
-
private _currentHeadPose: XRViewerPose | null = null;
|
|
283
|
-
public get HeadPose(): XRViewerPose | null { return this._currentHeadPose; }
|
|
284
|
-
|
|
285
|
-
onBeforeRender(frame:XRFrame | null | undefined) {
|
|
286
|
-
if (!frame) return;
|
|
287
|
-
// TODO: figure out why screen is black if we enable the code written here
|
|
288
|
-
// const referenceSpace = renderer.xr.getReferenceSpace();
|
|
289
|
-
const session = this.context.renderer.xr.getSession();
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
if (session) {
|
|
293
|
-
const referenceSpace = this.context.renderer.xr.getReferenceSpace();
|
|
294
|
-
if(!referenceSpace) return;
|
|
295
|
-
const pose = frame.getViewerPose(referenceSpace);
|
|
296
|
-
if (!pose) return;
|
|
297
|
-
this._currentHeadPose = pose;
|
|
298
|
-
const transform: XRRigidTransform = pose?.transform;
|
|
299
|
-
if (transform) {
|
|
300
|
-
this._transformOrientation.set(transform.orientation.x, transform.orientation.y, transform.orientation.z, transform.orientation.w);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
if (WebXR._isInXr === false && session) {
|
|
304
|
-
this.onEnterXR(session, frame);
|
|
305
|
-
}
|
|
306
|
-
else if (this.IsInVR) {
|
|
307
|
-
if (this.context.mainCamera) {
|
|
308
|
-
this.ensureRig();
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
for (const ctrl of this.controllers) {
|
|
313
|
-
ctrl.onUpdate(session);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (this._isInAR) {
|
|
317
|
-
this.webAR?.onUpdate(session, frame);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
WebXR.events.dispatchEvent({ type: WebXREvent.XRUpdate, frame: frame, xr: this.context.renderer.xr, rig: this.rig });
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
private onClickedARButton() {
|
|
325
|
-
if (!this._isInAR) {
|
|
326
|
-
this._requestedAR = true;
|
|
327
|
-
this._requestedVR = false;
|
|
328
|
-
|
|
329
|
-
// if we do this on enter xr the state has already been changed in AR mode
|
|
330
|
-
// so we need to to this before session has started
|
|
331
|
-
this.captureStateBeforeXR();
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
private onClickedVRButton() {
|
|
336
|
-
if (!this._isInVR) {
|
|
337
|
-
|
|
338
|
-
// happens e.g. when headset is off and xr session never actually started
|
|
339
|
-
if (this._requestedVR) {
|
|
340
|
-
this.onExitXR(null);
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
this._requestedAR = false;
|
|
345
|
-
this._requestedVR = true;
|
|
346
|
-
this.captureStateBeforeXR();
|
|
347
|
-
|
|
348
|
-
// build controllers before session begins - this seems to fix issue with controller models not appearing/not getting connection event
|
|
349
|
-
this.ensureRig();
|
|
350
|
-
for (let i = 0; i < 2; i++) {
|
|
351
|
-
WebXRController.Create(this, i, this.gameObject as GameObject, ControllerType.PhysicalDevice);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
WebXR.events.dispatchEvent({ type: WebXREvent.RequestVRSession });
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
private captureStateBeforeXR() {
|
|
359
|
-
if (this.context.mainCamera) {
|
|
360
|
-
this._originalCameraPosition.copy(getWorldPosition(this.context.mainCamera));
|
|
361
|
-
this._originalCameraRotation.copy(getWorldQuaternion(this.context.mainCamera));
|
|
362
|
-
this._originalCameraParent = this.context.mainCamera.parent;
|
|
363
|
-
}
|
|
364
|
-
if (this.Rig) {
|
|
365
|
-
this._originalXRRigParent = this.Rig.parent;
|
|
366
|
-
this._originalXRRigPosition.copy(this.Rig.position);
|
|
367
|
-
this._originalXRRigRotation.copy(this.Rig.quaternion);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
private ensureRig() {
|
|
372
|
-
if (!this.rig || isDestroyed(this.rig)) {
|
|
373
|
-
// currently just used for pose
|
|
374
|
-
const xrRig = GameObject.findObjectOfType(XRRig, this.context);
|
|
375
|
-
if (xrRig) {
|
|
376
|
-
// make it match unity forward
|
|
377
|
-
this.rig = xrRig.gameObject;
|
|
378
|
-
this.rig.rotateY(Math.PI);
|
|
379
|
-
// this.rig.position.copy(existing.worldPosition);
|
|
380
|
-
// this.rig.quaternion.premultiply(existing.worldQuaternion);
|
|
381
|
-
}
|
|
382
|
-
else {
|
|
383
|
-
this.rig = new Group();
|
|
384
|
-
this.rig.rotateY(Math.PI);
|
|
385
|
-
this.rig.name = "XRRig";
|
|
386
|
-
this.context.scene.add(this.rig);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Make sure the webxr camera is parented to the xr rig
|
|
391
|
-
if (this.context.isInXR && this.context.mainCamera && this.context.mainCamera.parent !== this.rig) {
|
|
392
|
-
this.rig.add(this.context.mainCamera);
|
|
393
|
-
|
|
394
|
-
// Hack: make sure we have the correct position and rotation (e.g. where we are dealing with an implicitly created rig)
|
|
395
|
-
// This handles the case where we switch between multiple scenes
|
|
396
|
-
if (this.IsInVR) {
|
|
397
|
-
const other = GameObject.findObjectOfType(XRRig);
|
|
398
|
-
if (other && other?.gameObject !== this.rig) {
|
|
399
|
-
this.rig.position.copy(other.gameObject.position);
|
|
400
|
-
this.rig.quaternion.copy(other.gameObject.quaternion);
|
|
401
|
-
this.rig.rotateY(Math.PI);
|
|
402
|
-
this.rig.scale.copy(other.gameObject.scale);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
private _originalCameraParent: Object3D | null = null;
|
|
410
|
-
private _originalCameraPosition: Vector3 = new Vector3();
|
|
411
|
-
private _originalCameraRotation: Quaternion = new Quaternion();
|
|
412
|
-
|
|
413
|
-
private _originalXRRigParent: Object3D | null = null;
|
|
414
|
-
private _originalXRRigPosition: Vector3 = new Vector3();
|
|
415
|
-
private _originalXRRigRotation: Quaternion = new Quaternion();
|
|
416
|
-
|
|
417
|
-
private onEnterXR(session: XRSession, frame: XRFrame) {
|
|
418
|
-
console.log("[XR] session begin", session, frame);
|
|
419
|
-
WebXR._isInXr = true;
|
|
420
|
-
|
|
421
|
-
this.ensureRig();
|
|
422
|
-
|
|
423
|
-
const space = this.context.renderer.xr.getReferenceSpace();
|
|
424
|
-
if (space && this.rig) {
|
|
425
|
-
const pose = frame.getViewerPose(space);
|
|
426
|
-
const rot = pose?.transform.orientation;
|
|
427
|
-
if (rot) {
|
|
428
|
-
const quat = new Quaternion(rot.x, rot.y, rot.z, rot.w);
|
|
429
|
-
const eu = new Euler().setFromQuaternion(quat);
|
|
430
|
-
this.rig.rotateY(eu.y);
|
|
431
|
-
// this.rig.quaternion.multiply(quat);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// when we set unity layers objects will only be rendered on one eye
|
|
436
|
-
// we set layers to sync raycasting and have a similar behaviour to unity
|
|
437
|
-
const xr = this.context.renderer.xr;
|
|
438
|
-
if (this.context.mainCamera) {
|
|
439
|
-
const cam = xr.getCamera() as WebXRArrayCamera;
|
|
440
|
-
if (debugWebXR) console.log("WebXRCamera", cam);
|
|
441
|
-
const cull = this.context.mainCameraComponent?.cullingMask;
|
|
442
|
-
if (cam && cull !== undefined) {
|
|
443
|
-
for (const c of cam.cameras) {
|
|
444
|
-
c.layers.mask = cull;
|
|
445
|
-
}
|
|
446
|
-
cam.layers.mask = cull;
|
|
447
|
-
}
|
|
448
|
-
else if (cam) {
|
|
449
|
-
for (const c of cam.cameras) {
|
|
450
|
-
c.layers.enableAll();
|
|
451
|
-
}
|
|
452
|
-
cam.layers.enableAll();
|
|
453
|
-
}
|
|
454
|
-
if (this._requestedAR) {
|
|
455
|
-
this.context.scene.add(this.rig);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
const flag = this._requestedAR ? XRStateFlag.AR : XRStateFlag.VR;
|
|
460
|
-
|
|
461
|
-
XRState.Global.Set(flag);
|
|
462
|
-
|
|
463
|
-
switch (flag) {
|
|
464
|
-
case XRStateFlag.AR:
|
|
465
|
-
this.context.xrSessionMode = XRSessionMode.ImmersiveAR;
|
|
466
|
-
this._isInAR = true;
|
|
467
|
-
this.webAR?.onBegin(session);
|
|
468
|
-
break;
|
|
469
|
-
case XRStateFlag.VR:
|
|
470
|
-
this.context.xrSessionMode = XRSessionMode.ImmersiveVR;
|
|
471
|
-
this._isInVR = true;
|
|
472
|
-
this.onEnterVR(session);
|
|
473
|
-
break;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
session.addEventListener('end', () => {
|
|
477
|
-
console.log("[XR] session end");
|
|
478
|
-
WebXR._isInXr = false;
|
|
479
|
-
this.onExitXR(session);
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
this.onEnterXR_HandleMirrorWindow(session);
|
|
483
|
-
|
|
484
|
-
WebXR.events.dispatchEvent({ type: WebXREvent.XRStarted, session: session });
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
private onExitXR(session: XRSession | null) {
|
|
488
|
-
|
|
489
|
-
const wasInAR = this._isInAR;
|
|
490
|
-
|
|
491
|
-
if (session) {
|
|
492
|
-
if (this._isInAR) {
|
|
493
|
-
this.webAR?.onEnd(session);
|
|
494
|
-
}
|
|
495
|
-
else {
|
|
496
|
-
// if in VR we want to restore the FOV
|
|
497
|
-
this.context.mainCameraComponent?.applyClearFlagsIfIsActiveCamera();
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
this._isInAR = false;
|
|
502
|
-
this._isInVR = false;
|
|
503
|
-
this._requestedAR = false;
|
|
504
|
-
this._requestedVR = false;
|
|
505
|
-
this.context.xrSessionMode = undefined;
|
|
506
|
-
|
|
507
|
-
if (this.xrMirrorWindow) {
|
|
508
|
-
this.xrMirrorWindow.close();
|
|
509
|
-
this.xrMirrorWindow = null;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
this.destroyControllers();
|
|
513
|
-
|
|
514
|
-
if (this.context.mainCamera) {
|
|
515
|
-
this._originalCameraParent?.add(this.context.mainCamera);
|
|
516
|
-
setWorldPosition(this.context.mainCamera, this._originalCameraPosition);
|
|
517
|
-
setWorldQuaternion(this.context.mainCamera, this._originalCameraRotation);
|
|
518
|
-
this.context.mainCamera.scale.set(1, 1, 1);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
if (wasInAR) {
|
|
522
|
-
this._originalXRRigParent?.add(this.rig);
|
|
523
|
-
this.rig.position.copy(this._originalXRRigPosition);
|
|
524
|
-
this.rig.quaternion.copy(this._originalXRRigRotation);
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
XRState.Global.Set(XRStateFlag.Browser | XRStateFlag.ThirdPerson);
|
|
528
|
-
WebXR.events.dispatchEvent({ type: WebXREvent.XRStopped, session: session });
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
private onEnterVR(_session: XRSession) {
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
private destroyControllers() {
|
|
535
|
-
for (let i = this.controllers.length - 1; i >= 0; i -= 1) {
|
|
536
|
-
this.controllers[i]?.destroy();
|
|
537
|
-
}
|
|
538
|
-
this.controllers.length = 0;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
private xrMirrorWindow: Window | null = null;
|
|
542
|
-
|
|
543
|
-
private onEnterXR_HandleMirrorWindow(session: XRSession) {
|
|
544
|
-
if (!getParam("mirror")) return;
|
|
545
|
-
setTimeout(() => {
|
|
546
|
-
if (!WebXR.IsInWebXR) return;
|
|
547
|
-
const url = new URL(window.location.href);
|
|
548
|
-
setOrAddParamsToUrl(url.searchParams, noVoip, 1);
|
|
549
|
-
setOrAddParamsToUrl(url.searchParams, "isMirror", 1);
|
|
550
|
-
const str = url.toString();
|
|
551
|
-
this.xrMirrorWindow = window.open(str, "webxr sync", "popup=yes");
|
|
552
|
-
if (this.xrMirrorWindow) {
|
|
553
|
-
this.xrMirrorWindow.onload = () => {
|
|
554
|
-
if (this.xrMirrorWindow)
|
|
555
|
-
this.xrMirrorWindow.onbeforeunload = () => {
|
|
556
|
-
if (WebXR.IsInWebXR)
|
|
557
|
-
session.end();
|
|
558
|
-
};
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
}, 1000);
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
// not sure if this should be a behaviour.
|
|
567
|
-
// for now we dont really need it to go through the usual update loop
|
|
568
|
-
export class WebAR {
|
|
569
|
-
|
|
570
|
-
get webxr(): WebXR { return this._webxr; }
|
|
571
|
-
|
|
572
|
-
private _webxr: WebXR;
|
|
573
|
-
|
|
574
|
-
private reticle: Object3D | null = null;
|
|
575
|
-
private reticleParent: Object3D | null = null;
|
|
576
|
-
private hitTestSource: XRHitTestSource | null = null;
|
|
577
|
-
private reticleActive: boolean = true;
|
|
578
|
-
|
|
579
|
-
// scene.background before entering AR
|
|
580
|
-
private previousBackground: Color | null | Texture = null;
|
|
581
|
-
private previousEnvironment: Texture | null = null;
|
|
582
|
-
|
|
583
|
-
private sessionRoot: WebARSessionRoot | null = null;
|
|
584
|
-
private _previousParent: Object3D | null = null;
|
|
585
|
-
// we need this in case the session root is on the same object as the webxr component
|
|
586
|
-
// so if we disable the session root we attach the webxr component to this temporary object
|
|
587
|
-
// to still receive updates
|
|
588
|
-
private static tempWebXRObject: Object3D;
|
|
589
|
-
|
|
590
|
-
private get context() { return this.webxr.context; }
|
|
591
|
-
|
|
592
|
-
constructor(webxr: WebXR) {
|
|
593
|
-
this._webxr = webxr;
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
private arDomOverlay: HTMLElement | null = null;
|
|
597
|
-
private arOverlayElement: INeedleEngineComponent | HTMLElement | null = null;
|
|
598
|
-
private noHitTestAvailable: boolean = false;
|
|
599
|
-
private didPlaceARSessionRoot: boolean = false;
|
|
600
|
-
|
|
601
|
-
getAROverlayContainer(): HTMLElement | null {
|
|
602
|
-
this.arDomOverlay = this.webxr.context.domElement as HTMLElement;
|
|
603
|
-
// for react cases we dont have an Engine Element
|
|
604
|
-
const element: any = this.arDomOverlay;
|
|
605
|
-
if (element.getAROverlayContainer)
|
|
606
|
-
this.arOverlayElement = element.getAROverlayContainer();
|
|
607
|
-
else this.arOverlayElement = this.arDomOverlay;
|
|
608
|
-
return this.arOverlayElement;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
setReticleActive(active: boolean) {
|
|
612
|
-
this.reticleActive = active;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
async onBegin(session: XRSession) {
|
|
616
|
-
const context = this.webxr.context;
|
|
617
|
-
this.reticleActive = true;
|
|
618
|
-
this.didPlaceARSessionRoot = false;
|
|
619
|
-
this.getAROverlayContainer();
|
|
620
|
-
|
|
621
|
-
const deviceType = isQuest() ? ControllerType.PhysicalDevice : ControllerType.Touch;
|
|
622
|
-
const controllerCount = deviceType === ControllerType.Touch ? 4 : 2;
|
|
623
|
-
for (let i = 0; i < controllerCount; i++) {
|
|
624
|
-
WebXRController.Create(this.webxr, i, this.webxr.gameObject as GameObject, deviceType)
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
if (!this.sessionRoot || this.sessionRoot.destroyed || !this.sessionRoot.activeAndEnabled)
|
|
628
|
-
this.sessionRoot = GameObject.findObjectOfType(WebARSessionRoot, context);
|
|
629
|
-
if (!this.sessionRoot) {
|
|
630
|
-
// TODO: adding it on the scene directly doesnt work (probably because then everything in the scene is disabled including this component). See code a bit furhter below where we add this component to a temporary object inside the scene
|
|
631
|
-
const obj = this.webxr.gameObject;
|
|
632
|
-
this.sessionRoot = GameObject.addNewComponent(obj, WebARSessionRoot);
|
|
633
|
-
console.warn("WebAR: No ARSessionRoot found, creating one automatically on the WebXR object");
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
this.previousBackground = context.scene.background;
|
|
637
|
-
this.previousEnvironment = context.scene.environment;
|
|
638
|
-
context.scene.background = null;
|
|
639
|
-
|
|
640
|
-
session.requestReferenceSpace('viewer').then((referenceSpace) => {
|
|
641
|
-
session.requestHitTestSource?.call(session, { space: referenceSpace })?.then((source) => {
|
|
642
|
-
this.hitTestSource = source;
|
|
643
|
-
}).catch((err) => {
|
|
644
|
-
this.noHitTestAvailable = true;
|
|
645
|
-
console.warn("WebXR: Hit test not supported", err);
|
|
646
|
-
});
|
|
647
|
-
});
|
|
648
|
-
|
|
649
|
-
if (!this.reticle && this.sessionRoot) {
|
|
650
|
-
this.reticle = new Mesh(
|
|
651
|
-
new RingGeometry(0.07, 0.09, 32).rotateX(- Math.PI / 2),
|
|
652
|
-
new MeshBasicMaterial()
|
|
653
|
-
);
|
|
654
|
-
this.reticle.name = "AR Placement reticle";
|
|
655
|
-
this.reticle.matrixAutoUpdate = false;
|
|
656
|
-
this.reticle.visible = false;
|
|
657
|
-
|
|
658
|
-
// create AR reticle parent to allow WebXRSessionRoot to be translated, rotated or scaled
|
|
659
|
-
this.reticleParent = new Object3D();
|
|
660
|
-
this.reticleParent.name = "AR Reticle Parent";
|
|
661
|
-
this.reticleParent.matrixAutoUpdate = false;
|
|
662
|
-
this.reticleParent.add(this.reticle);
|
|
663
|
-
// this.reticleParent.matrix.copy(this.sessionRoot.gameObject.matrixWorld);
|
|
664
|
-
|
|
665
|
-
if (this.webxr.scene) {
|
|
666
|
-
this.context.scene.add(this.reticleParent);
|
|
667
|
-
// this.context.scene.add(this.reticle);
|
|
668
|
-
this.context.scene.visible = true;
|
|
669
|
-
}
|
|
670
|
-
else console.warn("Could not found WebXR Rig");
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
this._previousParent = this.webxr.gameObject;
|
|
674
|
-
if (!WebAR.tempWebXRObject) WebAR.tempWebXRObject = new Object3D();
|
|
675
|
-
this.context.scene.add(WebAR.tempWebXRObject);
|
|
676
|
-
GameObject.addComponent(WebAR.tempWebXRObject as GameObject, this.webxr);
|
|
677
|
-
|
|
678
|
-
if (this.sessionRoot) {
|
|
679
|
-
this.sessionRoot.webAR = this;
|
|
680
|
-
this.sessionRoot?.onBegin(session);
|
|
681
|
-
}
|
|
682
|
-
else console.warn("No WebARSessionRoot found in scene")
|
|
683
|
-
|
|
684
|
-
const eng = this.context.domElement as INeedleEngineComponent;
|
|
685
|
-
eng?.onEnterAR?.call(eng, session, this.arOverlayElement!);
|
|
686
|
-
|
|
687
|
-
this.context.mainCameraComponent?.applyClearFlagsIfIsActiveCamera();
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
onEnd(session: XRSession) {
|
|
691
|
-
if (this._previousParent) {
|
|
692
|
-
GameObject.addComponent(this._previousParent as GameObject, this.webxr);
|
|
693
|
-
this._previousParent = null;
|
|
694
|
-
}
|
|
695
|
-
this.hitTestSource = null;
|
|
696
|
-
const context = this.webxr.context;
|
|
697
|
-
context.scene.background = this.previousBackground;
|
|
698
|
-
context.scene.environment = this.previousEnvironment;
|
|
699
|
-
if (this.sessionRoot) {
|
|
700
|
-
this.sessionRoot.onEnd(this.webxr.Rig, session);
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
const el = this.context.domElement as INeedleEngineComponent;
|
|
704
|
-
el.onExitAR?.call(el, session);
|
|
705
|
-
|
|
706
|
-
this.context.mainCameraComponent?.applyClearFlagsIfIsActiveCamera();
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
onUpdate(session: XRSession, frame: XRFrame) {
|
|
710
|
-
|
|
711
|
-
if (this.noHitTestAvailable === true) {
|
|
712
|
-
if (this.reticle)
|
|
713
|
-
this.reticle.visible = false;
|
|
714
|
-
if (!this.didPlaceARSessionRoot) {
|
|
715
|
-
this.didPlaceARSessionRoot = true;
|
|
716
|
-
const rig = this.webxr.Rig;
|
|
717
|
-
const placementMatrix = arPlacementWithoutHitTestMatrix.clone();
|
|
718
|
-
// if (rig) {
|
|
719
|
-
// const positionFromRig = new Vector3(0, 0, 0).add(rig.position).divideScalar(this.sessionRoot?.arScale ?? 1);
|
|
720
|
-
// placementMatrix.multiply(new Matrix4().makeTranslation(positionFromRig.x, positionFromRig.y, positionFromRig.z));
|
|
721
|
-
// // placementMatrix.setPosition(positionFromRig);
|
|
722
|
-
// }
|
|
723
|
-
this.sessionRoot?.placeAt(rig, placementMatrix);
|
|
724
|
-
}
|
|
725
|
-
return;
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
if (!this.hitTestSource) return;
|
|
729
|
-
const hitTestResults = frame.getHitTestResults(this.hitTestSource);
|
|
730
|
-
if (hitTestResults.length) {
|
|
731
|
-
const hit = hitTestResults[0];
|
|
732
|
-
const referenceSpace = this.webxr.context.renderer.xr.getReferenceSpace();
|
|
733
|
-
if (referenceSpace) {
|
|
734
|
-
const pose = hit.getPose(referenceSpace);
|
|
735
|
-
|
|
736
|
-
if (this.sessionRoot) {
|
|
737
|
-
const didPlace = this.sessionRoot.onUpdate(this.webxr.Rig, session, hit, pose);
|
|
738
|
-
this.didPlaceARSessionRoot = didPlace;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
if (this.reticle) {
|
|
742
|
-
this.reticle.visible = this.reticleActive && this._webxr.allowARPlacementReticle;
|
|
743
|
-
if (this.reticleActive) {
|
|
744
|
-
if (pose) {
|
|
745
|
-
const matrix = pose.transform.matrix;
|
|
746
|
-
this.reticle.matrix.fromArray(matrix);
|
|
747
|
-
if (this.webxr.Rig)
|
|
748
|
-
this.reticle.matrix.premultiply(this.webxr.Rig.matrix);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
} else {
|
|
755
|
-
this.sessionRoot?.onUpdate(this.webxr.Rig, session, null, null);
|
|
756
|
-
if (this.reticle)
|
|
757
|
-
this.reticle.visible = false;
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
|
|
1
|
+
import { Color, Euler, EventDispatcher, Group, Matrix4, Mesh, MeshBasicMaterial, Object3D, Quaternion, RingGeometry, Texture, Vector3, type WebXRArrayCamera } from 'three';
|
|
2
|
+
import { ARButton } from '../../include/three/ARButton.js';
|
|
3
|
+
import { VRButton } from '../../include/three/VRButton.js';
|
|
4
|
+
|
|
5
|
+
import { AssetReference } from "../../engine/engine_addressables.js";
|
|
6
|
+
import { serializable } from "../../engine/engine_serialization_decorator.js";
|
|
7
|
+
import { XRSessionMode } from "../../engine/engine_setup.js";
|
|
8
|
+
import { getWorldPosition, getWorldQuaternion, setWorldPosition, setWorldQuaternion } from "../../engine/engine_three_utils.js";
|
|
9
|
+
import type { INeedleEngineComponent } from "../../engine/engine_types.js";
|
|
10
|
+
import { getParam, isMozillaXR, isQuest, setOrAddParamsToUrl } from "../../engine/engine_utils.js";
|
|
11
|
+
|
|
12
|
+
import { Behaviour, GameObject } from "../Component.js";
|
|
13
|
+
import { noVoip } from "../Voip.js";
|
|
14
|
+
import { WebARSessionRoot } from "./WebARSessionRoot.js";
|
|
15
|
+
import { ControllerType, WebXRController } from "./WebXRController.js";
|
|
16
|
+
import { XRRig } from "./WebXRRig.js";
|
|
17
|
+
import { WebXRSync } from "./WebXRSync.js";
|
|
18
|
+
import { XRState, XRStateFlag } from "../XRFlag.js";
|
|
19
|
+
import { showBalloonWarning } from '../../engine/debug/index.js';
|
|
20
|
+
import { isDestroyed } from '../../engine/engine_gameobject.js';
|
|
21
|
+
|
|
22
|
+
const debugWebXR = getParam("debugwebxr");
|
|
23
|
+
|
|
24
|
+
export async function detectARSupport() {
|
|
25
|
+
if (isMozillaXR()) return true;
|
|
26
|
+
if ("xr" in navigator) {
|
|
27
|
+
//@ts-ignore
|
|
28
|
+
return (await navigator["xr"].isSessionSupported('immersive-ar')) === true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
export async function detectVRSupport() {
|
|
33
|
+
if ("xr" in navigator) {
|
|
34
|
+
//@ts-ignore
|
|
35
|
+
return (await navigator["xr"].isSessionSupported('immersive-vr')) === true;
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let arSupported = false;
|
|
41
|
+
let vrSupported = false;
|
|
42
|
+
detectARSupport().then(res => arSupported = res);
|
|
43
|
+
detectVRSupport().then(res => vrSupported = res);
|
|
44
|
+
|
|
45
|
+
// import TeleportVR from "teleportvr.js";
|
|
46
|
+
|
|
47
|
+
export enum WebXREvent {
|
|
48
|
+
XRStarted = "xrStarted",
|
|
49
|
+
XRStopped = "xrStopped",
|
|
50
|
+
XRUpdate = "xrUpdate",
|
|
51
|
+
RequestVRSession = "requestVRSession",
|
|
52
|
+
ModifyAROptions = "modify-ar-options",
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export declare type CreateButtonOptions = {
|
|
56
|
+
registerClick: boolean
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export class WebXR extends Behaviour {
|
|
60
|
+
|
|
61
|
+
@serializable()
|
|
62
|
+
enableVR = true;
|
|
63
|
+
@serializable()
|
|
64
|
+
enableAR = true;
|
|
65
|
+
|
|
66
|
+
@serializable(AssetReference)
|
|
67
|
+
defaultAvatar?: AssetReference;
|
|
68
|
+
@serializable()
|
|
69
|
+
handModelPath: string = "";
|
|
70
|
+
|
|
71
|
+
@serializable()
|
|
72
|
+
createVRButton: boolean = true;
|
|
73
|
+
@serializable()
|
|
74
|
+
createARButton: boolean = true;
|
|
75
|
+
|
|
76
|
+
private static _isInXr: boolean = false;
|
|
77
|
+
private static events: EventDispatcher = new EventDispatcher();
|
|
78
|
+
|
|
79
|
+
public static get IsInWebXR(): boolean { return this._isInXr; }
|
|
80
|
+
public static get XRSupported(): boolean { return 'xr' in navigator && (arSupported || vrSupported); }
|
|
81
|
+
public static get IsARSupported(): boolean { return arSupported; }
|
|
82
|
+
public static get IsVRSupported(): boolean { return vrSupported; }
|
|
83
|
+
|
|
84
|
+
private static _optionalFeatures_VR: string[] = ['local-floor', 'bounded-floor', 'hand-tracking', 'high-fixed-foveation-level', 'layers'];
|
|
85
|
+
private static _optionalFeatures_AR: string[] = ['anchors', 'local-floor', 'hand-tracking', 'layers'];
|
|
86
|
+
public static get OptionalFeatures_VR(): string[] { return this._optionalFeatures_VR; }
|
|
87
|
+
public static get OptionalFeatures_AR(): string[] { return this._optionalFeatures_AR; }
|
|
88
|
+
|
|
89
|
+
public static addEventListener(type: string, listener: any): any {
|
|
90
|
+
this.events.addEventListener(type, listener);
|
|
91
|
+
return listener;
|
|
92
|
+
}
|
|
93
|
+
public static removeEventListener(type: string, listener: any): any {
|
|
94
|
+
this.events.removeEventListener(type, listener);
|
|
95
|
+
return listener;
|
|
96
|
+
}
|
|
97
|
+
private static dispatchEvent(type: string, event: any): void {
|
|
98
|
+
this.events.dispatchEvent({ type, detail: event });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public static createVRButton(webXR: WebXR, opts?: CreateButtonOptions): HTMLButtonElement | HTMLAnchorElement {
|
|
102
|
+
if (!WebXR.XRSupported) {
|
|
103
|
+
console.warn("WebXR is not supported on this device");
|
|
104
|
+
}
|
|
105
|
+
else
|
|
106
|
+
webXR.__internalAwake();
|
|
107
|
+
const options = { optionalFeatures: WebXR.OptionalFeatures_VR };
|
|
108
|
+
const vrButton = VRButton.createButton(webXR.context.renderer, options);
|
|
109
|
+
vrButton.classList.add('webxr-ar-button');
|
|
110
|
+
vrButton.classList.add('webxr-button');
|
|
111
|
+
this.resetButtonStyles(vrButton);
|
|
112
|
+
// if (this.enableAR) vrButton.style.marginLeft = "60px";
|
|
113
|
+
if (opts?.registerClick ?? true)
|
|
114
|
+
vrButton.addEventListener('click', webXR.onClickedVRButton.bind(webXR));
|
|
115
|
+
return vrButton;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public static createARButton(webXR: WebXR, opts?: CreateButtonOptions): HTMLButtonElement | HTMLAnchorElement {
|
|
119
|
+
webXR.__internalAwake();
|
|
120
|
+
const domOverlayRoot = webXR.webAR?.getAROverlayContainer();
|
|
121
|
+
const options: any = { optionalFeatures: [...this.OptionalFeatures_AR] };
|
|
122
|
+
if (domOverlayRoot) {
|
|
123
|
+
options.domOverlay = { root: domOverlayRoot };
|
|
124
|
+
options.optionalFeatures.push('dom-overlay')
|
|
125
|
+
options.optionalFeatures.push('hit-test');
|
|
126
|
+
options.optionalFeatures.push('anchors');
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
console.warn("No dom overlay root found, HTML overlays on top of screen-based AR will not work.");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const arButton = ARButton.createButton(webXR.context.renderer, options, this.onModifyAROptions.bind(this));
|
|
133
|
+
arButton.classList.add('webxr-ar-button');
|
|
134
|
+
arButton.classList.add('webxr-button');
|
|
135
|
+
WebXR.resetButtonStyles(arButton);
|
|
136
|
+
if (opts?.registerClick ?? true)
|
|
137
|
+
arButton.addEventListener('click', webXR.onClickedARButton.bind(webXR));
|
|
138
|
+
return arButton;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private static onModifyAROptions(options) {
|
|
142
|
+
WebXR.dispatchEvent(WebXREvent.ModifyAROptions, options);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public static resetButtonStyles(button) {
|
|
146
|
+
if (!button) return;
|
|
147
|
+
button.style.position = "";
|
|
148
|
+
button.style.bottom = "";
|
|
149
|
+
button.style.left = "";
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public endSession() {
|
|
153
|
+
const session = this.context.renderer.xr.getSession();
|
|
154
|
+
if (session) session.end();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
public get Rig(): Object3D {
|
|
158
|
+
this.ensureRig();
|
|
159
|
+
return this.rig;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
private controllers: WebXRController[] = [];
|
|
164
|
+
public get Controllers(): WebXRController[] {
|
|
165
|
+
return this.controllers;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public get LeftController(): WebXRController | null {
|
|
169
|
+
if (this.controllers.length > 0 && this.controllers[0].input?.handedness === "left") return this.controllers[0];
|
|
170
|
+
if (this.controllers.length > 1 && this.controllers[1].input?.handedness === "left") return this.controllers[1];
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
public get RightController(): WebXRController | null {
|
|
175
|
+
if (this.controllers.length > 0 && this.controllers[0].input?.handedness === "right") return this.controllers[0];
|
|
176
|
+
if (this.controllers.length > 1 && this.controllers[1].input?.handedness === "right") return this.controllers[1];
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
public get ARButton(): HTMLButtonElement | undefined {
|
|
181
|
+
return this._arButton;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
public get VRButton(): HTMLButtonElement | undefined {
|
|
185
|
+
return this._vrButton;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
public get IsInVR() { return this._isInVR; }
|
|
189
|
+
public get IsInAR() { return this._isInAR; }
|
|
190
|
+
|
|
191
|
+
/** When enabled */
|
|
192
|
+
allowARPlacementReticle: boolean = true;
|
|
193
|
+
|
|
194
|
+
private rig!: Object3D;
|
|
195
|
+
private isInit: boolean = false;
|
|
196
|
+
|
|
197
|
+
private _requestedAR: boolean = false;
|
|
198
|
+
private _requestedVR: boolean = false;
|
|
199
|
+
private _isInAR: boolean = false;
|
|
200
|
+
private _isInVR: boolean = false;
|
|
201
|
+
|
|
202
|
+
private _arButton?: HTMLButtonElement;
|
|
203
|
+
private _vrButton?: HTMLButtonElement;
|
|
204
|
+
|
|
205
|
+
private webAR: WebAR | null = null;
|
|
206
|
+
|
|
207
|
+
awake(): void {
|
|
208
|
+
// as the webxr component is most of the times currently loaded as part of the scene
|
|
209
|
+
// and not part of the glTF directly and thus does not go through the whole serialization process currently
|
|
210
|
+
// we need to to manuall make sure it is of the correct type here
|
|
211
|
+
if (this.defaultAvatar) {
|
|
212
|
+
if (typeof (this.defaultAvatar) === "string") {
|
|
213
|
+
this.defaultAvatar = AssetReference.getOrCreate(this.sourceId ?? "/", this.defaultAvatar, this.context);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (!GameObject.findObjectOfType(WebXRSync, this.context)) {
|
|
217
|
+
const sync = GameObject.addNewComponent(this.gameObject, WebXRSync, false) as WebXRSync;
|
|
218
|
+
sync.webXR = this;
|
|
219
|
+
}
|
|
220
|
+
this.webAR = new WebAR(this);
|
|
221
|
+
|
|
222
|
+
if (location.protocol == 'http:' && location.host.indexOf('localhost') < 0) {
|
|
223
|
+
showBalloonWarning("WebXR only works on https");
|
|
224
|
+
console.warn("WebXR only works on https. https://engine.needle.tools/docs/xr.html");
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
onEnable() {
|
|
229
|
+
if (this.isInit) return;
|
|
230
|
+
if (!this.enableAR && !this.enableVR) return;
|
|
231
|
+
this.isInit = true;
|
|
232
|
+
|
|
233
|
+
this.context.renderer.xr.enabled = true;
|
|
234
|
+
|
|
235
|
+
// TODO: move the whole buttons positioning out of here and make it configureable from css
|
|
236
|
+
// better set proper classes so user code can react to it instead
|
|
237
|
+
// of this hardcoded stuff
|
|
238
|
+
let arButton, vrButton;
|
|
239
|
+
const buttonsContainer = document.createElement('div');
|
|
240
|
+
buttonsContainer.classList.add("webxr-buttons");
|
|
241
|
+
buttonsContainer.style.cssText = `
|
|
242
|
+
position: absolute;
|
|
243
|
+
bottom: 21px;
|
|
244
|
+
left: 50%;
|
|
245
|
+
transform: translate(-50%, 0%);
|
|
246
|
+
z-index: 1000;
|
|
247
|
+
|
|
248
|
+
display: flex;
|
|
249
|
+
flex-direction: row;
|
|
250
|
+
justify-content: center;
|
|
251
|
+
align-items: flex-start;
|
|
252
|
+
gap: 10px;
|
|
253
|
+
`;
|
|
254
|
+
this.context.appendHTMLElement(buttonsContainer);
|
|
255
|
+
|
|
256
|
+
const forceButtons = debugWebXR;
|
|
257
|
+
if (debugWebXR) console.log("ARSupported?", arSupported, "VRSupported?", vrSupported);
|
|
258
|
+
|
|
259
|
+
// AR support
|
|
260
|
+
if (forceButtons || (this.createARButton && this.enableAR && arSupported)) {
|
|
261
|
+
arButton = WebXR.createARButton(this);
|
|
262
|
+
this._arButton = arButton;
|
|
263
|
+
buttonsContainer.appendChild(arButton);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// VR support
|
|
267
|
+
if (forceButtons || (this.createVRButton && this.enableVR && vrSupported)) {
|
|
268
|
+
vrButton = WebXR.createVRButton(this);
|
|
269
|
+
this._vrButton = vrButton;
|
|
270
|
+
buttonsContainer.appendChild(vrButton);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
setTimeout(() => {
|
|
274
|
+
WebXR.resetButtonStyles(vrButton);
|
|
275
|
+
WebXR.resetButtonStyles(arButton);
|
|
276
|
+
}, 1000);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
private _transformOrientation: Quaternion = new Quaternion();
|
|
280
|
+
public get TransformOrientation(): Quaternion { return this._transformOrientation; }
|
|
281
|
+
|
|
282
|
+
private _currentHeadPose: XRViewerPose | null = null;
|
|
283
|
+
public get HeadPose(): XRViewerPose | null { return this._currentHeadPose; }
|
|
284
|
+
|
|
285
|
+
onBeforeRender(frame:XRFrame | null | undefined) {
|
|
286
|
+
if (!frame) return;
|
|
287
|
+
// TODO: figure out why screen is black if we enable the code written here
|
|
288
|
+
// const referenceSpace = renderer.xr.getReferenceSpace();
|
|
289
|
+
const session = this.context.renderer.xr.getSession();
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
if (session) {
|
|
293
|
+
const referenceSpace = this.context.renderer.xr.getReferenceSpace();
|
|
294
|
+
if(!referenceSpace) return;
|
|
295
|
+
const pose = frame.getViewerPose(referenceSpace);
|
|
296
|
+
if (!pose) return;
|
|
297
|
+
this._currentHeadPose = pose;
|
|
298
|
+
const transform: XRRigidTransform = pose?.transform;
|
|
299
|
+
if (transform) {
|
|
300
|
+
this._transformOrientation.set(transform.orientation.x, transform.orientation.y, transform.orientation.z, transform.orientation.w);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (WebXR._isInXr === false && session) {
|
|
304
|
+
this.onEnterXR(session, frame);
|
|
305
|
+
}
|
|
306
|
+
else if (this.IsInVR) {
|
|
307
|
+
if (this.context.mainCamera) {
|
|
308
|
+
this.ensureRig();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
for (const ctrl of this.controllers) {
|
|
313
|
+
ctrl.onUpdate(session);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (this._isInAR) {
|
|
317
|
+
this.webAR?.onUpdate(session, frame);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
WebXR.events.dispatchEvent({ type: WebXREvent.XRUpdate, frame: frame, xr: this.context.renderer.xr, rig: this.rig });
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
private onClickedARButton() {
|
|
325
|
+
if (!this._isInAR) {
|
|
326
|
+
this._requestedAR = true;
|
|
327
|
+
this._requestedVR = false;
|
|
328
|
+
|
|
329
|
+
// if we do this on enter xr the state has already been changed in AR mode
|
|
330
|
+
// so we need to to this before session has started
|
|
331
|
+
this.captureStateBeforeXR();
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
private onClickedVRButton() {
|
|
336
|
+
if (!this._isInVR) {
|
|
337
|
+
|
|
338
|
+
// happens e.g. when headset is off and xr session never actually started
|
|
339
|
+
if (this._requestedVR) {
|
|
340
|
+
this.onExitXR(null);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
this._requestedAR = false;
|
|
345
|
+
this._requestedVR = true;
|
|
346
|
+
this.captureStateBeforeXR();
|
|
347
|
+
|
|
348
|
+
// build controllers before session begins - this seems to fix issue with controller models not appearing/not getting connection event
|
|
349
|
+
this.ensureRig();
|
|
350
|
+
for (let i = 0; i < 2; i++) {
|
|
351
|
+
WebXRController.Create(this, i, this.gameObject as GameObject, ControllerType.PhysicalDevice);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
WebXR.events.dispatchEvent({ type: WebXREvent.RequestVRSession });
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
private captureStateBeforeXR() {
|
|
359
|
+
if (this.context.mainCamera) {
|
|
360
|
+
this._originalCameraPosition.copy(getWorldPosition(this.context.mainCamera));
|
|
361
|
+
this._originalCameraRotation.copy(getWorldQuaternion(this.context.mainCamera));
|
|
362
|
+
this._originalCameraParent = this.context.mainCamera.parent;
|
|
363
|
+
}
|
|
364
|
+
if (this.Rig) {
|
|
365
|
+
this._originalXRRigParent = this.Rig.parent;
|
|
366
|
+
this._originalXRRigPosition.copy(this.Rig.position);
|
|
367
|
+
this._originalXRRigRotation.copy(this.Rig.quaternion);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
private ensureRig() {
|
|
372
|
+
if (!this.rig || isDestroyed(this.rig)) {
|
|
373
|
+
// currently just used for pose
|
|
374
|
+
const xrRig = GameObject.findObjectOfType(XRRig, this.context);
|
|
375
|
+
if (xrRig) {
|
|
376
|
+
// make it match unity forward
|
|
377
|
+
this.rig = xrRig.gameObject;
|
|
378
|
+
this.rig.rotateY(Math.PI);
|
|
379
|
+
// this.rig.position.copy(existing.worldPosition);
|
|
380
|
+
// this.rig.quaternion.premultiply(existing.worldQuaternion);
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
this.rig = new Group();
|
|
384
|
+
this.rig.rotateY(Math.PI);
|
|
385
|
+
this.rig.name = "XRRig";
|
|
386
|
+
this.context.scene.add(this.rig);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Make sure the webxr camera is parented to the xr rig
|
|
391
|
+
if (this.context.isInXR && this.context.mainCamera && this.context.mainCamera.parent !== this.rig) {
|
|
392
|
+
this.rig.add(this.context.mainCamera);
|
|
393
|
+
|
|
394
|
+
// Hack: make sure we have the correct position and rotation (e.g. where we are dealing with an implicitly created rig)
|
|
395
|
+
// This handles the case where we switch between multiple scenes
|
|
396
|
+
if (this.IsInVR) {
|
|
397
|
+
const other = GameObject.findObjectOfType(XRRig);
|
|
398
|
+
if (other && other?.gameObject !== this.rig) {
|
|
399
|
+
this.rig.position.copy(other.gameObject.position);
|
|
400
|
+
this.rig.quaternion.copy(other.gameObject.quaternion);
|
|
401
|
+
this.rig.rotateY(Math.PI);
|
|
402
|
+
this.rig.scale.copy(other.gameObject.scale);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
private _originalCameraParent: Object3D | null = null;
|
|
410
|
+
private _originalCameraPosition: Vector3 = new Vector3();
|
|
411
|
+
private _originalCameraRotation: Quaternion = new Quaternion();
|
|
412
|
+
|
|
413
|
+
private _originalXRRigParent: Object3D | null = null;
|
|
414
|
+
private _originalXRRigPosition: Vector3 = new Vector3();
|
|
415
|
+
private _originalXRRigRotation: Quaternion = new Quaternion();
|
|
416
|
+
|
|
417
|
+
private onEnterXR(session: XRSession, frame: XRFrame) {
|
|
418
|
+
console.log("[XR] session begin", session, frame);
|
|
419
|
+
WebXR._isInXr = true;
|
|
420
|
+
|
|
421
|
+
this.ensureRig();
|
|
422
|
+
|
|
423
|
+
const space = this.context.renderer.xr.getReferenceSpace();
|
|
424
|
+
if (space && this.rig) {
|
|
425
|
+
const pose = frame.getViewerPose(space);
|
|
426
|
+
const rot = pose?.transform.orientation;
|
|
427
|
+
if (rot) {
|
|
428
|
+
const quat = new Quaternion(rot.x, rot.y, rot.z, rot.w);
|
|
429
|
+
const eu = new Euler().setFromQuaternion(quat);
|
|
430
|
+
this.rig.rotateY(eu.y);
|
|
431
|
+
// this.rig.quaternion.multiply(quat);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// when we set unity layers objects will only be rendered on one eye
|
|
436
|
+
// we set layers to sync raycasting and have a similar behaviour to unity
|
|
437
|
+
const xr = this.context.renderer.xr;
|
|
438
|
+
if (this.context.mainCamera) {
|
|
439
|
+
const cam = xr.getCamera() as WebXRArrayCamera;
|
|
440
|
+
if (debugWebXR) console.log("WebXRCamera", cam);
|
|
441
|
+
const cull = this.context.mainCameraComponent?.cullingMask;
|
|
442
|
+
if (cam && cull !== undefined) {
|
|
443
|
+
for (const c of cam.cameras) {
|
|
444
|
+
c.layers.mask = cull;
|
|
445
|
+
}
|
|
446
|
+
cam.layers.mask = cull;
|
|
447
|
+
}
|
|
448
|
+
else if (cam) {
|
|
449
|
+
for (const c of cam.cameras) {
|
|
450
|
+
c.layers.enableAll();
|
|
451
|
+
}
|
|
452
|
+
cam.layers.enableAll();
|
|
453
|
+
}
|
|
454
|
+
if (this._requestedAR) {
|
|
455
|
+
this.context.scene.add(this.rig);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const flag = this._requestedAR ? XRStateFlag.AR : XRStateFlag.VR;
|
|
460
|
+
|
|
461
|
+
XRState.Global.Set(flag);
|
|
462
|
+
|
|
463
|
+
switch (flag) {
|
|
464
|
+
case XRStateFlag.AR:
|
|
465
|
+
this.context.xrSessionMode = XRSessionMode.ImmersiveAR;
|
|
466
|
+
this._isInAR = true;
|
|
467
|
+
this.webAR?.onBegin(session);
|
|
468
|
+
break;
|
|
469
|
+
case XRStateFlag.VR:
|
|
470
|
+
this.context.xrSessionMode = XRSessionMode.ImmersiveVR;
|
|
471
|
+
this._isInVR = true;
|
|
472
|
+
this.onEnterVR(session);
|
|
473
|
+
break;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
session.addEventListener('end', () => {
|
|
477
|
+
console.log("[XR] session end");
|
|
478
|
+
WebXR._isInXr = false;
|
|
479
|
+
this.onExitXR(session);
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
this.onEnterXR_HandleMirrorWindow(session);
|
|
483
|
+
|
|
484
|
+
WebXR.events.dispatchEvent({ type: WebXREvent.XRStarted, session: session });
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
private onExitXR(session: XRSession | null) {
|
|
488
|
+
|
|
489
|
+
const wasInAR = this._isInAR;
|
|
490
|
+
|
|
491
|
+
if (session) {
|
|
492
|
+
if (this._isInAR) {
|
|
493
|
+
this.webAR?.onEnd(session);
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
// if in VR we want to restore the FOV
|
|
497
|
+
this.context.mainCameraComponent?.applyClearFlagsIfIsActiveCamera();
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
this._isInAR = false;
|
|
502
|
+
this._isInVR = false;
|
|
503
|
+
this._requestedAR = false;
|
|
504
|
+
this._requestedVR = false;
|
|
505
|
+
this.context.xrSessionMode = undefined;
|
|
506
|
+
|
|
507
|
+
if (this.xrMirrorWindow) {
|
|
508
|
+
this.xrMirrorWindow.close();
|
|
509
|
+
this.xrMirrorWindow = null;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
this.destroyControllers();
|
|
513
|
+
|
|
514
|
+
if (this.context.mainCamera) {
|
|
515
|
+
this._originalCameraParent?.add(this.context.mainCamera);
|
|
516
|
+
setWorldPosition(this.context.mainCamera, this._originalCameraPosition);
|
|
517
|
+
setWorldQuaternion(this.context.mainCamera, this._originalCameraRotation);
|
|
518
|
+
this.context.mainCamera.scale.set(1, 1, 1);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (wasInAR) {
|
|
522
|
+
this._originalXRRigParent?.add(this.rig);
|
|
523
|
+
this.rig.position.copy(this._originalXRRigPosition);
|
|
524
|
+
this.rig.quaternion.copy(this._originalXRRigRotation);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
XRState.Global.Set(XRStateFlag.Browser | XRStateFlag.ThirdPerson);
|
|
528
|
+
WebXR.events.dispatchEvent({ type: WebXREvent.XRStopped, session: session });
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
private onEnterVR(_session: XRSession) {
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
private destroyControllers() {
|
|
535
|
+
for (let i = this.controllers.length - 1; i >= 0; i -= 1) {
|
|
536
|
+
this.controllers[i]?.destroy();
|
|
537
|
+
}
|
|
538
|
+
this.controllers.length = 0;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
private xrMirrorWindow: Window | null = null;
|
|
542
|
+
|
|
543
|
+
private onEnterXR_HandleMirrorWindow(session: XRSession) {
|
|
544
|
+
if (!getParam("mirror")) return;
|
|
545
|
+
setTimeout(() => {
|
|
546
|
+
if (!WebXR.IsInWebXR) return;
|
|
547
|
+
const url = new URL(window.location.href);
|
|
548
|
+
setOrAddParamsToUrl(url.searchParams, noVoip, 1);
|
|
549
|
+
setOrAddParamsToUrl(url.searchParams, "isMirror", 1);
|
|
550
|
+
const str = url.toString();
|
|
551
|
+
this.xrMirrorWindow = window.open(str, "webxr sync", "popup=yes");
|
|
552
|
+
if (this.xrMirrorWindow) {
|
|
553
|
+
this.xrMirrorWindow.onload = () => {
|
|
554
|
+
if (this.xrMirrorWindow)
|
|
555
|
+
this.xrMirrorWindow.onbeforeunload = () => {
|
|
556
|
+
if (WebXR.IsInWebXR)
|
|
557
|
+
session.end();
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}, 1000);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
// not sure if this should be a behaviour.
|
|
567
|
+
// for now we dont really need it to go through the usual update loop
|
|
568
|
+
export class WebAR {
|
|
569
|
+
|
|
570
|
+
get webxr(): WebXR { return this._webxr; }
|
|
571
|
+
|
|
572
|
+
private _webxr: WebXR;
|
|
573
|
+
|
|
574
|
+
private reticle: Object3D | null = null;
|
|
575
|
+
private reticleParent: Object3D | null = null;
|
|
576
|
+
private hitTestSource: XRHitTestSource | null = null;
|
|
577
|
+
private reticleActive: boolean = true;
|
|
578
|
+
|
|
579
|
+
// scene.background before entering AR
|
|
580
|
+
private previousBackground: Color | null | Texture = null;
|
|
581
|
+
private previousEnvironment: Texture | null = null;
|
|
582
|
+
|
|
583
|
+
private sessionRoot: WebARSessionRoot | null = null;
|
|
584
|
+
private _previousParent: Object3D | null = null;
|
|
585
|
+
// we need this in case the session root is on the same object as the webxr component
|
|
586
|
+
// so if we disable the session root we attach the webxr component to this temporary object
|
|
587
|
+
// to still receive updates
|
|
588
|
+
private static tempWebXRObject: Object3D;
|
|
589
|
+
|
|
590
|
+
private get context() { return this.webxr.context; }
|
|
591
|
+
|
|
592
|
+
constructor(webxr: WebXR) {
|
|
593
|
+
this._webxr = webxr;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
private arDomOverlay: HTMLElement | null = null;
|
|
597
|
+
private arOverlayElement: INeedleEngineComponent | HTMLElement | null = null;
|
|
598
|
+
private noHitTestAvailable: boolean = false;
|
|
599
|
+
private didPlaceARSessionRoot: boolean = false;
|
|
600
|
+
|
|
601
|
+
getAROverlayContainer(): HTMLElement | null {
|
|
602
|
+
this.arDomOverlay = this.webxr.context.domElement as HTMLElement;
|
|
603
|
+
// for react cases we dont have an Engine Element
|
|
604
|
+
const element: any = this.arDomOverlay;
|
|
605
|
+
if (element.getAROverlayContainer)
|
|
606
|
+
this.arOverlayElement = element.getAROverlayContainer();
|
|
607
|
+
else this.arOverlayElement = this.arDomOverlay;
|
|
608
|
+
return this.arOverlayElement;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
setReticleActive(active: boolean) {
|
|
612
|
+
this.reticleActive = active;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
async onBegin(session: XRSession) {
|
|
616
|
+
const context = this.webxr.context;
|
|
617
|
+
this.reticleActive = true;
|
|
618
|
+
this.didPlaceARSessionRoot = false;
|
|
619
|
+
this.getAROverlayContainer();
|
|
620
|
+
|
|
621
|
+
const deviceType = isQuest() ? ControllerType.PhysicalDevice : ControllerType.Touch;
|
|
622
|
+
const controllerCount = deviceType === ControllerType.Touch ? 4 : 2;
|
|
623
|
+
for (let i = 0; i < controllerCount; i++) {
|
|
624
|
+
WebXRController.Create(this.webxr, i, this.webxr.gameObject as GameObject, deviceType)
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (!this.sessionRoot || this.sessionRoot.destroyed || !this.sessionRoot.activeAndEnabled)
|
|
628
|
+
this.sessionRoot = GameObject.findObjectOfType(WebARSessionRoot, context);
|
|
629
|
+
if (!this.sessionRoot) {
|
|
630
|
+
// TODO: adding it on the scene directly doesnt work (probably because then everything in the scene is disabled including this component). See code a bit furhter below where we add this component to a temporary object inside the scene
|
|
631
|
+
const obj = this.webxr.gameObject;
|
|
632
|
+
this.sessionRoot = GameObject.addNewComponent(obj, WebARSessionRoot);
|
|
633
|
+
console.warn("WebAR: No ARSessionRoot found, creating one automatically on the WebXR object");
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
this.previousBackground = context.scene.background;
|
|
637
|
+
this.previousEnvironment = context.scene.environment;
|
|
638
|
+
context.scene.background = null;
|
|
639
|
+
|
|
640
|
+
session.requestReferenceSpace('viewer').then((referenceSpace) => {
|
|
641
|
+
session.requestHitTestSource?.call(session, { space: referenceSpace })?.then((source) => {
|
|
642
|
+
this.hitTestSource = source;
|
|
643
|
+
}).catch((err) => {
|
|
644
|
+
this.noHitTestAvailable = true;
|
|
645
|
+
console.warn("WebXR: Hit test not supported", err);
|
|
646
|
+
});
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
if (!this.reticle && this.sessionRoot) {
|
|
650
|
+
this.reticle = new Mesh(
|
|
651
|
+
new RingGeometry(0.07, 0.09, 32).rotateX(- Math.PI / 2),
|
|
652
|
+
new MeshBasicMaterial()
|
|
653
|
+
);
|
|
654
|
+
this.reticle.name = "AR Placement reticle";
|
|
655
|
+
this.reticle.matrixAutoUpdate = false;
|
|
656
|
+
this.reticle.visible = false;
|
|
657
|
+
|
|
658
|
+
// create AR reticle parent to allow WebXRSessionRoot to be translated, rotated or scaled
|
|
659
|
+
this.reticleParent = new Object3D();
|
|
660
|
+
this.reticleParent.name = "AR Reticle Parent";
|
|
661
|
+
this.reticleParent.matrixAutoUpdate = false;
|
|
662
|
+
this.reticleParent.add(this.reticle);
|
|
663
|
+
// this.reticleParent.matrix.copy(this.sessionRoot.gameObject.matrixWorld);
|
|
664
|
+
|
|
665
|
+
if (this.webxr.scene) {
|
|
666
|
+
this.context.scene.add(this.reticleParent);
|
|
667
|
+
// this.context.scene.add(this.reticle);
|
|
668
|
+
this.context.scene.visible = true;
|
|
669
|
+
}
|
|
670
|
+
else console.warn("Could not found WebXR Rig");
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
this._previousParent = this.webxr.gameObject;
|
|
674
|
+
if (!WebAR.tempWebXRObject) WebAR.tempWebXRObject = new Object3D();
|
|
675
|
+
this.context.scene.add(WebAR.tempWebXRObject);
|
|
676
|
+
GameObject.addComponent(WebAR.tempWebXRObject as GameObject, this.webxr);
|
|
677
|
+
|
|
678
|
+
if (this.sessionRoot) {
|
|
679
|
+
this.sessionRoot.webAR = this;
|
|
680
|
+
this.sessionRoot?.onBegin(session);
|
|
681
|
+
}
|
|
682
|
+
else console.warn("No WebARSessionRoot found in scene")
|
|
683
|
+
|
|
684
|
+
const eng = this.context.domElement as INeedleEngineComponent;
|
|
685
|
+
eng?.onEnterAR?.call(eng, session, this.arOverlayElement!);
|
|
686
|
+
|
|
687
|
+
this.context.mainCameraComponent?.applyClearFlagsIfIsActiveCamera();
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
onEnd(session: XRSession) {
|
|
691
|
+
if (this._previousParent) {
|
|
692
|
+
GameObject.addComponent(this._previousParent as GameObject, this.webxr);
|
|
693
|
+
this._previousParent = null;
|
|
694
|
+
}
|
|
695
|
+
this.hitTestSource = null;
|
|
696
|
+
const context = this.webxr.context;
|
|
697
|
+
context.scene.background = this.previousBackground;
|
|
698
|
+
context.scene.environment = this.previousEnvironment;
|
|
699
|
+
if (this.sessionRoot) {
|
|
700
|
+
this.sessionRoot.onEnd(this.webxr.Rig, session);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
const el = this.context.domElement as INeedleEngineComponent;
|
|
704
|
+
el.onExitAR?.call(el, session);
|
|
705
|
+
|
|
706
|
+
this.context.mainCameraComponent?.applyClearFlagsIfIsActiveCamera();
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
onUpdate(session: XRSession, frame: XRFrame) {
|
|
710
|
+
|
|
711
|
+
if (this.noHitTestAvailable === true) {
|
|
712
|
+
if (this.reticle)
|
|
713
|
+
this.reticle.visible = false;
|
|
714
|
+
if (!this.didPlaceARSessionRoot) {
|
|
715
|
+
this.didPlaceARSessionRoot = true;
|
|
716
|
+
const rig = this.webxr.Rig;
|
|
717
|
+
const placementMatrix = arPlacementWithoutHitTestMatrix.clone();
|
|
718
|
+
// if (rig) {
|
|
719
|
+
// const positionFromRig = new Vector3(0, 0, 0).add(rig.position).divideScalar(this.sessionRoot?.arScale ?? 1);
|
|
720
|
+
// placementMatrix.multiply(new Matrix4().makeTranslation(positionFromRig.x, positionFromRig.y, positionFromRig.z));
|
|
721
|
+
// // placementMatrix.setPosition(positionFromRig);
|
|
722
|
+
// }
|
|
723
|
+
this.sessionRoot?.placeAt(rig, placementMatrix);
|
|
724
|
+
}
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
if (!this.hitTestSource) return;
|
|
729
|
+
const hitTestResults = frame.getHitTestResults(this.hitTestSource);
|
|
730
|
+
if (hitTestResults.length) {
|
|
731
|
+
const hit = hitTestResults[0];
|
|
732
|
+
const referenceSpace = this.webxr.context.renderer.xr.getReferenceSpace();
|
|
733
|
+
if (referenceSpace) {
|
|
734
|
+
const pose = hit.getPose(referenceSpace);
|
|
735
|
+
|
|
736
|
+
if (this.sessionRoot) {
|
|
737
|
+
const didPlace = this.sessionRoot.onUpdate(this.webxr.Rig, session, hit, pose);
|
|
738
|
+
this.didPlaceARSessionRoot = didPlace;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
if (this.reticle) {
|
|
742
|
+
this.reticle.visible = this.reticleActive && this._webxr.allowARPlacementReticle;
|
|
743
|
+
if (this.reticleActive) {
|
|
744
|
+
if (pose) {
|
|
745
|
+
const matrix = pose.transform.matrix;
|
|
746
|
+
this.reticle.matrix.fromArray(matrix);
|
|
747
|
+
if (this.webxr.Rig)
|
|
748
|
+
this.reticle.matrix.premultiply(this.webxr.Rig.matrix);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
} else {
|
|
755
|
+
this.sessionRoot?.onUpdate(this.webxr.Rig, session, null, null);
|
|
756
|
+
if (this.reticle)
|
|
757
|
+
this.reticle.visible = false;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
762
|
const arPlacementWithoutHitTestMatrix = new Matrix4().identity().makeTranslation(0, 0, 0);
|