@needle-tools/engine 4.12.5 → 4.13.0-next.1eca7a7
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 +5 -0
- package/README.md +38 -1
- package/components.needle.json +1 -1
- package/custom-elements.json +156 -5
- package/dist/{gltf-progressive-BqUnxvCx.umd.cjs → gltf-progressive-BURrJW0U.umd.cjs} +1 -1
- package/dist/{gltf-progressive-CSaX5HQb.min.js → gltf-progressive-DHLDFNvQ.min.js} +1 -1
- package/dist/{gltf-progressive-ChnIhDXx.js → gltf-progressive-eiJCrjLb.js} +3 -3
- package/dist/materialx-B9ddsHcF.min.js +90 -0
- package/dist/materialx-BF23AVE8.umd.cjs +90 -0
- package/dist/materialx-fkoFuRh3.js +4636 -0
- package/dist/{needle-engine.bundle-Cnemui9H.umd.cjs → needle-engine.bundle-BfrDWglE.umd.cjs} +124 -124
- package/dist/{needle-engine.bundle-B_IGIr6Z.min.js → needle-engine.bundle-Bx_Lq_3v.min.js} +131 -131
- package/dist/{needle-engine.bundle-Cj66livk.js → needle-engine.bundle-MQyZGnMF.js} +3754 -3374
- package/dist/needle-engine.d.ts +2791 -309
- package/dist/needle-engine.js +415 -414
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-12-UW7je.min.js → postprocessing-BVNrgYZK.min.js} +1 -1
- package/dist/{postprocessing-B3Hu0Ryi.umd.cjs → postprocessing-CI2TjWpu.umd.cjs} +1 -1
- package/dist/{postprocessing-R535krvT.js → postprocessing-DdM-tz1j.js} +2 -2
- package/dist/{three-BzxwLtUE.umd.cjs → three-BW2s1Yl-.umd.cjs} +25 -25
- package/dist/{three-DMvLgxja.min.js → three-I__hSXzr.min.js} +26 -26
- package/dist/{three-D9pcFbxc.js → three-VvRoMeIN.js} +22 -0
- package/dist/{three-examples-F0MJj0vr.js → three-examples-BhfOE7NG.js} +1 -1
- package/dist/{three-examples-CjSwCv_b.umd.cjs → three-examples-Bpfu6ke_.umd.cjs} +1 -1
- package/dist/{three-examples-CIv2roOA.min.js → three-examples-D8zAE_7t.min.js} +1 -1
- package/dist/{three-mesh-ui-BLnJQzMl.umd.cjs → three-mesh-ui-BU55xDxJ.umd.cjs} +1 -1
- package/dist/{three-mesh-ui-BllgajJz.min.js → three-mesh-ui-C3QbemOV.min.js} +1 -1
- package/dist/{three-mesh-ui-DYyiRn5Y.js → three-mesh-ui-CcMp-FQm.js} +1 -1
- package/dist/{vendor-BIFy-gRe.js → vendor-BiyIZ61v.js} +1 -1
- package/dist/{vendor-BFgQSG2m.umd.cjs → vendor-COVQl0b8.umd.cjs} +1 -1
- package/dist/{vendor-ChgmXMYr.min.js → vendor-DW7zqjuT.min.js} +1 -1
- package/lib/engine/engine_context.d.ts +16 -0
- package/lib/engine/engine_context.js +16 -0
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_gameobject.d.ts +72 -0
- package/lib/engine/engine_gameobject.js +38 -0
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_input.d.ts +80 -4
- package/lib/engine/engine_input.js +78 -2
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_loaders.js +7 -1
- package/lib/engine/engine_loaders.js.map +1 -1
- package/lib/engine/engine_math.d.ts +81 -2
- package/lib/engine/engine_math.js +68 -2
- package/lib/engine/engine_math.js.map +1 -1
- package/lib/engine/engine_modules.d.ts +9 -0
- package/lib/engine/engine_modules.js +25 -0
- package/lib/engine/engine_modules.js.map +1 -1
- package/lib/engine/engine_networking.d.ts +181 -14
- package/lib/engine/engine_networking.js +181 -14
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine/engine_networking_auto.d.ts +35 -8
- package/lib/engine/engine_networking_auto.js +35 -8
- package/lib/engine/engine_networking_auto.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +35 -1
- package/lib/engine/engine_physics.js +35 -1
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_physics_rapier.d.ts +76 -0
- package/lib/engine/engine_physics_rapier.js +76 -0
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_serialization_decorator.d.ts +28 -2
- package/lib/engine/engine_serialization_decorator.js +28 -2
- package/lib/engine/engine_serialization_decorator.js.map +1 -1
- package/lib/engine/engine_time.d.ts +23 -3
- package/lib/engine/engine_time.js +23 -3
- package/lib/engine/engine_time.js.map +1 -1
- package/lib/engine/engine_util_decorator.d.ts +31 -1
- package/lib/engine/engine_util_decorator.js +31 -1
- package/lib/engine/engine_util_decorator.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +21 -5
- package/lib/engine/engine_utils.js +21 -5
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/engine_utils_format.d.ts +1 -1
- package/lib/engine/engine_utils_format.js +4 -1
- package/lib/engine/engine_utils_format.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_materialx.d.ts +29 -0
- package/lib/engine/extensions/NEEDLE_materialx.js +115 -0
- package/lib/engine/extensions/NEEDLE_materialx.js.map +1 -0
- package/lib/engine/extensions/extensions.js +2 -0
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/lib/engine/extensions/index.d.ts +1 -0
- package/lib/engine/extensions/index.js +1 -0
- package/lib/engine/extensions/index.js.map +1 -1
- package/lib/engine-components/AlignmentConstraint.d.ts +23 -3
- package/lib/engine-components/AlignmentConstraint.js +23 -3
- package/lib/engine-components/AlignmentConstraint.js.map +1 -1
- package/lib/engine-components/Animation.d.ts +42 -0
- package/lib/engine-components/Animation.js +36 -0
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/Animator.d.ts +37 -4
- package/lib/engine-components/Animator.js +37 -4
- package/lib/engine-components/Animator.js.map +1 -1
- package/lib/engine-components/AudioSource.d.ts +32 -10
- package/lib/engine-components/AudioSource.js +32 -10
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/AxesHelper.d.ts +22 -3
- package/lib/engine-components/AxesHelper.js +22 -3
- package/lib/engine-components/AxesHelper.js.map +1 -1
- package/lib/engine-components/BasicIKConstraint.d.ts +27 -4
- package/lib/engine-components/BasicIKConstraint.js +27 -4
- package/lib/engine-components/BasicIKConstraint.js.map +1 -1
- package/lib/engine-components/Camera.d.ts +31 -1
- package/lib/engine-components/Camera.js +31 -1
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/CharacterController.d.ts +67 -3
- package/lib/engine-components/CharacterController.js +67 -3
- package/lib/engine-components/CharacterController.js.map +1 -1
- package/lib/engine-components/Collider.d.ts +69 -12
- package/lib/engine-components/Collider.js +69 -12
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/ContactShadows.d.ts +26 -6
- package/lib/engine-components/ContactShadows.js +46 -8
- package/lib/engine-components/ContactShadows.js.map +1 -1
- package/lib/engine-components/DeleteBox.d.ts +43 -2
- package/lib/engine-components/DeleteBox.js +43 -2
- package/lib/engine-components/DeleteBox.js.map +1 -1
- package/lib/engine-components/DeviceFlag.d.ts +21 -2
- package/lib/engine-components/DeviceFlag.js +21 -2
- package/lib/engine-components/DeviceFlag.js.map +1 -1
- package/lib/engine-components/DragControls.d.ts +32 -2
- package/lib/engine-components/DragControls.js +32 -2
- package/lib/engine-components/DragControls.js.map +1 -1
- package/lib/engine-components/DropListener.d.ts +33 -21
- package/lib/engine-components/DropListener.js +33 -21
- package/lib/engine-components/DropListener.js.map +1 -1
- package/lib/engine-components/Duplicatable.d.ts +36 -5
- package/lib/engine-components/Duplicatable.js +36 -5
- package/lib/engine-components/Duplicatable.js.map +1 -1
- package/lib/engine-components/EventList.d.ts +38 -10
- package/lib/engine-components/EventList.js +38 -10
- package/lib/engine-components/EventList.js.map +1 -1
- package/lib/engine-components/Fog.d.ts +23 -1
- package/lib/engine-components/Fog.js +23 -1
- package/lib/engine-components/Fog.js.map +1 -1
- package/lib/engine-components/GridHelper.d.ts +18 -2
- package/lib/engine-components/GridHelper.js +18 -2
- package/lib/engine-components/GridHelper.js.map +1 -1
- package/lib/engine-components/GroundProjection.d.ts +24 -2
- package/lib/engine-components/GroundProjection.js +24 -2
- package/lib/engine-components/GroundProjection.js.map +1 -1
- package/lib/engine-components/Interactable.d.ts +17 -2
- package/lib/engine-components/Interactable.js +17 -2
- package/lib/engine-components/Interactable.js.map +1 -1
- package/lib/engine-components/Joints.d.ts +50 -7
- package/lib/engine-components/Joints.js +50 -7
- package/lib/engine-components/Joints.js.map +1 -1
- package/lib/engine-components/LODGroup.d.ts +36 -14
- package/lib/engine-components/LODGroup.js +43 -11
- package/lib/engine-components/LODGroup.js.map +1 -1
- package/lib/engine-components/Light.d.ts +27 -5
- package/lib/engine-components/Light.js +27 -5
- package/lib/engine-components/Light.js.map +1 -1
- package/lib/engine-components/LookAtConstraint.d.ts +22 -7
- package/lib/engine-components/LookAtConstraint.js +22 -7
- package/lib/engine-components/LookAtConstraint.js.map +1 -1
- package/lib/engine-components/NeedleMenu.d.ts +27 -5
- package/lib/engine-components/NeedleMenu.js +27 -5
- package/lib/engine-components/NeedleMenu.js.map +1 -1
- package/lib/engine-components/NestedGltf.d.ts +39 -4
- package/lib/engine-components/NestedGltf.js +42 -4
- package/lib/engine-components/NestedGltf.js.map +1 -1
- package/lib/engine-components/OffsetConstraint.d.ts +27 -3
- package/lib/engine-components/OffsetConstraint.js +27 -3
- package/lib/engine-components/OffsetConstraint.js.map +1 -1
- package/lib/engine-components/OrbitControls.d.ts +41 -3
- package/lib/engine-components/OrbitControls.js +41 -3
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.d.ts +17 -2
- package/lib/engine-components/ReflectionProbe.js +28 -10
- package/lib/engine-components/ReflectionProbe.js.map +1 -1
- package/lib/engine-components/Renderer.d.ts +34 -0
- package/lib/engine-components/Renderer.js +35 -2
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.d.ts +11 -0
- package/lib/engine-components/SceneSwitcher.js +11 -0
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/ScreenCapture.d.ts +38 -6
- package/lib/engine-components/ScreenCapture.js +38 -6
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/Skybox.js +1 -1
- package/lib/engine-components/Skybox.js.map +1 -1
- package/lib/engine-components/SmoothFollow.d.ts +66 -7
- package/lib/engine-components/SmoothFollow.js +66 -7
- package/lib/engine-components/SmoothFollow.js.map +1 -1
- package/lib/engine-components/SpatialTrigger.d.ts +48 -1
- package/lib/engine-components/SpatialTrigger.js +48 -1
- package/lib/engine-components/SpatialTrigger.js.map +1 -1
- package/lib/engine-components/SpectatorCamera.d.ts +21 -3
- package/lib/engine-components/SpectatorCamera.js +21 -3
- package/lib/engine-components/SpectatorCamera.js.map +1 -1
- package/lib/engine-components/SyncedRoom.d.ts +6 -0
- package/lib/engine-components/SyncedRoom.js +6 -0
- package/lib/engine-components/SyncedRoom.js.map +1 -1
- package/lib/engine-components/SyncedTransform.d.ts +55 -6
- package/lib/engine-components/SyncedTransform.js +55 -6
- package/lib/engine-components/SyncedTransform.js.map +1 -1
- package/lib/engine-components/TransformGizmo.d.ts +30 -3
- package/lib/engine-components/TransformGizmo.js +30 -3
- package/lib/engine-components/TransformGizmo.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +33 -6
- package/lib/engine-components/VideoPlayer.js +45 -6
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/Voip.d.ts +33 -2
- package/lib/engine-components/Voip.js +33 -2
- package/lib/engine-components/Voip.js.map +1 -1
- package/lib/engine-components/export/usdz/USDZExporter.d.ts +47 -13
- package/lib/engine-components/export/usdz/USDZExporter.js +47 -13
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
- package/lib/engine-components/particlesystem/ParticleSystem.d.ts +82 -3
- package/lib/engine-components/particlesystem/ParticleSystem.js +82 -3
- package/lib/engine-components/particlesystem/ParticleSystem.js.map +1 -1
- package/lib/engine-components/timeline/PlayableDirector.d.ts +99 -14
- package/lib/engine-components/timeline/PlayableDirector.js +91 -25
- package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
- package/lib/engine-components/ui/Button.d.ts +29 -3
- package/lib/engine-components/ui/Button.js +29 -3
- package/lib/engine-components/ui/Button.js.map +1 -1
- package/lib/engine-components/ui/Canvas.d.ts +28 -3
- package/lib/engine-components/ui/Canvas.js +28 -3
- package/lib/engine-components/ui/Canvas.js.map +1 -1
- package/lib/engine-components/ui/Image.d.ts +22 -3
- package/lib/engine-components/ui/Image.js +22 -3
- package/lib/engine-components/ui/Image.js.map +1 -1
- package/lib/engine-components/ui/Raycaster.d.ts +55 -6
- package/lib/engine-components/ui/Raycaster.js +55 -6
- package/lib/engine-components/ui/Raycaster.js.map +1 -1
- package/lib/engine-components/ui/Text.d.ts +23 -1
- package/lib/engine-components/ui/Text.js +23 -1
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/engine-components/webxr/TeleportTarget.d.ts +21 -2
- package/lib/engine-components/webxr/TeleportTarget.js +21 -2
- package/lib/engine-components/webxr/TeleportTarget.js.map +1 -1
- package/lib/engine-components/webxr/WebXR.d.ts +10 -2
- package/lib/engine-components/webxr/WebXR.js +10 -2
- package/lib/engine-components/webxr/WebXR.js.map +1 -1
- package/lib/engine-components/webxr/WebXRAvatar.d.ts +39 -2
- package/lib/engine-components/webxr/WebXRAvatar.js +35 -3
- package/lib/engine-components/webxr/WebXRAvatar.js.map +1 -1
- package/lib/engine-components/webxr/WebXRImageTracking.d.ts +266 -30
- package/lib/engine-components/webxr/WebXRImageTracking.js +266 -30
- package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
- package/lib/engine-components/webxr/XRFlag.d.ts +29 -2
- package/lib/engine-components/webxr/XRFlag.js +29 -2
- package/lib/engine-components/webxr/XRFlag.js.map +1 -1
- package/package.json +3 -2
- package/plugins/vite/custom-element-data.js +128 -19
- package/plugins/vite/dependencies.js +9 -4
- package/plugins/vite/index.js +0 -2
- package/src/engine/engine_context.ts +16 -0
- package/src/engine/engine_gameobject.ts +73 -0
- package/src/engine/engine_input.ts +83 -7
- package/src/engine/engine_loaders.ts +9 -2
- package/src/engine/engine_math.ts +81 -2
- package/src/engine/engine_modules.ts +24 -0
- package/src/engine/engine_networking.ts +187 -17
- package/src/engine/engine_networking_auto.ts +36 -9
- package/src/engine/engine_physics.ts +37 -1
- package/src/engine/engine_physics_rapier.ts +77 -0
- package/src/engine/engine_serialization_decorator.ts +28 -2
- package/src/engine/engine_time.ts +23 -3
- package/src/engine/engine_util_decorator.ts +31 -1
- package/src/engine/engine_utils.ts +21 -5
- package/src/engine/engine_utils_format.ts +6 -2
- package/src/engine/extensions/NEEDLE_materialx.ts +143 -0
- package/src/engine/extensions/extensions.ts +2 -0
- package/src/engine/extensions/index.ts +1 -0
- package/src/engine-components/AlignmentConstraint.ts +24 -4
- package/src/engine-components/Animation.ts +44 -2
- package/src/engine-components/Animator.ts +40 -7
- package/src/engine-components/AudioSource.ts +37 -15
- package/src/engine-components/AxesHelper.ts +23 -4
- package/src/engine-components/BasicIKConstraint.ts +28 -5
- package/src/engine-components/Camera.ts +33 -3
- package/src/engine-components/CharacterController.ts +73 -6
- package/src/engine-components/Collider.ts +78 -21
- package/src/engine-components/ContactShadows.ts +51 -11
- package/src/engine-components/DeleteBox.ts +43 -2
- package/src/engine-components/DeviceFlag.ts +22 -3
- package/src/engine-components/DragControls.ts +32 -2
- package/src/engine-components/DropListener.ts +42 -29
- package/src/engine-components/Duplicatable.ts +37 -6
- package/src/engine-components/EventList.ts +41 -13
- package/src/engine-components/Fog.ts +23 -1
- package/src/engine-components/GridHelper.ts +18 -2
- package/src/engine-components/GroundProjection.ts +25 -3
- package/src/engine-components/Interactable.ts +17 -2
- package/src/engine-components/Joints.ts +51 -8
- package/src/engine-components/LODGroup.ts +45 -11
- package/src/engine-components/Light.ts +30 -8
- package/src/engine-components/LookAtConstraint.ts +26 -8
- package/src/engine-components/NeedleMenu.ts +29 -7
- package/src/engine-components/NestedGltf.ts +40 -4
- package/src/engine-components/OffsetConstraint.ts +27 -3
- package/src/engine-components/OrbitControls.ts +41 -3
- package/src/engine-components/ReflectionProbe.ts +31 -13
- package/src/engine-components/Renderer.ts +34 -1
- package/src/engine-components/SceneSwitcher.ts +11 -0
- package/src/engine-components/ScreenCapture.ts +41 -9
- package/src/engine-components/Skybox.ts +1 -1
- package/src/engine-components/SmoothFollow.ts +69 -7
- package/src/engine-components/SpatialTrigger.ts +51 -4
- package/src/engine-components/SpectatorCamera.ts +23 -5
- package/src/engine-components/SyncedRoom.ts +6 -0
- package/src/engine-components/SyncedTransform.ts +59 -10
- package/src/engine-components/TransformGizmo.ts +31 -4
- package/src/engine-components/VideoPlayer.ts +48 -6
- package/src/engine-components/Voip.ts +33 -2
- package/src/engine-components/export/usdz/USDZExporter.ts +47 -13
- package/src/engine-components/particlesystem/ParticleSystem.ts +84 -5
- package/src/engine-components/timeline/PlayableDirector.ts +104 -27
- package/src/engine-components/ui/Button.ts +29 -3
- package/src/engine-components/ui/Canvas.ts +28 -3
- package/src/engine-components/ui/Image.ts +22 -3
- package/src/engine-components/ui/Raycaster.ts +57 -8
- package/src/engine-components/ui/Text.ts +24 -2
- package/src/engine-components/webxr/TeleportTarget.ts +23 -4
- package/src/engine-components/webxr/WebXR.ts +11 -3
- package/src/engine-components/webxr/WebXRAvatar.ts +41 -4
- package/src/engine-components/webxr/WebXRImageTracking.ts +282 -38
- package/src/engine-components/webxr/XRFlag.ts +30 -3
- package/plugins/vite/materialx.js +0 -32
|
@@ -8,6 +8,30 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export namespace MODULES {
|
|
10
10
|
|
|
11
|
+
export namespace MaterialX {
|
|
12
|
+
export type TYPE = typeof import("@needle-tools/materialx");
|
|
13
|
+
export let MODULE: TYPE;
|
|
14
|
+
export let MAYBEMODULE: TYPE | null = null;
|
|
15
|
+
|
|
16
|
+
const callbacks: Array<(module: TYPE) => void> = [];
|
|
17
|
+
/** Wait for the module to be loaded (doesn't trigger a load) */
|
|
18
|
+
export function ready(): Promise<TYPE> {
|
|
19
|
+
if (MODULE) return Promise.resolve(MODULE);
|
|
20
|
+
return new Promise((resolve) => { callbacks.push(resolve); });
|
|
21
|
+
};
|
|
22
|
+
/** Load the module */
|
|
23
|
+
export async function load(): Promise<TYPE> {
|
|
24
|
+
if (MODULE) return MODULE;
|
|
25
|
+
const module = await import("@needle-tools/materialx");
|
|
26
|
+
MODULE = module;
|
|
27
|
+
MAYBEMODULE = module;
|
|
28
|
+
callbacks.forEach((callback) => callback(module));
|
|
29
|
+
callbacks.length = 0;
|
|
30
|
+
return module;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
11
35
|
export namespace RAPIER_PHYSICS {
|
|
12
36
|
export type TYPE = typeof import("@dimforge/rapier3d-compat");
|
|
13
37
|
export let MODULE: TYPE;
|
|
@@ -4,6 +4,9 @@ let networkingServerUrl: string | undefined = "wss://networking.needle.tools/soc
|
|
|
4
4
|
import * as flatbuffers from 'flatbuffers';
|
|
5
5
|
import { type Websocket } from 'websocket-ts';
|
|
6
6
|
|
|
7
|
+
import type { SyncedRoom } from "../engine-components/SyncedRoom.js";
|
|
8
|
+
import type { Networking } from "../engine-components/Networking.js";
|
|
9
|
+
|
|
7
10
|
import * as schemes from "../engine-schemes/schemes.js";
|
|
8
11
|
import { isDevEnvironment } from './debug/index.js';
|
|
9
12
|
import { Telemetry } from './engine_license.js';
|
|
@@ -116,27 +119,95 @@ declare type OwnershipResponse = {
|
|
|
116
119
|
|
|
117
120
|
declare type WebsocketSendType = IModel | object | boolean | null | string | number;
|
|
118
121
|
|
|
119
|
-
/**
|
|
120
|
-
*
|
|
122
|
+
/**
|
|
123
|
+
* Manages ownership of networked objects or components.
|
|
124
|
+
*
|
|
125
|
+
* In multiplayer scenarios, ownership determines which client has authority to modify an object.
|
|
126
|
+
* The networking server rejects changes from clients that don't own an object. This prevents conflicts
|
|
127
|
+
* when multiple users try to manipulate the same object simultaneously.
|
|
128
|
+
*
|
|
129
|
+
* **Ownership states:**
|
|
130
|
+
* - `hasOwnership`: This client owns the object and can modify it
|
|
131
|
+
* - `isOwned`: Some client (could be local or remote) owns the object
|
|
132
|
+
* - `undefined`: Ownership state is unknown (not yet queried)
|
|
133
|
+
*
|
|
134
|
+
* **Typical workflow:**
|
|
135
|
+
* 1. Request ownership before modifying an object
|
|
136
|
+
* 2. Make your changes while you have ownership
|
|
137
|
+
* 3. Free ownership when done (or keep it if still interacting)
|
|
138
|
+
*
|
|
139
|
+
* @example Basic usage
|
|
140
|
+
* ```ts
|
|
141
|
+
* export class MyComponent extends Behaviour {
|
|
142
|
+
* private ownership?: OwnershipModel;
|
|
143
|
+
*
|
|
144
|
+
* awake() {
|
|
145
|
+
* this.ownership = new OwnershipModel(this.context.connection, this.guid);
|
|
146
|
+
* }
|
|
147
|
+
*
|
|
148
|
+
* onClick() {
|
|
149
|
+
* // Request ownership before modifying the object
|
|
150
|
+
* this.ownership.requestOwnership();
|
|
151
|
+
* }
|
|
152
|
+
*
|
|
153
|
+
* update() {
|
|
154
|
+
* if (this.ownership.hasOwnership) {
|
|
155
|
+
* // Safe to modify and sync the object
|
|
156
|
+
* this.gameObject.position.y += 0.01;
|
|
157
|
+
* }
|
|
158
|
+
* }
|
|
159
|
+
*
|
|
160
|
+
* onDisable() {
|
|
161
|
+
* // Release ownership when done
|
|
162
|
+
* this.ownership.freeOwnership();
|
|
163
|
+
* this.ownership.destroy();
|
|
164
|
+
* }
|
|
165
|
+
* }
|
|
166
|
+
* ```
|
|
167
|
+
*
|
|
168
|
+
* @example Async ownership
|
|
169
|
+
* ```ts
|
|
170
|
+
* async modifyObject() {
|
|
171
|
+
* try {
|
|
172
|
+
* await this.ownership.requestOwnershipAsync();
|
|
173
|
+
* // Now guaranteed to have ownership
|
|
174
|
+
* this.transform.position.x = 5;
|
|
175
|
+
* } catch(e) {
|
|
176
|
+
* console.log("Failed to gain ownership");
|
|
177
|
+
* }
|
|
178
|
+
* }
|
|
179
|
+
* ```
|
|
180
|
+
*
|
|
181
|
+
* @see {@link SyncedTransform} for a complete example of ownership in action
|
|
182
|
+
* @link https://engine.needle.tools/docs/networking.html
|
|
183
|
+
*/
|
|
121
184
|
export class OwnershipModel {
|
|
122
185
|
|
|
186
|
+
/** The unique identifier (GUID) of the object this ownership model manages */
|
|
123
187
|
public guid: string;
|
|
124
188
|
private connection: NetworkConnection;
|
|
125
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Checks if the local client has ownership of this object.
|
|
192
|
+
* @returns `true` if this client owns the object and can modify it, `false` otherwise
|
|
193
|
+
*/
|
|
126
194
|
public get hasOwnership(): boolean {
|
|
127
195
|
return this._hasOwnership;
|
|
128
196
|
}
|
|
129
197
|
|
|
130
198
|
// TODO: server should just send id to everyone
|
|
131
199
|
|
|
132
|
-
/**
|
|
200
|
+
/**
|
|
201
|
+
* Checks if anyone (local or remote client) has ownership of this object.
|
|
202
|
+
* @returns `true` if someone owns the object, `false` if no one owns it, `undefined` if unknown
|
|
203
|
+
*/
|
|
133
204
|
public get isOwned(): boolean | undefined {
|
|
134
205
|
return this._isOwned;
|
|
135
206
|
}
|
|
136
207
|
|
|
137
|
-
/**
|
|
208
|
+
/**
|
|
138
209
|
* Checks if Needle Engine networking is connected to a websocket. Note that this is **not equal** to being connected to a *room*. If you want to check if Needle Engine is connected to a networking room use the `isInRoom` property.
|
|
139
|
-
* @returns true if connected to the websocket.
|
|
210
|
+
* @returns true if connected to the websocket.
|
|
140
211
|
*/
|
|
141
212
|
public get isConnected(): boolean {
|
|
142
213
|
return this.connection.isConnected;
|
|
@@ -162,6 +233,10 @@ export class OwnershipModel {
|
|
|
162
233
|
|
|
163
234
|
private _isWaitingForOwnershipResponseCallback: Function | null = null;
|
|
164
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Queries the server to update the `isOwned` state.
|
|
238
|
+
* Call this to check if anyone currently has ownership.
|
|
239
|
+
*/
|
|
165
240
|
public updateIsOwned() {
|
|
166
241
|
this.connection.send(OwnershipEvent.RequestHasOwner, { guid: this.guid });
|
|
167
242
|
}
|
|
@@ -172,6 +247,11 @@ export class OwnershipModel {
|
|
|
172
247
|
}
|
|
173
248
|
}
|
|
174
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Requests ownership only if the object is not currently owned by anyone.
|
|
252
|
+
* Internally checks ownership state first, then requests ownership if free.
|
|
253
|
+
* @returns this OwnershipModel instance for method chaining
|
|
254
|
+
*/
|
|
175
255
|
public requestOwnershipIfNotOwned(): OwnershipModel {
|
|
176
256
|
if (this._isWaitingForOwnershipResponseCallback !== null) return this;
|
|
177
257
|
this._isWaitingForOwnershipResponseCallback = this.waitForHasOwnershipRequestResponse.bind(this);
|
|
@@ -197,6 +277,20 @@ export class OwnershipModel {
|
|
|
197
277
|
}
|
|
198
278
|
|
|
199
279
|
|
|
280
|
+
/**
|
|
281
|
+
* Requests ownership and waits asynchronously until ownership is granted or timeout occurs.
|
|
282
|
+
* @returns Promise that resolves with this OwnershipModel when ownership is gained
|
|
283
|
+
* @throws Rejects with "Timeout" if ownership is not gained within ~1 second
|
|
284
|
+
* @example
|
|
285
|
+
* ```ts
|
|
286
|
+
* try {
|
|
287
|
+
* await ownership.requestOwnershipAsync();
|
|
288
|
+
* // Ownership granted, safe to modify object
|
|
289
|
+
* } catch(e) {
|
|
290
|
+
* console.warn("Could not gain ownership:", e);
|
|
291
|
+
* }
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
200
294
|
public requestOwnershipAsync(): Promise<OwnershipModel> {
|
|
201
295
|
return new Promise((resolve, reject) => {
|
|
202
296
|
this.requestOwnership();
|
|
@@ -212,12 +306,22 @@ export class OwnershipModel {
|
|
|
212
306
|
});
|
|
213
307
|
}
|
|
214
308
|
|
|
309
|
+
/**
|
|
310
|
+
* Requests ownership of this object from the networking server.
|
|
311
|
+
* Ownership may not be granted immediately - check `hasOwnership` property or use `requestOwnershipAsync()`.
|
|
312
|
+
* @returns this OwnershipModel instance for method chaining
|
|
313
|
+
*/
|
|
215
314
|
public requestOwnership(): OwnershipModel {
|
|
216
315
|
if (debugOwner) console.log("Request ownership", this.guid);
|
|
217
316
|
this.connection.send(OwnershipEvent.RequestOwnership, { guid: this.guid });
|
|
218
317
|
return this;
|
|
219
318
|
}
|
|
220
319
|
|
|
320
|
+
/**
|
|
321
|
+
* Releases ownership of this object, allowing others to take control.
|
|
322
|
+
* Call this when you're done modifying an object to allow other users to interact with it.
|
|
323
|
+
* @returns this OwnershipModel instance for method chaining
|
|
324
|
+
*/
|
|
221
325
|
public freeOwnership(): OwnershipModel {
|
|
222
326
|
// TODO: abort "requestOwnershipIfNotOwned"
|
|
223
327
|
this.connection.send(OwnershipEvent.RemoveOwnership, { guid: this.guid });
|
|
@@ -228,6 +332,10 @@ export class OwnershipModel {
|
|
|
228
332
|
return this;
|
|
229
333
|
}
|
|
230
334
|
|
|
335
|
+
/**
|
|
336
|
+
* Cleans up event listeners and resources.
|
|
337
|
+
* Call this when the OwnershipModel is no longer needed (e.g., in `onDestroy()`).
|
|
338
|
+
*/
|
|
231
339
|
public destroy() {
|
|
232
340
|
this.connection.stopListen(OwnershipEvent.GainedOwnership, this._gainSubscription);
|
|
233
341
|
this.connection.stopListen(OwnershipEvent.LostOwnership, this._lostSubscription);
|
|
@@ -265,10 +373,46 @@ export declare type BinaryCallback = {
|
|
|
265
373
|
(data: any | flatbuffers.ByteBuffer): void;
|
|
266
374
|
}
|
|
267
375
|
|
|
268
|
-
/**
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
|
|
376
|
+
/**
|
|
377
|
+
* Main class for multiuser networking. Access via `this.context.connection` from any component.
|
|
378
|
+
*
|
|
379
|
+
* **About GUIDs:**
|
|
380
|
+
* In Needle Engine networking, GUIDs (Globally Unique Identifiers) are used to identify objects and components across the network.
|
|
381
|
+
* Every GameObject and Component has a unique `guid` property that remains consistent across all clients.
|
|
382
|
+
* GUIDs are automatically assigned (e.g. during export from Unity/Blender) and are essential for:
|
|
383
|
+
* - Object ownership management (see {@link OwnershipModel})
|
|
384
|
+
* - State synchronization (storing and retrieving object state)
|
|
385
|
+
* - Identifying which object received a network message
|
|
386
|
+
*
|
|
387
|
+
* When working with networking, you'll typically use `this.guid` to identify your component or `this.gameObject.guid` for the GameObject.
|
|
388
|
+
*
|
|
389
|
+
* @example Joining a room
|
|
390
|
+
* ```ts
|
|
391
|
+
* this.context.connection.connect();
|
|
392
|
+
* this.context.connection.joinRoom("my-room");
|
|
393
|
+
* ```
|
|
394
|
+
* @example Listening to events
|
|
395
|
+
* ```ts
|
|
396
|
+
* this.context.connection.beginListen("my-event", (data) => {
|
|
397
|
+
* console.log("Received:", data);
|
|
398
|
+
* });
|
|
399
|
+
* ```
|
|
400
|
+
* @example Sending data
|
|
401
|
+
* ```ts
|
|
402
|
+
* this.context.connection.send("my-event", { message: "Hello" });
|
|
403
|
+
* ```
|
|
404
|
+
* @example Using GUIDs for object identification
|
|
405
|
+
* ```ts
|
|
406
|
+
* // Get state for a specific object by its GUID
|
|
407
|
+
* const state = this.context.connection.tryGetState(this.guid);
|
|
408
|
+
*
|
|
409
|
+
* // Delete remote state for an object
|
|
410
|
+
* this.context.connection.sendDeleteRemoteState(this.guid);
|
|
411
|
+
* ```
|
|
412
|
+
* @see {@link RoomEvents} for room lifecycle events
|
|
413
|
+
* @see {@link OwnershipModel} for object ownership
|
|
414
|
+
* @link https://engine.needle.tools/docs/how-to-guides/networking/
|
|
415
|
+
*/
|
|
272
416
|
export class NetworkConnection implements INetworkConnection {
|
|
273
417
|
|
|
274
418
|
private context: Context;
|
|
@@ -287,7 +431,18 @@ export class NetworkConnection implements INetworkConnection {
|
|
|
287
431
|
}
|
|
288
432
|
|
|
289
433
|
/**
|
|
290
|
-
* Returns the state
|
|
434
|
+
* Returns the cached network state for a given GUID.
|
|
435
|
+
* The state is stored locally whenever network updates are received for that object.
|
|
436
|
+
* @param guid The unique identifier of the object whose state you want to retrieve
|
|
437
|
+
* @returns The cached state object, or `null` if no state exists for this GUID
|
|
438
|
+
* @example
|
|
439
|
+
* ```ts
|
|
440
|
+
* // Get the last known state for this component
|
|
441
|
+
* const myState = this.context.connection.tryGetState(this.guid);
|
|
442
|
+
* if (myState) {
|
|
443
|
+
* console.log("Found cached state:", myState);
|
|
444
|
+
* }
|
|
445
|
+
* ```
|
|
291
446
|
*/
|
|
292
447
|
public tryGetState(guid: string): IModel | null {
|
|
293
448
|
if (guid === "invalid") return null;
|
|
@@ -307,7 +462,7 @@ export class NetworkConnection implements INetworkConnection {
|
|
|
307
462
|
}
|
|
308
463
|
|
|
309
464
|
/**
|
|
310
|
-
* Checks if Needle Engine networking is connected to a websocket. Note that this is **not equal** to being connected to a *room*. If you want to check if Needle Engine is connected to a networking room use the `isInRoom` property.
|
|
465
|
+
* Checks if Needle Engine networking is connected to a websocket. Note that this is **not equal** to being connected to a *room*. If you want to check if Needle Engine is connected to a networking room use the `{@link isInRoom}` property.
|
|
311
466
|
* @returns true if connected to the websocket.
|
|
312
467
|
*/
|
|
313
468
|
public get isConnected(): boolean {
|
|
@@ -372,7 +527,7 @@ export class NetworkConnection implements INetworkConnection {
|
|
|
372
527
|
return target;
|
|
373
528
|
}
|
|
374
529
|
|
|
375
|
-
/** Joins a networked room. If you don't want to manage a connection yourself you can use a `SyncedRoom` component as well */
|
|
530
|
+
/** Joins a networked room. If you don't want to manage a connection yourself you can use a `{@link SyncedRoom}` component as well */
|
|
376
531
|
public joinRoom(room: string, viewOnly: boolean = false): boolean {
|
|
377
532
|
if (!room) {
|
|
378
533
|
console.error("Missing room name, can not join: \"" + room + "\"");
|
|
@@ -426,7 +581,18 @@ export class NetworkConnection implements INetworkConnection {
|
|
|
426
581
|
return this.sendWithWebsocket(key, data, queue);
|
|
427
582
|
}
|
|
428
583
|
|
|
429
|
-
/**
|
|
584
|
+
/**
|
|
585
|
+
* Deletes the network state for a specific object on the server.
|
|
586
|
+
* This removes the object's state from the room, preventing it from being sent to newly joining users.
|
|
587
|
+
* @param guid The unique identifier of the object whose state should be deleted
|
|
588
|
+
* @example
|
|
589
|
+
* ```ts
|
|
590
|
+
* // When destroying a networked object, clean up its server state
|
|
591
|
+
* onDestroy() {
|
|
592
|
+
* this.context.connection.sendDeleteRemoteState(this.guid);
|
|
593
|
+
* }
|
|
594
|
+
* ```
|
|
595
|
+
*/
|
|
430
596
|
public sendDeleteRemoteState(guid: string) {
|
|
431
597
|
this.send("delete-state", { guid: guid, dontSave: true });
|
|
432
598
|
delete this._state[guid];
|
|
@@ -469,7 +635,7 @@ export class NetworkConnection implements INetworkConnection {
|
|
|
469
635
|
}
|
|
470
636
|
|
|
471
637
|
/** Use to start listening to networking events.
|
|
472
|
-
* To unsubscribe from events use the `stopListen` method.
|
|
638
|
+
* To unsubscribe from events use the `{@link stopListen}` method.
|
|
473
639
|
* See the example below for typical usage:
|
|
474
640
|
*
|
|
475
641
|
* ### Component Example
|
|
@@ -501,7 +667,7 @@ export class NetworkConnection implements INetworkConnection {
|
|
|
501
667
|
public stopListening(key: (string & {}) | OwnershipEvent | OwnershipEventNamesIncoming | RoomEventsIncoming | RoomEvents, callback: Function | null) { return this.stopListen(key, callback); }
|
|
502
668
|
|
|
503
669
|
/** Use to stop listening to networking events
|
|
504
|
-
* To subscribe to events use the `beginListen` method.
|
|
670
|
+
* To subscribe to events use the `{@link beginListen}` method.
|
|
505
671
|
* See the example below for typical usage:
|
|
506
672
|
*
|
|
507
673
|
* ### Component Example
|
|
@@ -548,12 +714,16 @@ export class NetworkConnection implements INetworkConnection {
|
|
|
548
714
|
|
|
549
715
|
private netWebSocketUrlProvider?: INetworkingWebsocketUrlProvider;
|
|
550
716
|
|
|
551
|
-
/** Use to override the networking server backend url.
|
|
717
|
+
/** Use to override the networking server backend url.
|
|
718
|
+
* This is what the `{@link Networking}` component uses to modify the backend url.
|
|
719
|
+
**/
|
|
552
720
|
public registerProvider(prov: INetworkingWebsocketUrlProvider) {
|
|
553
721
|
this.netWebSocketUrlProvider = prov;
|
|
554
722
|
}
|
|
555
723
|
|
|
556
|
-
/** Used to connect to the networking server
|
|
724
|
+
/** Used to connect to the networking server
|
|
725
|
+
* @param url Optional url to connect to. If not provided, it will use the url from the registered `INetworkingWebsocketUrlProvider` or the default backend networking url. If you want to change the url after connecting, you need to disconnect first and then connect again with the new url.
|
|
726
|
+
*/
|
|
557
727
|
public async connect(url?: string) {
|
|
558
728
|
if (this.connected && url && url !== networkingServerUrl) {
|
|
559
729
|
return Promise.reject("Can not connect to different server url. Please disconnect first.");
|
|
@@ -176,15 +176,42 @@ export declare type SyncFieldOptions = {
|
|
|
176
176
|
export declare type FieldChangedCallbackFn = (newValue: any, previousValue: any) => void | boolean | any;
|
|
177
177
|
|
|
178
178
|
/**
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
179
|
+
* Marks a field for automatic network synchronization across connected clients.
|
|
180
|
+
* When a synced field changes, the new value is automatically broadcast to all users in the room.
|
|
181
|
+
*
|
|
182
|
+
* Primitives (string, number, boolean) sync automatically.
|
|
183
|
+
* For arrays/objects, reassign to trigger sync: `this.myArray = this.myArray`
|
|
184
|
+
*
|
|
185
|
+
* @param onFieldChanged Optional callback when the field changes (locally or from network).
|
|
186
|
+
* Return `false` to prevent syncing this change to others.
|
|
187
|
+
*
|
|
188
|
+
* @example Basic sync
|
|
189
|
+
* ```ts
|
|
190
|
+
* class MyComponent extends Behaviour {
|
|
191
|
+
* @syncField() playerScore: number = 0;
|
|
192
|
+
* }
|
|
193
|
+
* ```
|
|
194
|
+
* @example With change callback
|
|
195
|
+
* ```ts
|
|
196
|
+
* class MyComponent extends Behaviour {
|
|
197
|
+
* @syncField("onHealthChanged") health: number = 100;
|
|
198
|
+
*
|
|
199
|
+
* onHealthChanged(newValue: number, oldValue: number) {
|
|
200
|
+
* console.log(`Health: ${oldValue} → ${newValue}`);
|
|
201
|
+
* }
|
|
202
|
+
* }
|
|
203
|
+
* ```
|
|
204
|
+
* @example Preventing sync (one-way)
|
|
205
|
+
* ```ts
|
|
206
|
+
* class MyComponent extends Behaviour {
|
|
207
|
+
* @syncField(function(newVal, oldVal) {
|
|
208
|
+
* // Process incoming value but don't sync our changes
|
|
209
|
+
* return false;
|
|
210
|
+
* }) serverControlled: string = "";
|
|
211
|
+
* }
|
|
212
|
+
* ```
|
|
213
|
+
* @see {@link serializable} for editor serialization
|
|
214
|
+
* @link https://engine.needle.tools/docs/how-to-guides/networking/
|
|
188
215
|
*/
|
|
189
216
|
export const syncField = function (onFieldChanged: string | FieldChangedCallbackFn | undefined | null = null) {
|
|
190
217
|
|
|
@@ -10,8 +10,10 @@ import { Context } from './engine_setup.js';
|
|
|
10
10
|
import { getTempVector, getWorldPosition } from "./engine_three_utils.js"
|
|
11
11
|
import type { ConstructorConcrete, Vec2, Vec3, } from './engine_types.js';
|
|
12
12
|
import type { IPhysicsEngine } from './engine_types.js';
|
|
13
|
+
import type { RapierPhysics } from './engine_physics_rapier.js';
|
|
13
14
|
import { getParam } from "./engine_utils.js"
|
|
14
15
|
|
|
16
|
+
|
|
15
17
|
const debugPhysics = getParam("debugphysics");
|
|
16
18
|
const debugWorker = getParam("debugworker");
|
|
17
19
|
const layerMaskHelper: Layers = new Layers();
|
|
@@ -133,11 +135,45 @@ export class SphereIntersection implements Intersection {
|
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Provides physics utilities including raycasting and overlap detection.
|
|
140
|
+
* Access via `this.context.physics` from any component.
|
|
141
|
+
*
|
|
142
|
+
* For physics engine features (rigidbodies, colliders, forces, etc.), use `this.context.physics.engine`.
|
|
143
|
+
* The physics engine is {@link RapierPhysics}, which uses the Rapier physics library for realistic simulation.
|
|
144
|
+
*
|
|
145
|
+
* **Performance - Automatic MeshBVH:**
|
|
146
|
+
* Needle Engine automatically uses [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh) to accelerate raycasting.
|
|
147
|
+
* MeshBVH structures are generated automatically on web workers in the background, making raycasts significantly faster
|
|
148
|
+
* without blocking the main thread. This happens transparently - you don't need to do anything to enable it.
|
|
149
|
+
* While the BVH is being generated, raycasts fall back to standard three.js raycasting (configurable via `allowSlowRaycastFallback`).
|
|
150
|
+
*
|
|
151
|
+
* @example Raycasting from mouse position
|
|
152
|
+
* ```ts
|
|
153
|
+
* const hits = this.context.physics.raycast();
|
|
154
|
+
* if (hits.length > 0) {
|
|
155
|
+
* console.log("Hit:", hits[0].object.name);
|
|
156
|
+
* }
|
|
157
|
+
* ```
|
|
158
|
+
* @example Raycasting with inline options
|
|
159
|
+
* ```ts
|
|
160
|
+
* const hits = this.context.physics.raycast({
|
|
161
|
+
* maxDistance: 100, // Only hit objects within 100 units
|
|
162
|
+
* layerMask: 1, // Only layer 0
|
|
163
|
+
* ignore: [this.gameObject] // Ignore self
|
|
164
|
+
* });
|
|
165
|
+
* ```
|
|
166
|
+
* @example Physics engine raycast (against colliders only)
|
|
167
|
+
* ```ts
|
|
168
|
+
* const hit = this.context.physics.engine?.raycast(origin, direction);
|
|
169
|
+
* ```
|
|
170
|
+
* @see {@link RapierPhysics} for physics engine implementation details
|
|
171
|
+
*/
|
|
136
172
|
export class Physics {
|
|
137
173
|
|
|
138
174
|
private static _raycasting: number = 0;
|
|
139
175
|
/**
|
|
140
|
-
* Returns true if raycasting is currently
|
|
176
|
+
* Returns true if raycasting is currently in progress
|
|
141
177
|
*/
|
|
142
178
|
public static get raycasting() {
|
|
143
179
|
return this._raycasting > 0;
|
|
@@ -26,6 +26,7 @@ import type {
|
|
|
26
26
|
import { Collision, ContactPoint } from './engine_types.js';
|
|
27
27
|
import { ShapeOverlapResult } from './engine_types.js';
|
|
28
28
|
import { CircularBuffer, getParam } from "./engine_utils.js"
|
|
29
|
+
import type { Physics } from './engine_physics.js';
|
|
29
30
|
|
|
30
31
|
const debugPhysics = getParam("debugphysics");
|
|
31
32
|
const debugColliderPlacement = getParam("debugcolliderplacement");
|
|
@@ -61,6 +62,82 @@ declare type PhysicsBody = {
|
|
|
61
62
|
rotation(): { x: number, y: number, z: number, w: number }
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Rapier physics engine implementation for Needle Engine.
|
|
67
|
+
*
|
|
68
|
+
* Rapier is a fast, cross-platform physics engine that provides realistic physics simulation
|
|
69
|
+
* for rigidbodies, colliders, joints, and collision detection. It runs entirely in WebAssembly
|
|
70
|
+
* for high performance.
|
|
71
|
+
*
|
|
72
|
+
* **Features:**
|
|
73
|
+
* - Rigidbody simulation (dynamic, kinematic, static)
|
|
74
|
+
* - Multiple collider shapes (box, sphere, capsule, mesh, convex hull)
|
|
75
|
+
* - Raycasting and shape overlap queries against physics colliders
|
|
76
|
+
* - Collision and trigger events
|
|
77
|
+
* - Joints (fixed, hinge, etc.)
|
|
78
|
+
* - Continuous collision detection (CCD)
|
|
79
|
+
* - Physics materials (friction, bounciness)
|
|
80
|
+
*
|
|
81
|
+
* **Access:**
|
|
82
|
+
* The Rapier physics engine is accessible via `this.context.physics.engine` from any component.
|
|
83
|
+
* Rapier is automatically initialized when physics components are used.
|
|
84
|
+
*
|
|
85
|
+
* **Using the Rapier Module Directly:**
|
|
86
|
+
* Rapier is lazy-loaded for performance. You can access the raw Rapier module via {@link MODULES.RAPIER_PHYSICS}.
|
|
87
|
+
* Use `MODULES.RAPIER_PHYSICS.load()` to load the module, or `MODULES.RAPIER_PHYSICS.ready()` to wait for it without triggering a load.
|
|
88
|
+
* Once loaded, the module is available at `MODULES.RAPIER_PHYSICS.MODULE`.
|
|
89
|
+
*
|
|
90
|
+
* **Note:**
|
|
91
|
+
* This is the low-level physics engine implementation. For general raycasting (against all scene objects),
|
|
92
|
+
* use {@link Physics.raycast} instead. Use this class for physics-specific operations like applying forces,
|
|
93
|
+
* raycasting against colliders only, or accessing the Rapier world directly.
|
|
94
|
+
*
|
|
95
|
+
* @example Applying forces to a rigidbody
|
|
96
|
+
* ```ts
|
|
97
|
+
* const rb = this.gameObject.getComponent(Rigidbody);
|
|
98
|
+
* if (rb) {
|
|
99
|
+
* this.context.physics.engine?.addForce(rb, { x: 0, y: 10, z: 0 }, true);
|
|
100
|
+
* }
|
|
101
|
+
* ```
|
|
102
|
+
* @example Raycasting against physics colliders only
|
|
103
|
+
* ```ts
|
|
104
|
+
* const origin = { x: 0, y: 5, z: 0 };
|
|
105
|
+
* const direction = { x: 0, y: -1, z: 0 };
|
|
106
|
+
* const hit = this.context.physics.engine?.raycast(origin, direction);
|
|
107
|
+
* if (hit) {
|
|
108
|
+
* console.log("Hit collider:", hit.collider.name);
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
111
|
+
* @example Accessing Rapier world directly
|
|
112
|
+
* ```ts
|
|
113
|
+
* const rapierWorld = this.context.physics.engine?.world;
|
|
114
|
+
* if (rapierWorld) {
|
|
115
|
+
* // Direct access to Rapier API
|
|
116
|
+
* console.log("Gravity:", rapierWorld.gravity);
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
* @example Using the Rapier module directly
|
|
120
|
+
* ```ts
|
|
121
|
+
* import { MODULES } from "@needle-tools/engine";
|
|
122
|
+
*
|
|
123
|
+
* // Load the Rapier module
|
|
124
|
+
* const RAPIER = await MODULES.RAPIER_PHYSICS.load();
|
|
125
|
+
*
|
|
126
|
+
* // Now you can use Rapier types and create custom physics objects
|
|
127
|
+
* const rigidBodyDesc = RAPIER.RigidBodyDesc.dynamic()
|
|
128
|
+
* .setTranslation(0, 10, 0);
|
|
129
|
+
*
|
|
130
|
+
* // Or access the already-loaded module
|
|
131
|
+
* if (MODULES.RAPIER_PHYSICS.MODULE) {
|
|
132
|
+
* const colliderDesc = MODULES.RAPIER_PHYSICS.MODULE.ColliderDesc.ball(1.0);
|
|
133
|
+
* }
|
|
134
|
+
* ```
|
|
135
|
+
* @see {@link Physics} for general raycasting and physics utilities
|
|
136
|
+
* @see {@link MODULES.RAPIER_PHYSICS} for direct access to the Rapier module
|
|
137
|
+
* @link https://rapier.rs/docs/ for Rapier documentation
|
|
138
|
+
* @link https://engine.needle.tools/docs/reference/components.html#physics
|
|
139
|
+
* @link https://engine.needle.tools/docs/how-to-guides/scripting/use-physics.html
|
|
140
|
+
*/
|
|
64
141
|
export class RapierPhysics implements IPhysicsEngine {
|
|
65
142
|
|
|
66
143
|
debugRenderColliders: boolean = false;
|
|
@@ -8,8 +8,34 @@ export const serializeable = function <T>(type?: Constructor<T> | null | Array<C
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Marks a field for serialization and editor exposure. Required for fields that reference
|
|
12
|
+
* other objects, components, or assets. Primitive types (string, number, boolean) work without a type argument.
|
|
13
|
+
*
|
|
14
|
+
* @param type The constructor type for complex objects. Omit for primitives.
|
|
15
|
+
*
|
|
16
|
+
* @example Primitive types (no type needed)
|
|
17
|
+
* ```ts
|
|
18
|
+
* @serializable()
|
|
19
|
+
* speed: number = 1;
|
|
20
|
+
*
|
|
21
|
+
* @serializable()
|
|
22
|
+
* label: string = "Hello";
|
|
23
|
+
* ```
|
|
24
|
+
* @example Object references
|
|
25
|
+
* ```ts
|
|
26
|
+
* @serializable(Object3D)
|
|
27
|
+
* target: Object3D | null = null;
|
|
28
|
+
*
|
|
29
|
+
* @serializable(Renderer)
|
|
30
|
+
* myRenderer: Renderer | null = null;
|
|
31
|
+
* ```
|
|
32
|
+
* @example Arrays
|
|
33
|
+
* ```ts
|
|
34
|
+
* @serializable([Object3D])
|
|
35
|
+
* waypoints: Object3D[] = [];
|
|
36
|
+
* ```
|
|
37
|
+
* @see {@link syncField} for automatic network synchronization
|
|
38
|
+
* @link https://engine.needle.tools/docs/reference/typescript-decorators.html#serializable
|
|
13
39
|
*/
|
|
14
40
|
export const serializable = function <T>(type?: Constructor<T> | null | Array<Constructor<any> | TypeResolver<T>> | TypeResolver<T>) {
|
|
15
41
|
if (type === undefined) type = null;
|
|
@@ -8,8 +8,23 @@ let timeScale = 1;
|
|
|
8
8
|
if (typeof timescaleUrl === "number") timeScale = timescaleUrl;
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Provides time-related information for frame-based game logic.
|
|
12
|
+
* Access via `this.context.time` from any component.
|
|
13
|
+
*
|
|
14
|
+
* @example Using deltaTime for frame-rate independent movement
|
|
15
|
+
* ```ts
|
|
16
|
+
* update() {
|
|
17
|
+
* // Move 1 unit per second regardless of frame rate
|
|
18
|
+
* this.gameObject.position.x += 1 * this.context.time.deltaTime;
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
* @example Checking elapsed time
|
|
22
|
+
* ```ts
|
|
23
|
+
* start() {
|
|
24
|
+
* console.log(`Time since start: ${this.context.time.time}s`);
|
|
25
|
+
* console.log(`Current frame: ${this.context.time.frameCount}`);
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
13
28
|
*/
|
|
14
29
|
export class Time implements ITime {
|
|
15
30
|
|
|
@@ -27,7 +42,12 @@ export class Time implements ITime {
|
|
|
27
42
|
get deltaTimeUnscaled() { return this._deltaTimeUnscaled; }
|
|
28
43
|
private _deltaTimeUnscaled = 0;
|
|
29
44
|
|
|
30
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* The scale at which time passes. Default is 1.
|
|
47
|
+
* - Values < 1 create slow motion (e.g. 0.5 = half speed)
|
|
48
|
+
* - Values > 1 speed up time (e.g. 2 = double speed)
|
|
49
|
+
* - Value of 0 effectively pauses time-dependent logic
|
|
50
|
+
*/
|
|
31
51
|
timeScale = 1;
|
|
32
52
|
|
|
33
53
|
/** same as frameCount */
|
|
@@ -9,7 +9,37 @@ import { watchWrite } from "./engine_utils.js";
|
|
|
9
9
|
declare type setter = (v: any) => void;
|
|
10
10
|
declare type getter = () => any;
|
|
11
11
|
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Marks a field to trigger the `onValidate` callback when its value changes.
|
|
14
|
+
* Useful for reacting to property changes from the editor or at runtime.
|
|
15
|
+
*
|
|
16
|
+
* Your component must implement `onValidate(property?: string)` to receive notifications.
|
|
17
|
+
*
|
|
18
|
+
* @param set Optional custom setter called before the value is assigned
|
|
19
|
+
* @param get Optional custom getter called when the value is read
|
|
20
|
+
*
|
|
21
|
+
* @example Basic usage
|
|
22
|
+
* ```ts
|
|
23
|
+
* export class MyComponent extends Behaviour {
|
|
24
|
+
* @serializable()
|
|
25
|
+
* @validate()
|
|
26
|
+
* color: Color = new Color(1, 0, 0);
|
|
27
|
+
*
|
|
28
|
+
* onValidate(property?: string) {
|
|
29
|
+
* if (property === "color") {
|
|
30
|
+
* console.log("Color changed to:", this.color);
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
* @example With custom setter
|
|
36
|
+
* ```ts
|
|
37
|
+
* @validate(function(value) {
|
|
38
|
+
* console.log("Setting speed to", value);
|
|
39
|
+
* })
|
|
40
|
+
* speed: number = 1;
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
13
43
|
export const validate = function (set?: setter, get?: getter) {
|
|
14
44
|
// "descriptor : undefined" prevents @validate() to be added to property getters or setters
|
|
15
45
|
return function (target: IComponent | any, propertyKey: string, descriptor?: undefined) {
|