@needle-tools/engine 5.1.0-canary.db0c38f → 5.1.0-canary.e6680fa
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/.needle/generated/needle-bindings.gen.d.ts +5 -0
- package/CHANGELOG.md +133 -1
- package/SKILL.md +4 -1
- package/components.needle.json +1 -1
- package/dist/needle-engine.bundle-Bl_hyH5G.umd.cjs +1734 -0
- package/dist/needle-engine.bundle-Cduc1gj6.min.js +1734 -0
- package/dist/{needle-engine.bundle-B29kieh0.js → needle-engine.bundle-DNcqT8nJ.js} +13770 -12741
- package/dist/needle-engine.d.ts +1628 -402
- package/dist/needle-engine.js +591 -586
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/three.js +1 -0
- package/dist/three.min.js +21 -21
- package/dist/three.umd.cjs +16 -16
- package/lib/engine/api.d.ts +9 -2
- package/lib/engine/api.js +7 -1
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/codegen/register_types.js +10 -18
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/debug/debug_spatial_console.d.ts +2 -0
- package/lib/engine/debug/debug_spatial_console.js +10 -7
- package/lib/engine/debug/debug_spatial_console.js.map +1 -1
- package/lib/engine/engine_addressables.d.ts +2 -0
- package/lib/engine/engine_addressables.js +6 -3
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_audio.d.ts +68 -0
- package/lib/engine/engine_audio.js +172 -0
- package/lib/engine/engine_audio.js.map +1 -1
- package/lib/engine/engine_camera.fit.js +16 -4
- package/lib/engine/engine_camera.fit.js.map +1 -1
- package/lib/engine/engine_components.js +1 -1
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_context.d.ts +41 -27
- package/lib/engine/engine_context.js +71 -30
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_context_eventbus.d.ts +47 -0
- package/lib/engine/engine_context_eventbus.js +47 -0
- package/lib/engine/engine_context_eventbus.js.map +1 -0
- package/lib/engine/engine_disposable.d.ts +172 -0
- package/lib/engine/engine_disposable.js +136 -0
- package/lib/engine/engine_disposable.js.map +1 -0
- package/lib/engine/engine_gameobject.d.ts +1 -10
- package/lib/engine/engine_gameobject.js +22 -120
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_gltf_builtin_components.js +7 -69
- package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
- package/lib/engine/engine_init.js +16 -1
- package/lib/engine/engine_init.js.map +1 -1
- package/lib/engine/engine_input.d.ts +24 -5
- package/lib/engine/engine_input.js +3 -2
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_instantiate_resolve.d.ts +42 -0
- package/lib/engine/engine_instantiate_resolve.js +372 -0
- package/lib/engine/engine_instantiate_resolve.js.map +1 -0
- package/lib/engine/engine_license.d.ts +8 -6
- package/lib/engine/engine_license.js +195 -59
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_lifecycle_functions_internal.js +5 -0
- package/lib/engine/engine_lifecycle_functions_internal.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.js +7 -4
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_networking.d.ts +51 -37
- package/lib/engine/engine_networking.js +132 -82
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine/engine_networking.transport.websocket.d.ts +15 -0
- package/lib/engine/engine_networking.transport.websocket.js +38 -0
- package/lib/engine/engine_networking.transport.websocket.js.map +1 -0
- package/lib/engine/engine_networking_blob.js +4 -4
- package/lib/engine/engine_networking_blob.js.map +1 -1
- package/lib/engine/engine_networking_instantiate.js +2 -2
- package/lib/engine/engine_networking_instantiate.js.map +1 -1
- package/lib/engine/engine_networking_types.d.ts +39 -1
- package/lib/engine/engine_networking_types.js +7 -0
- package/lib/engine/engine_networking_types.js.map +1 -1
- package/lib/engine/engine_physics_rapier.d.ts +21 -3
- package/lib/engine/engine_physics_rapier.js +94 -25
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_pmrem.js +53 -5
- package/lib/engine/engine_pmrem.js.map +1 -1
- package/lib/engine/engine_scenedata.d.ts +13 -17
- package/lib/engine/engine_scenedata.js +58 -31
- package/lib/engine/engine_scenedata.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.d.ts +10 -16
- package/lib/engine/engine_serialization_builtin_serializer.js +56 -46
- package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
- package/lib/engine/engine_serialization_core.d.ts +1 -0
- package/lib/engine/engine_serialization_core.js +7 -0
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_ssr.d.ts +2 -0
- package/lib/engine/engine_ssr.js +20 -0
- package/lib/engine/engine_ssr.js.map +1 -1
- package/lib/engine/engine_types.d.ts +31 -11
- package/lib/engine/engine_types.js +1 -1
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_util_decorator.js +7 -2
- package/lib/engine/engine_util_decorator.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +1 -1
- package/lib/engine/engine_utils.js +19 -5
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/engine_utils_format.js +20 -14
- package/lib/engine/engine_utils_format.js.map +1 -1
- package/lib/engine/engine_utils_qrcode.js +2 -2
- package/lib/engine/engine_utils_qrcode.js.map +1 -1
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
- package/lib/engine/webcomponents/jsx.d.ts +51 -0
- package/lib/engine/webcomponents/logo-element.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +3 -4
- package/lib/engine/webcomponents/needle menu/needle-menu.js +6 -6
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-button.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.d.ts +10 -4
- package/lib/engine/webcomponents/needle-engine.js +3 -3
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.loading.js +2 -2
- package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.d.ts +3 -2
- package/lib/engine/xr/NeedleXRSession.js +50 -14
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine/xr/TempXRContext.js +2 -2
- package/lib/engine/xr/TempXRContext.js.map +1 -1
- package/lib/engine/xr/events.d.ts +1 -1
- package/lib/engine/xr/events.js.map +1 -1
- package/lib/engine-components/Animation.js +17 -16
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/AnimationBuilder.d.ts +158 -0
- package/lib/engine-components/AnimationBuilder.js +305 -0
- package/lib/engine-components/AnimationBuilder.js.map +1 -0
- package/lib/engine-components/Animator.d.ts +6 -0
- package/lib/engine-components/Animator.js +23 -13
- package/lib/engine-components/Animator.js.map +1 -1
- package/lib/engine-components/AnimatorController.builder.d.ts +191 -0
- package/lib/engine-components/AnimatorController.builder.js +263 -0
- package/lib/engine-components/AnimatorController.builder.js.map +1 -0
- package/lib/engine-components/AnimatorController.d.ts +4 -119
- package/lib/engine-components/AnimatorController.js +37 -233
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/AudioSource.d.ts +19 -3
- package/lib/engine-components/AudioSource.js +121 -68
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/Camera.d.ts +6 -1
- package/lib/engine-components/Camera.js +16 -3
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/CameraUtils.js +14 -6
- package/lib/engine-components/CameraUtils.js.map +1 -1
- package/lib/engine-components/Collider.d.ts +18 -9
- package/lib/engine-components/Collider.js +61 -14
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/Component.d.ts +72 -9
- package/lib/engine-components/Component.js +114 -10
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/ContactShadows.d.ts +1 -0
- package/lib/engine-components/ContactShadows.js +14 -1
- package/lib/engine-components/ContactShadows.js.map +1 -1
- package/lib/engine-components/DragControls.d.ts +7 -0
- package/lib/engine-components/DragControls.js +19 -7
- package/lib/engine-components/DragControls.js.map +1 -1
- package/lib/engine-components/DropListener.js +4 -0
- package/lib/engine-components/DropListener.js.map +1 -1
- package/lib/engine-components/EventList.d.ts +31 -9
- package/lib/engine-components/EventList.js +37 -76
- package/lib/engine-components/EventList.js.map +1 -1
- package/lib/engine-components/Joints.d.ts +4 -2
- package/lib/engine-components/Joints.js +19 -3
- package/lib/engine-components/Joints.js.map +1 -1
- package/lib/engine-components/Light.d.ts +6 -8
- package/lib/engine-components/Light.js +48 -27
- package/lib/engine-components/Light.js.map +1 -1
- package/lib/engine-components/Networking.d.ts +1 -1
- package/lib/engine-components/Networking.js +1 -1
- package/lib/engine-components/OrbitControls.d.ts +1 -2
- package/lib/engine-components/OrbitControls.js +37 -14
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.js +2 -0
- package/lib/engine-components/ReflectionProbe.js.map +1 -1
- package/lib/engine-components/RigidBody.d.ts +12 -4
- package/lib/engine-components/RigidBody.js +18 -4
- package/lib/engine-components/RigidBody.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.js +3 -0
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/SeeThrough.js +2 -2
- package/lib/engine-components/SeeThrough.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +8 -2
- package/lib/engine-components/VideoPlayer.js +42 -19
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/Voip.d.ts +16 -7
- package/lib/engine-components/Voip.js +90 -53
- package/lib/engine-components/Voip.js.map +1 -1
- package/lib/engine-components/api.d.ts +3 -1
- package/lib/engine-components/api.js +3 -1
- package/lib/engine-components/api.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +7 -13
- package/lib/engine-components/codegen/components.js +7 -13
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
- package/lib/engine-components/postprocessing/VolumeParameter.d.ts +2 -0
- package/lib/engine-components/postprocessing/VolumeParameter.js +4 -1
- package/lib/engine-components/postprocessing/VolumeParameter.js.map +1 -1
- package/lib/engine-components/timeline/PlayableDirector.d.ts +21 -11
- package/lib/engine-components/timeline/PlayableDirector.js +75 -67
- package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
- package/lib/engine-components/timeline/SignalAsset.d.ts +3 -1
- package/lib/engine-components/timeline/SignalAsset.js +1 -0
- package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
- package/lib/engine-components/timeline/TimelineBuilder.d.ts +413 -0
- package/lib/engine-components/timeline/TimelineBuilder.js +506 -0
- package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -0
- package/lib/engine-components/timeline/TimelineModels.d.ts +2 -1
- package/lib/engine-components/timeline/TimelineModels.js +3 -0
- package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
- package/lib/engine-components/timeline/TimelineTracks.d.ts +37 -6
- package/lib/engine-components/timeline/TimelineTracks.js +92 -26
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/lib/engine-components/timeline/index.d.ts +2 -1
- package/lib/engine-components/timeline/index.js +2 -0
- package/lib/engine-components/timeline/index.js.map +1 -1
- package/lib/engine-components/ui/Canvas.d.ts +1 -1
- package/lib/engine-components/ui/Canvas.js +2 -8
- package/lib/engine-components/ui/Canvas.js.map +1 -1
- package/lib/engine-components/ui/Text.d.ts +1 -0
- package/lib/engine-components/ui/Text.js +10 -7
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/engine-components/web/CursorFollow.d.ts +0 -1
- package/lib/engine-components/web/CursorFollow.js +21 -13
- package/lib/engine-components/web/CursorFollow.js.map +1 -1
- package/lib/engine-components/webxr/WebXRImageTracking.d.ts +62 -1
- package/lib/engine-components/webxr/WebXRImageTracking.js +59 -2
- package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
- package/lib/needle-engine.d.ts +2 -0
- package/lib/needle-engine.js +2 -0
- package/lib/needle-engine.js.map +1 -1
- package/package.json +4 -84
- package/plugins/common/cloud.js +6 -1
- package/plugins/common/license.js +55 -12
- package/plugins/common/worker.js +9 -4
- package/plugins/dts-generator/dts.codegen.js +255 -50
- package/plugins/dts-generator/dts.scan.js +37 -9
- package/plugins/dts-generator/dts.writer.js +1 -1
- package/plugins/dts-generator/glb.discovery.js +140 -23
- package/plugins/dts-generator/glb.extractor.js +48 -8
- package/plugins/dts-generator/glb.reader.js +80 -27
- package/plugins/dts-generator/index.js +1 -1
- package/plugins/types/needle-bindings.d.ts +25 -14
- package/plugins/types/userconfig.d.ts +16 -1
- package/plugins/vite/asap.js +18 -9
- package/plugins/vite/build-pipeline.js +57 -20
- package/plugins/vite/dependencies.js +29 -10
- package/plugins/vite/dependency-watcher.d.ts +2 -2
- package/plugins/vite/dependency-watcher.js +5 -6
- package/plugins/vite/drop.d.ts +2 -2
- package/plugins/vite/drop.js +3 -4
- package/plugins/vite/dts-generator.d.ts +2 -2
- package/plugins/vite/dts-generator.js +43 -9
- package/plugins/vite/editor-connection.js +3 -3
- package/plugins/vite/index.d.ts +9 -3
- package/plugins/vite/index.js +23 -10
- package/plugins/vite/license.js +42 -7
- package/plugins/vite/local-files-core.js +3 -3
- package/plugins/vite/local-files-utils.d.ts +3 -1
- package/plugins/vite/local-files-utils.js +29 -5
- package/plugins/vite/meta.js +4 -2
- package/plugins/vite/poster.d.ts +2 -2
- package/plugins/vite/poster.js +3 -5
- package/plugins/vite/reload.d.ts +2 -2
- package/plugins/vite/reload.js +23 -23
- package/plugins/vite/server.js +2 -1
- package/src/engine/api.ts +12 -2
- package/src/engine/codegen/register_types.ts +10 -18
- package/src/engine/debug/debug_spatial_console.ts +10 -7
- package/src/engine/engine_addressables.ts +6 -3
- package/src/engine/engine_audio.ts +184 -0
- package/src/engine/engine_camera.fit.ts +15 -4
- package/src/engine/engine_components.ts +1 -1
- package/src/engine/engine_context.ts +85 -38
- package/src/engine/engine_context_eventbus.ts +73 -0
- package/src/engine/engine_disposable.ts +214 -0
- package/src/engine/engine_gameobject.ts +54 -159
- package/src/engine/engine_gltf_builtin_components.ts +7 -76
- package/src/engine/engine_init.ts +15 -1
- package/src/engine/engine_input.ts +28 -7
- package/src/engine/engine_instantiate_resolve.ts +407 -0
- package/src/engine/engine_license.ts +209 -61
- package/src/engine/engine_lifecycle_functions_internal.ts +7 -0
- package/src/engine/engine_mainloop_utils.ts +7 -4
- package/src/engine/engine_networking.transport.websocket.ts +45 -0
- package/src/engine/engine_networking.ts +161 -137
- package/src/engine/engine_networking_blob.ts +4 -4
- package/src/engine/engine_networking_instantiate.ts +2 -2
- package/src/engine/engine_networking_types.ts +41 -1
- package/src/engine/engine_physics_rapier.ts +102 -33
- package/src/engine/engine_pmrem.ts +56 -6
- package/src/engine/engine_scenedata.ts +56 -30
- package/src/engine/engine_serialization_builtin_serializer.ts +64 -52
- package/src/engine/engine_serialization_core.ts +9 -0
- package/src/engine/engine_ssr.ts +29 -3
- package/src/engine/engine_types.ts +48 -27
- package/src/engine/engine_util_decorator.ts +7 -2
- package/src/engine/engine_utils.ts +16 -5
- package/src/engine/engine_utils_format.ts +20 -14
- package/src/engine/engine_utils_qrcode.ts +2 -2
- package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
- package/src/engine/webcomponents/jsx.d.ts +51 -0
- package/src/engine/webcomponents/logo-element.ts +1 -0
- package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
- package/src/engine/webcomponents/needle menu/needle-menu.ts +8 -7
- package/src/engine/webcomponents/needle-button.ts +1 -0
- package/src/engine/webcomponents/needle-engine.loading.ts +6 -6
- package/src/engine/webcomponents/needle-engine.ts +13 -6
- package/src/engine/xr/NeedleXRSession.ts +48 -13
- package/src/engine/xr/TempXRContext.ts +2 -2
- package/src/engine/xr/events.ts +1 -1
- package/src/engine-components/Animation.ts +19 -16
- package/src/engine-components/AnimationBuilder.ts +472 -0
- package/src/engine-components/Animator.ts +24 -12
- package/src/engine-components/AnimatorController.builder.ts +387 -0
- package/src/engine-components/AnimatorController.ts +24 -292
- package/src/engine-components/AudioSource.ts +130 -79
- package/src/engine-components/Camera.ts +16 -3
- package/src/engine-components/CameraUtils.ts +12 -5
- package/src/engine-components/Collider.ts +66 -18
- package/src/engine-components/Component.ts +118 -20
- package/src/engine-components/ContactShadows.ts +15 -1
- package/src/engine-components/DragControls.ts +18 -11
- package/src/engine-components/DropListener.ts +4 -0
- package/src/engine-components/EventList.ts +45 -83
- package/src/engine-components/Joints.ts +20 -4
- package/src/engine-components/Light.ts +49 -27
- package/src/engine-components/Networking.ts +1 -1
- package/src/engine-components/OrbitControls.ts +42 -16
- package/src/engine-components/ReflectionProbe.ts +2 -0
- package/src/engine-components/RigidBody.ts +18 -4
- package/src/engine-components/SceneSwitcher.ts +3 -0
- package/src/engine-components/SeeThrough.ts +2 -2
- package/src/engine-components/VideoPlayer.ts +40 -17
- package/src/engine-components/Voip.ts +88 -53
- package/src/engine-components/api.ts +3 -1
- package/src/engine-components/codegen/components.ts +7 -13
- package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
- package/src/engine-components/postprocessing/VolumeParameter.ts +4 -1
- package/src/engine-components/timeline/PlayableDirector.ts +83 -81
- package/src/engine-components/timeline/SignalAsset.ts +4 -1
- package/src/engine-components/timeline/TimelineBuilder.ts +824 -0
- package/src/engine-components/timeline/TimelineModels.ts +5 -1
- package/src/engine-components/timeline/TimelineTracks.ts +96 -27
- package/src/engine-components/timeline/index.ts +2 -1
- package/src/engine-components/ui/Canvas.ts +2 -8
- package/src/engine-components/ui/Text.ts +12 -8
- package/src/engine-components/web/CursorFollow.ts +21 -14
- package/src/engine-components/webxr/WebXRImageTracking.ts +79 -7
- package/src/needle-engine.ts +3 -0
- package/dist/needle-engine.bundle-Dq0Ly8fW.umd.cjs +0 -1732
- package/dist/needle-engine.bundle-YnpzzOPL.min.js +0 -1732
- package/lib/engine-components/AvatarLoader.d.ts +0 -80
- package/lib/engine-components/AvatarLoader.js +0 -232
- package/lib/engine-components/AvatarLoader.js.map +0 -1
- package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +0 -11
- package/lib/engine-components/avatar/AvatarBlink_Simple.js +0 -77
- package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +0 -1
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +0 -14
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +0 -69
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +0 -1
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +0 -29
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +0 -122
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +0 -1
- package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +0 -15
- package/lib/engine-components/avatar/Avatar_MouthShapes.js +0 -80
- package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +0 -1
- package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +0 -9
- package/lib/engine-components/avatar/Avatar_MustacheShake.js +0 -30
- package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +0 -1
- package/src/engine-components/AvatarLoader.ts +0 -264
- package/src/engine-components/avatar/AvatarBlink_Simple.ts +0 -70
- package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +0 -64
- package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +0 -140
- package/src/engine-components/avatar/Avatar_MouthShapes.ts +0 -84
- package/src/engine-components/avatar/Avatar_MustacheShake.ts +0 -32
- package/src/vite-env.d.ts +0 -16
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Ball, Collider, ColliderDesc, Cuboid, EventQueue, QueryFilterFlags, Ray, RigidBody, RigidBodyDesc, World } from '@dimforge/rapier3d-compat';
|
|
1
|
+
import type { Ball, Collider, ColliderDesc, Cuboid, EventQueue, ImpulseJoint, QueryFilterFlags, Ray, RigidBody, RigidBodyDesc, World } from '@dimforge/rapier3d-compat';
|
|
2
2
|
import { BufferAttribute, BufferGeometry, InterleavedBufferAttribute, LineBasicMaterial, LineSegments, Matrix4, Mesh, Object3D, Quaternion, Vector3, Vector4Like } from 'three'
|
|
3
3
|
import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'
|
|
4
4
|
|
|
@@ -402,11 +402,16 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
402
402
|
filterGroups?: number,
|
|
403
403
|
/** Return false to ignore this collider */
|
|
404
404
|
filterPredicate?: (c: ICollider) => boolean,
|
|
405
|
-
/** When enabled the hit object's layer will be tested. If layer 2 is enabled the object will be ignored (Layer 2 == IgnoreRaycast)
|
|
405
|
+
/** When enabled the hit object's layer will be tested. If layer 2 is enabled the object will be ignored (Layer 2 == IgnoreRaycast)
|
|
406
406
|
* If not set the raycast will ignore objects in the IgnoreRaycast layer (default: true)
|
|
407
|
-
* @default undefined
|
|
407
|
+
* @default undefined
|
|
408
408
|
*/
|
|
409
|
-
useIgnoreRaycastLayer?: boolean
|
|
409
|
+
useIgnoreRaycastLayer?: boolean,
|
|
410
|
+
/** When true, trigger/sensor colliders will be included in the raycast results.
|
|
411
|
+
* By default trigger colliders are skipped.
|
|
412
|
+
* @default false
|
|
413
|
+
*/
|
|
414
|
+
includeTriggers?: boolean,
|
|
410
415
|
})
|
|
411
416
|
: null | { point: Vector3, collider: ICollider } {
|
|
412
417
|
|
|
@@ -428,6 +433,8 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
428
433
|
|
|
429
434
|
const hit = this.world?.castRay(ray, maxDistance, solid, options?.queryFilterFlags, options?.filterGroups, undefined, undefined, (c) => {
|
|
430
435
|
const component = c[$componentKey];
|
|
436
|
+
// Skip trigger/sensor colliders unless explicitly included
|
|
437
|
+
if (options?.includeTriggers !== true && component?.isTrigger) return false;
|
|
431
438
|
if (options?.filterPredicate) return options.filterPredicate(component);
|
|
432
439
|
if (options?.useIgnoreRaycastLayer !== false) {
|
|
433
440
|
// ignore objects in the IgnoreRaycast=2 layer
|
|
@@ -453,11 +460,16 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
453
460
|
filterGroups?: number,
|
|
454
461
|
/** Return false to ignore this collider */
|
|
455
462
|
filterPredicate?: (c: ICollider) => boolean,
|
|
456
|
-
/** When enabled the hit object's layer will be tested. If layer 2 is enabled the object will be ignored (Layer 2 == IgnoreRaycast)
|
|
463
|
+
/** When enabled the hit object's layer will be tested. If layer 2 is enabled the object will be ignored (Layer 2 == IgnoreRaycast)
|
|
457
464
|
* If not set the raycast will ignore objects in the IgnoreRaycast layer (default: true)
|
|
458
|
-
* @default undefined
|
|
465
|
+
* @default undefined
|
|
459
466
|
*/
|
|
460
|
-
useIgnoreRaycastLayer?: boolean
|
|
467
|
+
useIgnoreRaycastLayer?: boolean,
|
|
468
|
+
/** When true, trigger/sensor colliders will be included in the raycast results.
|
|
469
|
+
* By default trigger colliders are skipped.
|
|
470
|
+
* @default false
|
|
471
|
+
*/
|
|
472
|
+
includeTriggers?: boolean,
|
|
461
473
|
})
|
|
462
474
|
: null | { point: Vector3, normal: Vector3, collider: ICollider } {
|
|
463
475
|
|
|
@@ -478,6 +490,8 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
478
490
|
|
|
479
491
|
const hit = this.world?.castRayAndGetNormal(ray, maxDistance, solid, options?.queryFilterFlags, options?.filterGroups, undefined, undefined, (c) => {
|
|
480
492
|
const component = c[$componentKey];
|
|
493
|
+
// Skip trigger/sensor colliders unless explicitly included
|
|
494
|
+
if (options?.includeTriggers !== true && component?.isTrigger) return false;
|
|
481
495
|
if (options?.filterPredicate) return options.filterPredicate(component);
|
|
482
496
|
if (options?.useIgnoreRaycastLayer !== false) {
|
|
483
497
|
// ignore objects in the IgnoreRaycast=2 layer
|
|
@@ -690,12 +704,26 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
690
704
|
}
|
|
691
705
|
}
|
|
692
706
|
|
|
693
|
-
|
|
707
|
+
/** Tears down the physics world and frees all WASM resources.
|
|
708
|
+
* After calling this, the world will be re-created on next use. */
|
|
709
|
+
dispose() {
|
|
694
710
|
this._meshCache.clear();
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
711
|
+
this.eventQueue?.free();
|
|
712
|
+
this._world?.free();
|
|
713
|
+
// Reset initialization state so the world can be recreated
|
|
714
|
+
this._world = undefined;
|
|
715
|
+
this.eventQueue = undefined;
|
|
716
|
+
this.collisionHandler = undefined;
|
|
717
|
+
this._isInitialized = false;
|
|
718
|
+
this._hasCreatedWorld = false;
|
|
719
|
+
this._initializePromise = undefined;
|
|
720
|
+
this.objects.length = 0;
|
|
721
|
+
this.bodies.length = 0;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/** @deprecated Use {@link dispose} instead. */
|
|
725
|
+
clearCaches() {
|
|
726
|
+
this.dispose();
|
|
699
727
|
}
|
|
700
728
|
|
|
701
729
|
async addBoxCollider(collider: ICollider, size: Vector3) {
|
|
@@ -981,13 +1009,17 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
981
1009
|
}
|
|
982
1010
|
}
|
|
983
1011
|
|
|
984
|
-
//
|
|
985
|
-
//
|
|
1012
|
+
// When using explicit mass (autoMass=false), set collider mass to near-zero
|
|
1013
|
+
// so Rapier doesn't contribute mass from the collider shape.
|
|
1014
|
+
// The actual mass is applied via setAdditionalMass on the rigidbody instead.
|
|
1015
|
+
// Note: setMass overrides any prior setDensity call (they are mutually exclusive in Rapier)
|
|
986
1016
|
// https://rapier.rs/docs/user_guides/javascript/rigid_bodies#mass-properties
|
|
987
1017
|
if (collider.attachedRigidbody?.autoMass === false) {
|
|
988
|
-
desc.setDensity(.000001);
|
|
989
1018
|
desc.setMass(.000001);
|
|
990
1019
|
}
|
|
1020
|
+
else if (collider.density != null) {
|
|
1021
|
+
desc.setDensity(collider.density);
|
|
1022
|
+
}
|
|
991
1023
|
|
|
992
1024
|
try {
|
|
993
1025
|
const col = this.world.createCollider(desc, rigidBody);
|
|
@@ -1130,6 +1162,11 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
1130
1162
|
break;
|
|
1131
1163
|
}
|
|
1132
1164
|
|
|
1165
|
+
// Update density if specified (setDensity auto-recomputes parent body mass)
|
|
1166
|
+
if (col.density != null) {
|
|
1167
|
+
collider.setDensity(col.density);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1133
1170
|
if (sizeHasChanged) {
|
|
1134
1171
|
const rb = col.attachedRigidbody;
|
|
1135
1172
|
if (rb?.autoMass) {
|
|
@@ -1161,7 +1198,8 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
1161
1198
|
rigidbody.setAdditionalMass(0, false);
|
|
1162
1199
|
for (let i = 0; i < rigidbody.numColliders(); i++) {
|
|
1163
1200
|
const col = rigidbody.collider(i);
|
|
1164
|
-
col
|
|
1201
|
+
const colliderComponent = col[$componentKey] as ICollider | null;
|
|
1202
|
+
col.setDensity(colliderComponent?.density ?? 1);
|
|
1165
1203
|
}
|
|
1166
1204
|
rigidbody.recomputeMassPropertiesFromColliders();
|
|
1167
1205
|
}
|
|
@@ -1477,16 +1515,21 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
1477
1515
|
|
|
1478
1516
|
private static centerConnectionPos = { x: 0, y: 0, z: 0 };
|
|
1479
1517
|
private static centerConnectionRot = { x: 0, y: 0, z: 0, w: 1 };
|
|
1518
|
+
private _jointTempMatrix = new Matrix4();
|
|
1480
1519
|
|
|
1481
1520
|
|
|
1482
|
-
|
|
1483
|
-
|
|
1521
|
+
async addFixedJoint(body1: IRigidbody, body2: IRigidbody): Promise<ImpulseJoint | null> {
|
|
1522
|
+
if (!this._isInitialized) await this.initialize();
|
|
1484
1523
|
if (!this.world) {
|
|
1485
1524
|
console.error("Physics world not initialized");
|
|
1486
|
-
return;
|
|
1525
|
+
return null;
|
|
1487
1526
|
}
|
|
1488
1527
|
const b1 = body1[$bodyKey] as RigidBody;
|
|
1489
1528
|
const b2 = body2[$bodyKey] as RigidBody;
|
|
1529
|
+
if (!b1 || !b2) {
|
|
1530
|
+
console.error("Cannot create fixed joint: one or both physics bodies are not initialized");
|
|
1531
|
+
return null;
|
|
1532
|
+
}
|
|
1490
1533
|
|
|
1491
1534
|
this.calculateJointRelativeMatrices(body1.gameObject, body2.gameObject, this._tempMatrix);
|
|
1492
1535
|
this._tempMatrix.decompose(this._tempPosition, this._tempQuaternion, this._tempScale);
|
|
@@ -1498,41 +1541,67 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
1498
1541
|
const joint = this.world.createImpulseJoint(params, b1, b2, true);
|
|
1499
1542
|
if (debugPhysics)
|
|
1500
1543
|
console.log("ADD FIXED JOINT", joint)
|
|
1544
|
+
return joint;
|
|
1501
1545
|
}
|
|
1502
1546
|
|
|
1503
1547
|
|
|
1504
1548
|
/** The joint prevents any relative movement between two rigid-bodies, except for relative rotations along one axis. This is typically used to simulate wheels, fans, etc. They are characterized by one local anchor as well as one local axis on each rigid-body. */
|
|
1505
|
-
addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: { x: number, y: number, z: number }, axis: { x: number, y: number, z: number }) {
|
|
1549
|
+
async addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: { x: number, y: number, z: number }, axis: { x: number, y: number, z: number }): Promise<ImpulseJoint | null> {
|
|
1550
|
+
if (!this._isInitialized) await this.initialize();
|
|
1506
1551
|
if (!this.world) {
|
|
1507
1552
|
console.error("Physics world not initialized");
|
|
1508
|
-
return;
|
|
1553
|
+
return null;
|
|
1509
1554
|
}
|
|
1510
1555
|
const b1 = body1[$bodyKey] as RigidBody;
|
|
1511
1556
|
const b2 = body2[$bodyKey] as RigidBody;
|
|
1557
|
+
if (!b1 || !b2) {
|
|
1558
|
+
console.error("Cannot create hinge joint: one or both physics bodies are not initialized");
|
|
1559
|
+
return null;
|
|
1560
|
+
}
|
|
1512
1561
|
|
|
1513
1562
|
this.calculateJointRelativeMatrices(body1.gameObject, body2.gameObject, this._tempMatrix);
|
|
1514
|
-
|
|
1563
|
+
// Transform anchor from body1's local space to body2's local space
|
|
1564
|
+
const anchor2 = this._tempPosition.set(anchor.x, anchor.y, anchor.z).applyMatrix4(this._tempMatrix);
|
|
1515
1565
|
|
|
1516
|
-
const params = MODULES.RAPIER_PHYSICS.MODULE.JointData.revolute(anchor,
|
|
1566
|
+
const params = MODULES.RAPIER_PHYSICS.MODULE.JointData.revolute(anchor, anchor2, axis);
|
|
1517
1567
|
const joint = this.world.createImpulseJoint(params, b1, b2, true);
|
|
1518
1568
|
if (debugPhysics)
|
|
1519
1569
|
console.log("ADD HINGE JOINT", joint)
|
|
1570
|
+
return joint;
|
|
1520
1571
|
}
|
|
1521
1572
|
|
|
1522
1573
|
|
|
1574
|
+
removeJoint(joint: ImpulseJoint) {
|
|
1575
|
+
if (!this.world) return;
|
|
1576
|
+
this.world.removeImpulseJoint(joint, true);
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
|
|
1580
|
+
/** Compute the relative transform from body1's local space to body2's local space (W2⁻¹ * W1), ignoring scale. */
|
|
1523
1581
|
private calculateJointRelativeMatrices(body1: IGameObject, body2: IGameObject, mat: Matrix4) {
|
|
1524
1582
|
body1.updateWorldMatrix(true, false);
|
|
1525
1583
|
body2.updateWorldMatrix(true, false);
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
mat
|
|
1584
|
+
|
|
1585
|
+
// Work on copies to avoid mutating the actual world matrices
|
|
1586
|
+
mat.copy(body1.matrixWorld);
|
|
1587
|
+
const w2 = this._jointTempMatrix.copy(body2.matrixWorld);
|
|
1588
|
+
|
|
1589
|
+
// Strip scale by normalizing each column of the upper 3x3
|
|
1590
|
+
this.normalizeMatrixColumns(mat);
|
|
1591
|
+
this.normalizeMatrixColumns(w2);
|
|
1592
|
+
|
|
1593
|
+
// mat = W2^-1 * W1 (body1's frame in body2's local space)
|
|
1594
|
+
mat.premultiply(w2.invert());
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
private normalizeMatrixColumns(m: Matrix4) {
|
|
1598
|
+
const e = m.elements;
|
|
1599
|
+
let len = Math.sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]);
|
|
1600
|
+
if (len > 0) { e[0] /= len; e[1] /= len; e[2] /= len; }
|
|
1601
|
+
len = Math.sqrt(e[4] * e[4] + e[5] * e[5] + e[6] * e[6]);
|
|
1602
|
+
if (len > 0) { e[4] /= len; e[5] /= len; e[6] /= len; }
|
|
1603
|
+
len = Math.sqrt(e[8] * e[8] + e[9] * e[9] + e[10] * e[10]);
|
|
1604
|
+
if (len > 0) { e[8] /= len; e[9] /= len; e[10] /= len; }
|
|
1536
1605
|
}
|
|
1537
1606
|
}
|
|
1538
1607
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createLoaders } from "@needle-tools/gltf-progressive";
|
|
2
2
|
import { CubeUVReflectionMapping, EquirectangularRefractionMapping, SRGBColorSpace, Texture, TextureLoader, WebGLRenderer } from "three";
|
|
3
|
-
import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader";
|
|
4
|
-
import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader";
|
|
5
|
-
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
|
|
3
|
+
import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader.js";
|
|
4
|
+
import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader.js";
|
|
5
|
+
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
|
|
6
6
|
|
|
7
7
|
const running: Map<string, Promise<Texture | null>> = new Map();
|
|
8
8
|
|
|
@@ -37,9 +37,59 @@ async function internalLoadPMREM(url: URL, renderer: WebGLRenderer) {
|
|
|
37
37
|
const pathname = url.pathname;
|
|
38
38
|
const isPMREM_URL: boolean = url.toString().toLowerCase().includes("pmrem") || url.searchParams.get("pmrem") != null;
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
let isEXR = pathname.endsWith(".exr");
|
|
41
|
+
let isHdr = pathname.endsWith(".hdr");
|
|
42
|
+
let isKtx2 = pathname.endsWith(".ktx2");
|
|
43
|
+
|
|
44
|
+
// For URLs that don't carry a recognizable extension (e.g. `blob:` URLs
|
|
45
|
+
// from dropped local files, or signed CDN URLs that elide the filename),
|
|
46
|
+
// sniff Content-Type and a few magic bytes to pick the right loader.
|
|
47
|
+
// EXRLoader / RGBELoader / KTX2Loader vs TextureLoader is not interchangeable —
|
|
48
|
+
// routing EXR binary data through TextureLoader fails outright.
|
|
49
|
+
if (!isEXR && !isHdr && !isKtx2) {
|
|
50
|
+
try {
|
|
51
|
+
const probe = await fetch(url.toString(), {
|
|
52
|
+
method: "GET",
|
|
53
|
+
headers: { range: "bytes=0-15" },
|
|
54
|
+
});
|
|
55
|
+
const contentType = probe.headers.get("content-type")?.toLowerCase() ?? "";
|
|
56
|
+
|
|
57
|
+
// Content-Type wins when it's specific — skip reading the body.
|
|
58
|
+
if (contentType === "image/x-exr" || contentType === "image/aces") {
|
|
59
|
+
isEXR = true;
|
|
60
|
+
}
|
|
61
|
+
else if (contentType === "image/vnd.radiance" || contentType === "image/x-hdr") {
|
|
62
|
+
isHdr = true;
|
|
63
|
+
}
|
|
64
|
+
else if (contentType === "image/ktx2") {
|
|
65
|
+
isKtx2 = true;
|
|
66
|
+
}
|
|
67
|
+
// Otherwise fall back to magic-byte sniffing.
|
|
68
|
+
else {
|
|
69
|
+
const bytes = new Uint8Array(await probe.arrayBuffer());
|
|
70
|
+
if (bytes.length >= 4 && bytes[0] === 0x76 && bytes[1] === 0x2f && bytes[2] === 0x31 && bytes[3] === 0x01) {
|
|
71
|
+
// EXR magic: 0x76 0x2f 0x31 0x01
|
|
72
|
+
isEXR = true;
|
|
73
|
+
}
|
|
74
|
+
else if (bytes.length >= 12
|
|
75
|
+
&& bytes[0] === 0xAB && bytes[1] === 0x4B && bytes[2] === 0x54 && bytes[3] === 0x58
|
|
76
|
+
&& bytes[4] === 0x20 && bytes[5] === 0x32 && bytes[6] === 0x30 && bytes[7] === 0xBB) {
|
|
77
|
+
// KTX2 magic: «KTX 20»\r\n\x1A\n
|
|
78
|
+
isKtx2 = true;
|
|
79
|
+
}
|
|
80
|
+
else if (bytes.length >= 10
|
|
81
|
+
&& bytes[0] === 0x23 && bytes[1] === 0x3F // "#?"
|
|
82
|
+
&& bytes[2] === 0x52 && bytes[3] === 0x41 && bytes[4] === 0x44 && bytes[5] === 0x49 // "RADI"
|
|
83
|
+
&& bytes[6] === 0x41 && bytes[7] === 0x4E && bytes[8] === 0x43 && bytes[9] === 0x45) { // "ANCE"
|
|
84
|
+
// Radiance HDR header: "#?RADIANCE"
|
|
85
|
+
isHdr = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
console.warn("loadPMREM: failed to probe URL for format detection", url, err);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
43
93
|
|
|
44
94
|
let loader: RGBELoader | EXRLoader | TextureLoader | KTX2Loader;
|
|
45
95
|
|
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
import type { SceneData } from "needle
|
|
2
|
-
|
|
3
|
-
import { getComponent } from "./engine_components.js";
|
|
4
|
-
import { TypeStore } from "./engine_typestore.js";
|
|
1
|
+
import type { SceneData } from "needle-bindings";
|
|
2
|
+
export type { SceneData };
|
|
5
3
|
import { isDevEnvironment } from "./debug/index.js";
|
|
4
|
+
import { getComponent } from "./engine_components.js";
|
|
6
5
|
import { ContextRegistry } from "./engine_context_registry.js";
|
|
6
|
+
import type { IContext } from "./engine_types.js";
|
|
7
|
+
import { TypeStore } from "./engine_typestore.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* safe to import at module level, including in SSR environments
|
|
12
|
-
* (returns a silent error proxy when no context is active).
|
|
10
|
+
* Quick access to the current Needle Engine context from anywhere — no need to pass `ctx` around.
|
|
11
|
+
* Use it in React/Svelte/Vue components, button handlers, or plain JavaScript.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Safe to import at module level, including in SSR environments.
|
|
14
|
+
* For pages with multiple `<needle-engine>` elements, use `ctx` directly instead.
|
|
16
15
|
*
|
|
17
|
-
*
|
|
16
|
+
* @experimental This API may change in future releases.
|
|
18
17
|
*
|
|
19
18
|
* @example
|
|
20
19
|
* import { needle } from "@needle-tools/engine";
|
|
@@ -28,7 +27,7 @@ export const needle: IContext = new Proxy({} as IContext, {
|
|
|
28
27
|
const ctx = ContextRegistry.Current;
|
|
29
28
|
if (!ctx) {
|
|
30
29
|
const fn = isDevEnvironment() ? console.error : console.warn;
|
|
31
|
-
fn(`[needle] needle.${prop} accessed before scene started`);
|
|
30
|
+
fn(`[needle] needle.${prop} was accessed before the scene started. Use "needle" inside event handlers or callbacks, not at module top-level. For setup code use: onStart(ctx => { ... })`);
|
|
32
31
|
return makeErrorProxy(`needle not ready — scene hasn't started yet`);
|
|
33
32
|
}
|
|
34
33
|
const val = (ctx as any)[prop];
|
|
@@ -38,7 +37,7 @@ export const needle: IContext = new Proxy({} as IContext, {
|
|
|
38
37
|
const ctx = ContextRegistry.Current;
|
|
39
38
|
if (!ctx) {
|
|
40
39
|
const fn = isDevEnvironment() ? console.error : console.warn;
|
|
41
|
-
fn(`[needle] needle.${prop} set before scene started`);
|
|
40
|
+
fn(`[needle] needle.${prop} was set before the scene started. Use "needle" inside event handlers or callbacks, not at module top-level. For setup code use: onStart(ctx => { ... })`);
|
|
42
41
|
return true;
|
|
43
42
|
}
|
|
44
43
|
(ctx as any)[prop] = value;
|
|
@@ -70,36 +69,63 @@ function makeErrorProxy(message: string): object {
|
|
|
70
69
|
return new Proxy({}, handler);
|
|
71
70
|
}
|
|
72
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Returns a proxy for a scene node that exposes `$object`, `$components`,
|
|
74
|
+
* and child nodes as nested properties.
|
|
75
|
+
*/
|
|
76
|
+
function makeNodeProxy(ctx: IContext, node: import("three").Object3D): object {
|
|
77
|
+
return new Proxy({}, {
|
|
78
|
+
get(_t, prop: string) {
|
|
79
|
+
if (prop === "$object") return node;
|
|
80
|
+
if (prop === "$components") {
|
|
81
|
+
return new Proxy({}, {
|
|
82
|
+
get(_t2, compName: string) {
|
|
83
|
+
if (compName === "then") return undefined;
|
|
84
|
+
const ctor = TypeStore.get(compName);
|
|
85
|
+
if (!ctor) return makeErrorProxy(`Component type "${compName}" not registered (node "${node.name}")`);
|
|
86
|
+
const comp = getComponent(node, ctor);
|
|
87
|
+
if (!comp) return makeErrorProxy(`Component "${compName}" not found on node "${node.name}"`);
|
|
88
|
+
return comp;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (prop === "then") return undefined; // not a Promise
|
|
93
|
+
// Child node lookup by name
|
|
94
|
+
const child = node.children.find(c => c.name === prop) ?? null;
|
|
95
|
+
if (!child) {
|
|
96
|
+
const fn = isDevEnvironment() ? console.error : console.warn;
|
|
97
|
+
fn(`[SceneData] "${prop}" is not a child of "${node.name}". Use .$object to get the Three.js object or .$components.Name to access a component.`);
|
|
98
|
+
return makeErrorProxy(`"${prop}" not found on node "${node.name}"`);
|
|
99
|
+
}
|
|
100
|
+
return makeNodeProxy(ctx, child);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
73
105
|
/**
|
|
74
106
|
* Returns a lazily-resolved proxy typed as {@link SceneData}.
|
|
75
107
|
* The proxy is cached per context — each context gets exactly one instance.
|
|
76
108
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* If a node or component is not found, property accesses log a warning
|
|
83
|
-
* instead of throwing, so chained access never crashes.
|
|
109
|
+
* Shape mirrors the generated `needle-bindings.gen.d.ts`:
|
|
110
|
+
* ctx.sceneData.MyGlb.Camera.$components.OrbitControls.autoRotate = true;
|
|
111
|
+
* ctx.sceneData.MyGlb.Camera.$object // → THREE.Camera
|
|
112
|
+
* ctx.sceneData.MyGlb.UI.Button.$components.Button // → Needle Button component
|
|
84
113
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
114
|
+
* GLB name is ignored at runtime (scene is already loaded).
|
|
115
|
+
* Node lookup starts at the scene root.
|
|
87
116
|
*/
|
|
88
117
|
export function getSceneData(ctx: IContext): SceneData {
|
|
89
118
|
let proxy = cache.get(ctx);
|
|
90
119
|
if (!proxy) {
|
|
91
120
|
proxy = new Proxy({} as SceneData, {
|
|
92
|
-
get(_target,
|
|
121
|
+
get(_target, _glbName: string) {
|
|
122
|
+
// GLB name level — ignored at runtime, return node-name proxy
|
|
93
123
|
return new Proxy({}, {
|
|
94
|
-
get(_target,
|
|
124
|
+
get(_target, nodeName: string) {
|
|
125
|
+
if (nodeName === "then") return undefined;
|
|
95
126
|
const node = ctx.scene.getObjectByName(nodeName) ?? null;
|
|
96
127
|
if (!node) return makeErrorProxy(`Node "${nodeName}" not found in scene`);
|
|
97
|
-
|
|
98
|
-
const ctor = TypeStore.get(compName);
|
|
99
|
-
if (!ctor) return makeErrorProxy(`Component type "${compName}" not registered (node "${nodeName}")`);
|
|
100
|
-
const comp = getComponent(node, ctor);
|
|
101
|
-
if (!comp) return makeErrorProxy(`Component "${compName}" not found on node "${nodeName}"`);
|
|
102
|
-
return comp;
|
|
128
|
+
return makeNodeProxy(ctx, node);
|
|
103
129
|
}
|
|
104
130
|
});
|
|
105
131
|
}
|
|
@@ -4,6 +4,7 @@ import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../eng
|
|
|
4
4
|
import { Behaviour, Component, GameObject } from "../engine-components/Component.js";
|
|
5
5
|
import { CallInfo, EventList } from "../engine-components/EventList.js";
|
|
6
6
|
import { AssetReference } from "./engine_addressables.js";
|
|
7
|
+
import { AudioClip } from "./engine_audio.js";
|
|
7
8
|
import { debugExtension } from "./engine_default_parameters.js";
|
|
8
9
|
import { SerializationContext, TypeSerializer } from "./engine_serialization_core.js";
|
|
9
10
|
import { RenderTexture } from "./engine_texture.js";
|
|
@@ -11,25 +12,7 @@ import { IComponent } from "./engine_types.js";
|
|
|
11
12
|
import { resolveUrl } from "./engine_utils.js";
|
|
12
13
|
import { RGBAColor } from "./js-extensions/index.js";
|
|
13
14
|
|
|
14
|
-
//
|
|
15
|
-
// src?:string
|
|
16
|
-
// };
|
|
17
|
-
|
|
18
|
-
// class SourcePathSerializer extends TypeSerializer{
|
|
19
|
-
// constructor(){
|
|
20
|
-
// super(SourcePath);
|
|
21
|
-
// }
|
|
22
|
-
// onDeserialize(data: any, _context: SerializationContext) {
|
|
23
|
-
// if(data.src && typeof data.src === "string"){
|
|
24
|
-
// return data.src;
|
|
25
|
-
// }
|
|
26
|
-
// }
|
|
27
|
-
// onSerialize(_data: any, _context: SerializationContext) {
|
|
28
|
-
|
|
29
|
-
// }
|
|
30
|
-
// }
|
|
31
|
-
// new SourcePathSerializer();
|
|
32
|
-
|
|
15
|
+
// #region Color
|
|
33
16
|
class ColorSerializer extends TypeSerializer {
|
|
34
17
|
constructor() {
|
|
35
18
|
super([Color, RGBAColor], "ColorSerializer")
|
|
@@ -52,7 +35,8 @@ class ColorSerializer extends TypeSerializer {
|
|
|
52
35
|
return { r: data.r, g: data.g, b: data.b }
|
|
53
36
|
}
|
|
54
37
|
}
|
|
55
|
-
|
|
38
|
+
|
|
39
|
+
// #region Euler
|
|
56
40
|
|
|
57
41
|
class EulerSerializer extends TypeSerializer {
|
|
58
42
|
constructor() {
|
|
@@ -72,12 +56,13 @@ class EulerSerializer extends TypeSerializer {
|
|
|
72
56
|
return { x: data.x, y: data.y, z: data.z, order: data.order };
|
|
73
57
|
}
|
|
74
58
|
}
|
|
75
|
-
export const euler = new EulerSerializer();
|
|
76
59
|
|
|
77
60
|
declare type ObjectData = {
|
|
78
61
|
node?: number;
|
|
79
62
|
guid?: string;
|
|
80
63
|
}
|
|
64
|
+
|
|
65
|
+
// #region ObjectSerializer
|
|
81
66
|
class ObjectSerializer extends TypeSerializer {
|
|
82
67
|
constructor() {
|
|
83
68
|
super(Object3D, "ObjectSerializer");
|
|
@@ -107,16 +92,6 @@ class ObjectSerializer extends TypeSerializer {
|
|
|
107
92
|
console.warn(`Wrong usage of @serializable detected in your script \"${scriptname}\"\n\nIt looks like you used @serializable(Object3D) or @serializable(GameObject) for a prefab or scene reference which is exported to a separate glTF file.\n\nTo fix this please change your code to:\n\n@serializable(AssetReference)\n${context.path}! : AssetReference;\n\0`);
|
|
108
93
|
}
|
|
109
94
|
// ACTUALLY: this is already handled by the extension_utils where we resolve json pointers recursively
|
|
110
|
-
// if(data.startsWith("/nodes/")){
|
|
111
|
-
// const node = parseInt(data.substring("/nodes/".length));
|
|
112
|
-
// if (context.nodeToObject) {
|
|
113
|
-
// const res = context.nodeToObject[node];
|
|
114
|
-
// if (debugExtension)
|
|
115
|
-
// console.log("Deserialized object reference?", data, res, context?.nodeToObject);
|
|
116
|
-
// if (!res) console.warn("Did not find node: " + data, context.nodeToObject, context.object);
|
|
117
|
-
// return res;
|
|
118
|
-
// }
|
|
119
|
-
// }
|
|
120
95
|
return undefined;
|
|
121
96
|
}
|
|
122
97
|
|
|
@@ -149,7 +124,7 @@ class ObjectSerializer extends TypeSerializer {
|
|
|
149
124
|
}
|
|
150
125
|
if (!res) {
|
|
151
126
|
if (isDevEnvironment() || debugExtension)
|
|
152
|
-
console.warn(
|
|
127
|
+
console.warn(`Could not resolve object reference \"${context.path}\" (guid: ${data.guid}). The referenced object may have been deleted — check if the reference is still valid in your scene.`);
|
|
153
128
|
data["could_not_resolve"] = true;
|
|
154
129
|
}
|
|
155
130
|
else {
|
|
@@ -166,9 +141,8 @@ class ObjectSerializer extends TypeSerializer {
|
|
|
166
141
|
return undefined;
|
|
167
142
|
}
|
|
168
143
|
}
|
|
169
|
-
export const objectSerializer = new ObjectSerializer();
|
|
170
|
-
|
|
171
144
|
|
|
145
|
+
// #region ComponentSerializer
|
|
172
146
|
class ComponentSerializer extends TypeSerializer {
|
|
173
147
|
|
|
174
148
|
constructor() {
|
|
@@ -241,7 +215,6 @@ class ComponentSerializer extends TypeSerializer {
|
|
|
241
215
|
}
|
|
242
216
|
}
|
|
243
217
|
}
|
|
244
|
-
export const componentSerializer = new ComponentSerializer();
|
|
245
218
|
|
|
246
219
|
|
|
247
220
|
declare class EventListData {
|
|
@@ -258,6 +231,7 @@ declare type EventListCall = {
|
|
|
258
231
|
|
|
259
232
|
const $eventListDebugInfo = Symbol("eventListDebugInfo");
|
|
260
233
|
|
|
234
|
+
// #region EventListSerializer
|
|
261
235
|
class EventListSerializer extends TypeSerializer {
|
|
262
236
|
constructor() {
|
|
263
237
|
super([EventList]);
|
|
@@ -360,11 +334,6 @@ class EventListSerializer extends TypeSerializer {
|
|
|
360
334
|
if (debugExtension)
|
|
361
335
|
console.log(evt);
|
|
362
336
|
|
|
363
|
-
const eventListOwner = context.target;
|
|
364
|
-
if (eventListOwner !== undefined && context.path !== undefined) {
|
|
365
|
-
evt.setEventTarget(context.path, eventListOwner);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
337
|
return evt;
|
|
369
338
|
}
|
|
370
339
|
return undefined;
|
|
@@ -396,22 +365,14 @@ class EventListSerializer extends TypeSerializer {
|
|
|
396
365
|
// };
|
|
397
366
|
// }
|
|
398
367
|
}
|
|
399
|
-
export const eventListSerializer = new EventListSerializer();
|
|
400
368
|
|
|
401
369
|
|
|
402
370
|
/** Map<Clone, Original> texture. This is used for compressed textures (or when the GLTFLoader is cloning RenderTextures)
|
|
403
371
|
* It's a weak map so we don't have to worry about memory leaks
|
|
404
372
|
*/
|
|
405
373
|
const cloneOriginalMap = new WeakMap<Texture, Texture>();
|
|
406
|
-
const textureClone = Texture.prototype.clone;
|
|
407
|
-
Texture.prototype.clone = function () {
|
|
408
|
-
const clone = textureClone.call(this);
|
|
409
|
-
if (!cloneOriginalMap.has(clone)) {
|
|
410
|
-
cloneOriginalMap.set(clone, this);
|
|
411
|
-
}
|
|
412
|
-
return clone;
|
|
413
|
-
}
|
|
414
374
|
|
|
375
|
+
// #region RenderTextureSerializer
|
|
415
376
|
export class RenderTextureSerializer extends TypeSerializer {
|
|
416
377
|
constructor() {
|
|
417
378
|
super([RenderTexture, WebGLRenderTarget]);
|
|
@@ -452,9 +413,8 @@ export class RenderTextureSerializer extends TypeSerializer {
|
|
|
452
413
|
return undefined;
|
|
453
414
|
}
|
|
454
415
|
}
|
|
455
|
-
new RenderTextureSerializer();
|
|
456
|
-
|
|
457
416
|
|
|
417
|
+
// #region UriSerializer
|
|
458
418
|
export class UriSerializer extends TypeSerializer {
|
|
459
419
|
constructor() {
|
|
460
420
|
super([URL]);
|
|
@@ -471,4 +431,56 @@ export class UriSerializer extends TypeSerializer {
|
|
|
471
431
|
return undefined;
|
|
472
432
|
}
|
|
473
433
|
}
|
|
474
|
-
|
|
434
|
+
|
|
435
|
+
// #region AudioClipSerializer
|
|
436
|
+
class AudioClipSerializer extends TypeSerializer {
|
|
437
|
+
constructor() {
|
|
438
|
+
super([AudioClip]);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
onSerialize(_data: AudioClip, _context: SerializationContext) {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
onDeserialize(data: string, context: SerializationContext) {
|
|
446
|
+
if (typeof data === "string" && data.length > 0) {
|
|
447
|
+
const url = resolveUrl(context.gltfId, data);
|
|
448
|
+
if (url) return new AudioClip(url);
|
|
449
|
+
}
|
|
450
|
+
return undefined;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
// #region Init serializer
|
|
456
|
+
// Module-level references used by EventListSerializer internally
|
|
457
|
+
export let colorSerializer: ColorSerializer;
|
|
458
|
+
export let objectSerializer: ObjectSerializer;
|
|
459
|
+
export let componentSerializer: ComponentSerializer;
|
|
460
|
+
export let eventListSerializer: EventListSerializer;
|
|
461
|
+
|
|
462
|
+
/** Register all builtin serializers and prototype patches.
|
|
463
|
+
* Must be called from {@link initEngine} so the registrations survive tree-shaking
|
|
464
|
+
* when the package declares `sideEffects: false`.
|
|
465
|
+
*/
|
|
466
|
+
export function initBuiltinSerializers() {
|
|
467
|
+
// Prototype patches
|
|
468
|
+
const textureClone = Texture.prototype.clone;
|
|
469
|
+
Texture.prototype.clone = function () {
|
|
470
|
+
const clone = textureClone.call(this);
|
|
471
|
+
if (!cloneOriginalMap.has(clone)) {
|
|
472
|
+
cloneOriginalMap.set(clone, this);
|
|
473
|
+
}
|
|
474
|
+
return clone;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Register all serializers
|
|
478
|
+
colorSerializer = new ColorSerializer();
|
|
479
|
+
new EulerSerializer();
|
|
480
|
+
objectSerializer = new ObjectSerializer();
|
|
481
|
+
componentSerializer = new ComponentSerializer();
|
|
482
|
+
eventListSerializer = new EventListSerializer();
|
|
483
|
+
new RenderTextureSerializer();
|
|
484
|
+
new UriSerializer();
|
|
485
|
+
new AudioClipSerializer();
|
|
486
|
+
}
|