@needle-tools/engine 5.1.0-canary.fbdfce3 → 5.1.0-experimental.03e8105
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 +86 -0
- package/SKILL.md +4 -1
- package/components.needle.json +1 -1
- package/dist/{needle-engine.bundle-BFSj2Fz8.js → needle-engine.bundle-BNqUjnSQ.js} +19180 -18386
- package/dist/needle-engine.bundle-Bt8ULD7E.umd.cjs +1733 -0
- package/dist/needle-engine.bundle-DF6ovbwD.min.js +1733 -0
- package/dist/needle-engine.d.ts +1487 -356
- package/dist/needle-engine.js +544 -542
- 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 +8 -1
- 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/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 +21 -8
- package/lib/engine/engine_context.js +32 -16
- 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 +7 -7
- 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 +7 -7
- package/lib/engine/engine_license.js +183 -57
- package/lib/engine/engine_license.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_scenedata.js +2 -2
- package/lib/engine/engine_scenedata.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.js +28 -5
- 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_types.d.ts +29 -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_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/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 +1 -1
- 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-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 +2 -119
- package/lib/engine-components/AnimatorController.js +33 -232
- 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/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 +3 -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.js +9 -1
- 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 +0 -2
- package/lib/engine-components/OrbitControls.js +30 -12
- package/lib/engine-components/OrbitControls.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/api.d.ts +2 -1
- package/lib/engine-components/api.js +2 -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/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.js +4 -0
- package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
- package/package.json +2 -83
- package/plugins/common/cloud.js +6 -1
- package/plugins/common/license.js +31 -10
- package/plugins/common/worker.js +9 -4
- package/plugins/vite/asap.js +17 -8
- package/plugins/vite/dependencies.js +29 -10
- package/plugins/vite/dependency-watcher.js +2 -2
- package/plugins/vite/editor-connection.js +3 -3
- package/plugins/vite/license.js +46 -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/reload.js +1 -1
- package/plugins/vite/server.js +2 -1
- package/src/engine/api.ts +11 -1
- package/src/engine/codegen/register_types.ts +10 -18
- 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 +34 -18
- 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 +7 -7
- package/src/engine/engine_input.ts +28 -7
- package/src/engine/engine_instantiate_resolve.ts +407 -0
- package/src/engine/engine_license.ts +197 -55
- 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_scenedata.ts +3 -3
- package/src/engine/engine_serialization_builtin_serializer.ts +32 -9
- package/src/engine/engine_serialization_core.ts +9 -0
- package/src/engine/engine_types.ts +46 -27
- package/src/engine/engine_util_decorator.ts +7 -2
- package/src/engine/engine_utils.ts +16 -5
- package/src/engine/engine_utils_qrcode.ts +2 -2
- package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
- package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
- package/src/engine/webcomponents/needle menu/needle-menu.ts +6 -6
- package/src/engine/webcomponents/needle-engine.loading.ts +6 -6
- package/src/engine/webcomponents/needle-engine.ts +12 -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 +20 -291
- package/src/engine-components/AudioSource.ts +130 -79
- 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 +3 -0
- package/src/engine-components/EventList.ts +45 -83
- package/src/engine-components/Joints.ts +20 -4
- package/src/engine-components/Light.ts +10 -2
- package/src/engine-components/Networking.ts +1 -1
- package/src/engine-components/OrbitControls.ts +34 -14
- 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/api.ts +2 -1
- package/src/engine-components/codegen/components.ts +7 -13
- package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
- 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 +2 -0
- package/dist/needle-engine.bundle-CmxIO5uH.min.js +0 -1732
- package/dist/needle-engine.bundle-tJIZukCz.umd.cjs +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/plugins/dts-generator/dts.codegen.js +0 -334
- package/plugins/dts-generator/dts.scan.js +0 -99
- package/plugins/dts-generator/dts.writer.js +0 -59
- package/plugins/dts-generator/glb.discovery.js +0 -279
- package/plugins/dts-generator/glb.extractor.js +0 -215
- package/plugins/dts-generator/glb.reader.js +0 -167
- package/plugins/dts-generator/index.js +0 -36
- package/plugins/dts-generator/manifest.types.js +0 -174
- package/plugins/gltf-packer.mjs +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
|
@@ -663,7 +663,15 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
663
663
|
}
|
|
664
664
|
this._controls.enabled = true;
|
|
665
665
|
|
|
666
|
-
|
|
666
|
+
// Interrupt programmatic transitions on meaningful new user interaction:
|
|
667
|
+
// - Middle/right button down (always intentional camera control)
|
|
668
|
+
// - Mouse wheel (zoom intent)
|
|
669
|
+
// - Left button drag start: getPointerDown(0) with a position delta — a bare click
|
|
670
|
+
// without movement shouldn't cancel an animation, but starting to drag should.
|
|
671
|
+
// Using getPointerDown (not getPointerPressed) ensures we only interrupt once at
|
|
672
|
+
// drag onset, not continuously every frame during a drag.
|
|
673
|
+
const leftDragStart = this.context.input.getPointerDown(0) && (this.context.input.getPointerPositionDelta(0)?.length() || 0) > .1;
|
|
674
|
+
if (this.context.input.getPointerDown(1) || this.context.input.getPointerDown(2) || this.context.input.mouseWheelChanged || leftDragStart) {
|
|
667
675
|
this._inputs += 1;
|
|
668
676
|
}
|
|
669
677
|
if (this._inputs > 0 && this.allowInterrupt) {
|
|
@@ -758,19 +766,26 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
758
766
|
|
|
759
767
|
if (this.targetBounds) {
|
|
760
768
|
// #region target bounds
|
|
761
|
-
const targetVector = this._controls.target;
|
|
762
769
|
const boundsCenter = this.targetBounds.worldPosition;
|
|
763
770
|
const boundsHalfSize = getTempVector(this.targetBounds.worldScale).multiplyScalar(0.5);
|
|
764
771
|
const min = getTempVector(boundsCenter).sub(boundsHalfSize);
|
|
765
772
|
const max = getTempVector(boundsCenter).add(boundsHalfSize);
|
|
766
|
-
|
|
767
|
-
const duration = .1;
|
|
768
|
-
if (duration <= 0) targetVector.copy(newTarget);
|
|
769
|
-
else targetVector.lerp(newTarget, this.context.time.deltaTime / duration);
|
|
773
|
+
|
|
770
774
|
if (this._lookTargetLerpActive) {
|
|
771
|
-
|
|
772
|
-
|
|
775
|
+
// During a programmatic transition (fitCamera / setLookTargetPosition with immediate: false),
|
|
776
|
+
// only clamp the destination. The look-target lerp (above) handles moving _controls.target
|
|
777
|
+
// towards the endpoint — we must not fight it by also lerping _controls.target here.
|
|
778
|
+
this._lookTargetEndPosition.clamp(min, max);
|
|
779
|
+
}
|
|
780
|
+
else {
|
|
781
|
+
// Interactive use (pan/orbit): smoothly push the target back into bounds
|
|
782
|
+
const targetVector = this._controls.target;
|
|
783
|
+
const newTarget = getTempVector(targetVector).clamp(min, max);
|
|
784
|
+
const duration = .1;
|
|
785
|
+
if (duration <= 0) targetVector.copy(newTarget);
|
|
786
|
+
else targetVector.lerp(newTarget, Math.min(1, this.context.time.deltaTime / duration));
|
|
773
787
|
}
|
|
788
|
+
|
|
774
789
|
if (debug) {
|
|
775
790
|
Gizmos.DrawWireBox(boundsCenter, boundsHalfSize.multiplyScalar(2), 0xffaa00);
|
|
776
791
|
}
|
|
@@ -847,7 +862,8 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
847
862
|
this._controls.update(this.context.time.deltaTime);
|
|
848
863
|
|
|
849
864
|
if (debug) {
|
|
850
|
-
|
|
865
|
+
const distance = this._controls.getDistance();
|
|
866
|
+
Gizmos.DrawWireSphere(this._controls.target, 0.01 * distance, 0x00ff00);
|
|
851
867
|
}
|
|
852
868
|
}
|
|
853
869
|
}
|
|
@@ -1022,7 +1038,8 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
1022
1038
|
|
|
1023
1039
|
if (debug) {
|
|
1024
1040
|
console.warn("OrbitControls: setLookTargetPosition", position, immediateOrDuration);
|
|
1025
|
-
|
|
1041
|
+
const distance = this._controls.getDistance();
|
|
1042
|
+
Gizmos.DrawWireSphere(this._lookTargetEndPosition, 0.01 * distance, 0xff5500, 2);
|
|
1026
1043
|
}
|
|
1027
1044
|
|
|
1028
1045
|
if (immediateOrDuration === true) {
|
|
@@ -1086,13 +1103,16 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
1086
1103
|
// Adapted from https://discourse.threejs.org/t/camera-zoom-to-fit-object/936/24
|
|
1087
1104
|
// Slower but better implementation that takes bones and exact vertex positions into account: https://github.com/google/model-viewer/blob/04e900c5027de8c5306fe1fe9627707f42811b05/packages/model-viewer/src/three-components/ModelScene.ts#L321
|
|
1088
1105
|
|
|
1089
|
-
/**
|
|
1090
|
-
* Fits the camera to show the objects provided (defaults to the scene if no objects are passed in)
|
|
1106
|
+
/**
|
|
1107
|
+
* Fits the camera to show the objects provided (defaults to the scene if no objects are passed in)
|
|
1091
1108
|
* @param options The options for fitting the camera. Use to provide objects to fit to, fit direction and size and other settings.
|
|
1092
1109
|
*/
|
|
1093
1110
|
fitCamera(options?: OrbitFitCameraOptions);
|
|
1094
|
-
|
|
1095
|
-
|
|
1111
|
+
// Deprecated overload commented out: it accepted Object3D as first arg, which caused
|
|
1112
|
+
// TypeScript autocomplete to show Object3D properties (position, worldPosition, etc.)
|
|
1113
|
+
// instead of OrbitFitCameraOptions. The implementation still handles Object3D at runtime
|
|
1114
|
+
// for backwards-compat — use fitCamera({ objects: [...] }) instead.
|
|
1115
|
+
// fitCamera(objects?: Object3D | Array<Object3D>, options?: Omit<OrbitFitCameraOptions, "objects">);
|
|
1096
1116
|
fitCamera(objectsOrOptions?: Object3D | Array<Object3D> | OrbitFitCameraOptions, options?: OrbitFitCameraOptions): void {
|
|
1097
1117
|
|
|
1098
1118
|
|
|
@@ -204,12 +204,19 @@ export class Rigidbody extends Behaviour implements IRigidbody {
|
|
|
204
204
|
|
|
205
205
|
get isRigidbody() { return true; }
|
|
206
206
|
|
|
207
|
-
/** When true the mass
|
|
207
|
+
/** When true the mass is automatically computed from the attached colliders using `mass = density × volume`.
|
|
208
|
+
* Each collider's {@link Collider.density} determines how heavy it contributes to the total mass.
|
|
209
|
+
* Disable to set mass explicitly via the `mass` property.
|
|
210
|
+
*/
|
|
208
211
|
@validate()
|
|
209
212
|
autoMass: boolean = true;
|
|
210
213
|
|
|
211
|
-
/**
|
|
212
|
-
*
|
|
214
|
+
/** The mass of the rigidbody in kg (when `autoMass` is disabled).
|
|
215
|
+
* When `autoMass` is enabled, reading this returns the computed mass from `density × volume` of all attached colliders.
|
|
216
|
+
* Setting this property automatically disables `autoMass`.
|
|
217
|
+
*
|
|
218
|
+
* **Prefer using {@link Collider.density}** with `autoMass` enabled instead — density scales
|
|
219
|
+
* naturally with collider size, while explicit mass stays fixed regardless of shape changes.
|
|
213
220
|
*/
|
|
214
221
|
@serializable()
|
|
215
222
|
set mass(value: number) {
|
|
@@ -403,9 +410,16 @@ export class Rigidbody extends Behaviour implements IRigidbody {
|
|
|
403
410
|
this.context.physics.engine?.removeBody(this);
|
|
404
411
|
}
|
|
405
412
|
|
|
406
|
-
onValidate() {
|
|
413
|
+
onValidate(property?: string) {
|
|
407
414
|
this._propertiesChanged = true;
|
|
415
|
+
if (property === "autoMass" && !this.autoMass) {
|
|
416
|
+
if (isDevEnvironment() && !Rigidbody._didWarnAutoMass) {
|
|
417
|
+
Rigidbody._didWarnAutoMass = true;
|
|
418
|
+
console.warn("[Rigidbody] autoMass disabled — consider using Collider.density instead of setting mass explicitly. Density scales naturally with collider size.");
|
|
419
|
+
}
|
|
420
|
+
}
|
|
408
421
|
}
|
|
422
|
+
private static _didWarnAutoMass = false;
|
|
409
423
|
|
|
410
424
|
// need to do this right before updating physics to prevent rendered object glitching through physical bodies
|
|
411
425
|
* beforePhysics() {
|
|
@@ -747,6 +747,9 @@ export class SceneSwitcher extends Behaviour {
|
|
|
747
747
|
const openedEvt = new CustomEvent<LoadSceneEvent>("scene-opened", { detail: { scene: scene, switcher: this, index: index } });
|
|
748
748
|
this.dispatchEvent(openedEvt);
|
|
749
749
|
this.sceneLoaded?.invoke(this);
|
|
750
|
+
if (this._currentSceneAsset) {
|
|
751
|
+
this.context.events.emit("scene-content-changed", { source: this, object: this._currentSceneAsset });
|
|
752
|
+
}
|
|
750
753
|
return true;
|
|
751
754
|
}
|
|
752
755
|
}
|
|
@@ -249,10 +249,10 @@ export class SeeThrough extends Behaviour {
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
const materials = renderer.sharedMaterials;// : this.rendererMaterials.get(renderer);
|
|
252
|
-
if (!materials) return;
|
|
252
|
+
if (!materials?.length) return;
|
|
253
253
|
|
|
254
254
|
const block = MaterialPropertyBlock.get(renderer.gameObject);
|
|
255
|
-
const currentOpacity = (block.getOverride("opacity")?.value ?? materials[0]
|
|
255
|
+
const currentOpacity = (block.getOverride("opacity")?.value ?? materials[0]?.opacity ?? 1);
|
|
256
256
|
|
|
257
257
|
let newAlpha = Mathf.lerp(currentOpacity, targetAlpha, duration <= 0 ? 1 : this.context.time.deltaTime / duration);;
|
|
258
258
|
if (newAlpha >= 0.99) newAlpha = 1;
|
|
@@ -34,8 +34,9 @@
|
|
|
34
34
|
* @module Built-in Components
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
+
export { AnimationBuilder, type AnimationKeyframe, type Tween, type AnimationInterpolation } from "./AnimationBuilder.js";
|
|
38
|
+
export { AnimatorControllerBuilder, type ConditionMode, type StateOptions, type TransitionOptions } from "./AnimatorController.builder.js";
|
|
37
39
|
export * from "./codegen/components.js";
|
|
38
|
-
export { AnimatorControllerBuilder, type ConditionMode, type StateOptions, type TransitionOptions } from "./AnimatorController.js";
|
|
39
40
|
export { Collider } from "./Collider.js"; // export abstract type
|
|
40
41
|
export { Behaviour, Component, GameObject } from "./Component.js";
|
|
41
42
|
|
|
@@ -3,21 +3,13 @@
|
|
|
3
3
|
export class __Ignore {}
|
|
4
4
|
export { AlignmentConstraint } from "../AlignmentConstraint.js";
|
|
5
5
|
export { Animation } from "../Animation.js";
|
|
6
|
+
export { AnimationBuilder } from "../AnimationBuilder.js";
|
|
6
7
|
export { Keyframe } from "../AnimationCurve.js";
|
|
7
8
|
export { AnimationCurve } from "../AnimationCurve.js";
|
|
8
9
|
export { Animator } from "../Animator.js";
|
|
9
|
-
export { AnimatorControllerBuilder } from "../AnimatorController.js";
|
|
10
10
|
export { AnimatorController } from "../AnimatorController.js";
|
|
11
11
|
export { AudioListener } from "../AudioListener.js";
|
|
12
12
|
export { AudioSource } from "../AudioSource.js";
|
|
13
|
-
export { Avatar_POI } from "../avatar/Avatar_Brain_LookAt.js";
|
|
14
|
-
export { Avatar_Brain_LookAt } from "../avatar/Avatar_Brain_LookAt.js";
|
|
15
|
-
export { Avatar_MouthShapes } from "../avatar/Avatar_MouthShapes.js";
|
|
16
|
-
export { Avatar_MustacheShake } from "../avatar/Avatar_MustacheShake.js";
|
|
17
|
-
export { AvatarBlink_Simple } from "../avatar/AvatarBlink_Simple.js";
|
|
18
|
-
export { AvatarEyeLook_Rotation } from "../avatar/AvatarEyeLook_Rotation.js";
|
|
19
|
-
export { AvatarModel } from "../AvatarLoader.js";
|
|
20
|
-
export { AvatarLoader } from "../AvatarLoader.js";
|
|
21
13
|
export { AxesHelper } from "../AxesHelper.js";
|
|
22
14
|
export { BasicIKConstraint } from "../BasicIKConstraint.js";
|
|
23
15
|
export { BoxHelperComponent } from "../BoxHelperComponent.js";
|
|
@@ -168,11 +160,13 @@ export { PlayableDirector } from "../timeline/PlayableDirector.js";
|
|
|
168
160
|
export { SignalAsset } from "../timeline/SignalAsset.js";
|
|
169
161
|
export { SignalReceiverEvent } from "../timeline/SignalAsset.js";
|
|
170
162
|
export { SignalReceiver } from "../timeline/SignalAsset.js";
|
|
171
|
-
export {
|
|
172
|
-
export {
|
|
173
|
-
export {
|
|
163
|
+
export { TimelineBuilder } from "../timeline/TimelineBuilder.js";
|
|
164
|
+
export { TimelineAnimationTrack } from "../timeline/TimelineTracks.js";
|
|
165
|
+
export { TimelineAudioTrack } from "../timeline/TimelineTracks.js";
|
|
166
|
+
export { TimelineMarkerTrack } from "../timeline/TimelineTracks.js";
|
|
174
167
|
export { SignalTrackHandler } from "../timeline/TimelineTracks.js";
|
|
175
|
-
export {
|
|
168
|
+
export { TimelineActivationTrack } from "../timeline/TimelineTracks.js";
|
|
169
|
+
export { TimelineControlTrack } from "../timeline/TimelineTracks.js";
|
|
176
170
|
export { TransformGizmo } from "../TransformGizmo.js";
|
|
177
171
|
export { BaseUIComponent } from "../ui/BaseUIComponent.js";
|
|
178
172
|
export { UIRootComponent } from "../ui/BaseUIComponent.js";
|
|
@@ -3,7 +3,7 @@ import { Euler, Material, Matrix4, Mesh, Object3D, Quaternion, Vector3 } from "t
|
|
|
3
3
|
|
|
4
4
|
import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../../../engine/debug/index.js";
|
|
5
5
|
import { findObjectOfType } from "../../../engine/engine_components.js";
|
|
6
|
-
import {
|
|
6
|
+
import { UFadk } from "../../../engine/engine_license.js";
|
|
7
7
|
import { serializable } from "../../../engine/engine_serialization.js";
|
|
8
8
|
import { getFormattedDate, Progress } from "../../../engine/engine_time_utils.js";
|
|
9
9
|
import { DeviceUtilities, getParam } from "../../../engine/engine_utils.js";
|
|
@@ -277,7 +277,7 @@ export class USDZExporter extends Behaviour {
|
|
|
277
277
|
let name = this.exportFileName ?? this.objectToExport?.name ?? this.name;
|
|
278
278
|
name += "-" + getFormattedDate(); // seems iOS caches the file in some cases, this ensures we always have a fresh file
|
|
279
279
|
|
|
280
|
-
if (!
|
|
280
|
+
if (!UFadk()) {
|
|
281
281
|
if (name !== "") name += "-";
|
|
282
282
|
name += "MadeWithNeedle";
|
|
283
283
|
}
|
|
@@ -682,7 +682,7 @@ export class USDZExporter extends Behaviour {
|
|
|
682
682
|
if (debug)
|
|
683
683
|
showBalloonMessage("Quicklook url: " + callToActionURL);
|
|
684
684
|
if (callToActionURL) {
|
|
685
|
-
if (!
|
|
685
|
+
if (!UFadk()) {
|
|
686
686
|
console.warn("Quicklook closed: custom redirects require a Needle Engine Pro license: https://needle.tools/pricing", callToActionURL)
|
|
687
687
|
}
|
|
688
688
|
else {
|
|
@@ -697,7 +697,7 @@ export class USDZExporter extends Behaviour {
|
|
|
697
697
|
private buildQuicklookOverlay(): CustomBranding {
|
|
698
698
|
const obj: CustomBranding = {};
|
|
699
699
|
if (this.customBranding) Object.assign(obj, this.customBranding);
|
|
700
|
-
if (!
|
|
700
|
+
if (!UFadk()) {
|
|
701
701
|
console.log("Custom Quicklook banner text requires pro license: https://needle.tools/pricing");
|
|
702
702
|
obj.callToAction = "Close";
|
|
703
703
|
obj.checkoutTitle = "🌵 Made with Needle";
|
|
@@ -4,7 +4,6 @@ import { isDevEnvironment } from '../../engine/debug/index.js';
|
|
|
4
4
|
import { FrameEvent } from '../../engine/engine_context.js';
|
|
5
5
|
import { isLocalNetwork } from '../../engine/engine_networking_utils.js';
|
|
6
6
|
import { serializable } from '../../engine/engine_serialization.js';
|
|
7
|
-
import type { GuidsMap } from '../../engine/engine_types.js';
|
|
8
7
|
import { deepClone, delay, getParam } from '../../engine/engine_utils.js';
|
|
9
8
|
import { Animator } from '../Animator.js';
|
|
10
9
|
import { AudioListener } from '../AudioListener.js';
|
|
@@ -45,7 +44,7 @@ export enum ClipExtrapolation {
|
|
|
45
44
|
};
|
|
46
45
|
|
|
47
46
|
/** @internal */
|
|
48
|
-
export type CreateTrackFunction = (director: PlayableDirector, track: Models.TrackModel) => Tracks.
|
|
47
|
+
export type CreateTrackFunction = (director: PlayableDirector, track: Models.TrackModel) => Tracks.TimelineTrackHandler | undefined | null;
|
|
49
48
|
|
|
50
49
|
/**
|
|
51
50
|
* PlayableDirector is the main component for controlling timelines in Needle Engine.
|
|
@@ -115,7 +114,15 @@ export class PlayableDirector extends Behaviour {
|
|
|
115
114
|
* The timeline asset containing tracks, clips, and markers that this director will play.
|
|
116
115
|
* Assign a timeline asset exported from Unity or Blender to enable playback.
|
|
117
116
|
*/
|
|
118
|
-
|
|
117
|
+
@serializable()
|
|
118
|
+
get playableAsset(): Models.TimelineAssetModel | undefined { return this._playableAsset; }
|
|
119
|
+
set playableAsset(value: Models.TimelineAssetModel | undefined) {
|
|
120
|
+
if (this._playableAsset !== value) {
|
|
121
|
+
this._playableAsset = value;
|
|
122
|
+
this._needsGraphRebuild = true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
private _playableAsset?: Models.TimelineAssetModel;
|
|
119
126
|
|
|
120
127
|
/**
|
|
121
128
|
* When true, the timeline starts playing automatically when the component awakens.
|
|
@@ -123,7 +130,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
123
130
|
* @default false
|
|
124
131
|
*/
|
|
125
132
|
@serializable()
|
|
126
|
-
playOnAwake
|
|
133
|
+
playOnAwake: boolean = false;
|
|
127
134
|
|
|
128
135
|
/**
|
|
129
136
|
* Determines how the timeline behaves when it reaches the end of its duration.
|
|
@@ -207,14 +214,10 @@ export class PlayableDirector extends Behaviour {
|
|
|
207
214
|
onEnable() {
|
|
208
215
|
if (debug) console.log("[Timeline] OnEnable", this.name, this.playOnAwake);
|
|
209
216
|
|
|
210
|
-
for (const
|
|
211
|
-
track
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
track.onEnable?.();
|
|
215
|
-
}
|
|
216
|
-
for (const track of this._animationTracks) {
|
|
217
|
-
track.onEnable?.();
|
|
217
|
+
for (const tracks of this._allTracks) {
|
|
218
|
+
for (const track of tracks) {
|
|
219
|
+
track.onEnable?.();
|
|
220
|
+
}
|
|
218
221
|
}
|
|
219
222
|
if (this.playOnAwake) {
|
|
220
223
|
this.play();
|
|
@@ -265,6 +268,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
265
268
|
this.resolveBindings();
|
|
266
269
|
this.updateTimelineDuration();
|
|
267
270
|
this.setupAndCreateTrackHandlers();
|
|
271
|
+
this._needsGraphRebuild = false;
|
|
268
272
|
}
|
|
269
273
|
|
|
270
274
|
/**
|
|
@@ -273,6 +277,8 @@ export class PlayableDirector extends Behaviour {
|
|
|
273
277
|
*/
|
|
274
278
|
async play() {
|
|
275
279
|
if (!this.isValid()) return;
|
|
280
|
+
// Ensure graph is built (handles the case where playableAsset is assigned after awake)
|
|
281
|
+
if (this._needsGraphRebuild) this.rebuildGraph();
|
|
276
282
|
const pauseChanged = this._isPaused == true;
|
|
277
283
|
this._isPaused = false;
|
|
278
284
|
if (this._isPlaying) return;
|
|
@@ -290,8 +296,13 @@ export class PlayableDirector extends Behaviour {
|
|
|
290
296
|
await Promise.all(promises);
|
|
291
297
|
if (!this._isPlaying) return;
|
|
292
298
|
}
|
|
293
|
-
|
|
299
|
+
let ticks = 0;
|
|
300
|
+
while (this._audioTracks.length > 0 && this._isPlaying && !AudioSource.userInteractionRegistered && this.waitForAudio) {
|
|
301
|
+
if (ticks++ <= 0) {
|
|
302
|
+
if (isDevEnvironment() || debug) console.warn(`[Timeline] Waiting for user interaction to play audio... (timeline '${this.name}' will start as soon as user interacts with the page). To start the timeline immediately without waiting for user interaction, set 'waitForAudio' to false on the PlayableDirector component.`);
|
|
303
|
+
}
|
|
294
304
|
await delay(200);
|
|
305
|
+
}
|
|
295
306
|
}
|
|
296
307
|
this.invokeStateChangedMethodsOnTracks();
|
|
297
308
|
// Update timeline in LateUpdate to give other scripts time to react to the updated state
|
|
@@ -343,6 +354,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
343
354
|
* Evaluate the timeline at the current time. This is useful when you want to manually update the timeline e.g. when the timeline is paused and you set `time` to a new value.
|
|
344
355
|
*/
|
|
345
356
|
evaluate() {
|
|
357
|
+
if (this._needsGraphRebuild) this.rebuildGraph();
|
|
346
358
|
this.internalEvaluate(true);
|
|
347
359
|
}
|
|
348
360
|
|
|
@@ -373,7 +385,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
373
385
|
/**
|
|
374
386
|
* @returns all audio tracks of the timeline
|
|
375
387
|
*/
|
|
376
|
-
get audioTracks(): Tracks.
|
|
388
|
+
get audioTracks(): Tracks.TimelineAudioTrack[] {
|
|
377
389
|
return this._audioTracks;
|
|
378
390
|
}
|
|
379
391
|
|
|
@@ -387,10 +399,24 @@ export class PlayableDirector extends Behaviour {
|
|
|
387
399
|
/**
|
|
388
400
|
* @returns all marker tracks of the timeline
|
|
389
401
|
*/
|
|
390
|
-
get markerTracks(): Tracks.
|
|
402
|
+
get markerTracks(): Tracks.TimelineMarkerTrack[] {
|
|
391
403
|
return this._markerTracks;
|
|
392
404
|
}
|
|
393
405
|
|
|
406
|
+
/**
|
|
407
|
+
* @returns all activation tracks of the timeline
|
|
408
|
+
*/
|
|
409
|
+
get activationTracks(): Tracks.TimelineActivationTrack[] {
|
|
410
|
+
return this._activationTracks;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* @returns all tracks of the timeline
|
|
415
|
+
*/
|
|
416
|
+
get tracks(): ReadonlyArray<Tracks.TimelineTrackHandler> {
|
|
417
|
+
return this._allTracks.flat();
|
|
418
|
+
}
|
|
419
|
+
|
|
394
420
|
/**
|
|
395
421
|
* Iterates over all markers of the timeline, optionally filtering by type
|
|
396
422
|
*
|
|
@@ -412,37 +438,37 @@ export class PlayableDirector extends Behaviour {
|
|
|
412
438
|
}
|
|
413
439
|
|
|
414
440
|
|
|
415
|
-
private _guidsMap?: GuidsMap;
|
|
416
|
-
/** @internal */
|
|
417
|
-
resolveGuids(map: GuidsMap) {
|
|
418
|
-
this._guidsMap = map;
|
|
419
|
-
}
|
|
420
441
|
|
|
421
442
|
// INTERNALS
|
|
422
443
|
|
|
444
|
+
private _needsGraphRebuild: boolean = false;
|
|
423
445
|
private _isPlaying: boolean = false;
|
|
424
446
|
private _internalUpdateRoutine: any;
|
|
425
447
|
private _isPaused: boolean = false;
|
|
426
448
|
/** internal, true during the time stop() is being processed */
|
|
427
449
|
private _isStopping: boolean = false;
|
|
450
|
+
/** @internal Whether the current evaluate() was triggered by user code (not the internal update loop or stop/pause). */
|
|
451
|
+
_isUserEvaluation: boolean = false;
|
|
428
452
|
private _time: number = 0;
|
|
429
453
|
private _duration: number = 0;
|
|
430
454
|
private _weight: number = 1;
|
|
431
|
-
private readonly _animationTracks: Array<Tracks.
|
|
432
|
-
private readonly _audioTracks: Array<Tracks.
|
|
455
|
+
private readonly _animationTracks: Array<Tracks.TimelineAnimationTrack> = [];
|
|
456
|
+
private readonly _audioTracks: Array<Tracks.TimelineAudioTrack> = [];
|
|
433
457
|
private readonly _signalTracks: Array<Tracks.SignalTrackHandler> = [];
|
|
434
|
-
private readonly _markerTracks: Array<Tracks.
|
|
435
|
-
private readonly _controlTracks: Array<Tracks.
|
|
436
|
-
private readonly
|
|
458
|
+
private readonly _markerTracks: Array<Tracks.TimelineMarkerTrack> = [];
|
|
459
|
+
private readonly _controlTracks: Array<Tracks.TimelineControlTrack> = [];
|
|
460
|
+
private readonly _activationTracks: Array<Tracks.TimelineActivationTrack> = [];
|
|
461
|
+
private readonly _customTracks: Array<Tracks.TimelineTrackHandler> = [];
|
|
437
462
|
|
|
438
|
-
private readonly _tracksArray: Array<Array<Tracks.
|
|
439
|
-
private get _allTracks(): Array<Array<Tracks.
|
|
463
|
+
private readonly _tracksArray: Array<Array<Tracks.TimelineTrackHandler>> = [];
|
|
464
|
+
private get _allTracks(): Array<Array<Tracks.TimelineTrackHandler>> {
|
|
440
465
|
this._tracksArray.length = 0;
|
|
441
466
|
this._tracksArray.push(this._animationTracks);
|
|
442
467
|
this._tracksArray.push(this._audioTracks);
|
|
443
468
|
this._tracksArray.push(this._signalTracks);
|
|
444
469
|
this._tracksArray.push(this._markerTracks);
|
|
445
470
|
this._tracksArray.push(this._controlTracks);
|
|
471
|
+
this._tracksArray.push(this._activationTracks);
|
|
446
472
|
this._tracksArray.push(this._customTracks);
|
|
447
473
|
return this._tracksArray;
|
|
448
474
|
}
|
|
@@ -503,60 +529,32 @@ export class PlayableDirector extends Behaviour {
|
|
|
503
529
|
|
|
504
530
|
const time = this._time;
|
|
505
531
|
|
|
506
|
-
|
|
507
|
-
if (track.muted) continue;
|
|
508
|
-
switch (track.type) {
|
|
509
|
-
case Models.TrackType.Activation:
|
|
510
|
-
// when the timeline is being disabled or stopped
|
|
511
|
-
// then we want to leave objects active state as they were
|
|
512
|
-
// see NE-3241
|
|
513
|
-
// TODO: support all "post-playback-state" settings an activation track has, this is just "Leave as is"
|
|
514
|
-
if (!called_by_user && !this._isPlaying) continue;
|
|
515
|
-
|
|
516
|
-
for (let i = 0; i < track.outputs.length; i++) {
|
|
517
|
-
const binding = track.outputs[i];
|
|
518
|
-
if (typeof binding === "object") {
|
|
519
|
-
let isActive: boolean = false;
|
|
520
|
-
if (track.clips) {
|
|
521
|
-
for (const clip of track.clips) {
|
|
522
|
-
if (clip.start <= time && time <= clip.end) {
|
|
523
|
-
isActive = true;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
const obj = binding as Object3D;
|
|
528
|
-
if (obj.visible !== undefined) {
|
|
529
|
-
if (obj.visible !== isActive) {
|
|
530
|
-
obj.visible = isActive;
|
|
531
|
-
if (debug)
|
|
532
|
-
console.warn(this.name, "set ActivationTrack-" + i, obj.name, isActive, time);
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
break;
|
|
538
|
-
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
532
|
+
this._isUserEvaluation = called_by_user;
|
|
542
533
|
for (const track of this._allTracks) {
|
|
543
534
|
for (const handler of track) {
|
|
544
535
|
// When timeline reaches the end "stop()" is called which is evaluating with time 0
|
|
545
536
|
// We don't want to re-evaluate the animation then in case the timeline is blended with the Animator
|
|
546
537
|
// e.g then the timeline animation at time 0 is 100% applied on top of the animator animation
|
|
547
|
-
|
|
548
|
-
if (this._isStopping && handler instanceof Tracks.AnimationTrackHandler) {
|
|
538
|
+
if (this._isStopping && handler instanceof Tracks.TimelineAnimationTrack) {
|
|
549
539
|
continue;
|
|
550
540
|
}
|
|
551
541
|
handler.evaluate(time);
|
|
552
542
|
}
|
|
553
543
|
}
|
|
544
|
+
this._isUserEvaluation = false;
|
|
554
545
|
}
|
|
555
546
|
|
|
556
547
|
private resolveBindings() {
|
|
557
548
|
if (!this._clonedPlayableAsset) {
|
|
558
549
|
this._clonedPlayableAsset = true;
|
|
559
|
-
|
|
550
|
+
// Deep clone so each director owns its own copy of the asset data.
|
|
551
|
+
// Needed because NEEDLE_persistent_assets returns the same shared object for all references —
|
|
552
|
+
// without this, resolving guid strings below would mutate shared data.
|
|
553
|
+
// On instantiated clones this is skipped (_clonedPlayableAsset is copied as true)
|
|
554
|
+
// because the instantiate resolve system already created an independent copy.
|
|
555
|
+
this.playableAsset = deepClone(this.playableAsset, (_obj, _key, val) => {
|
|
556
|
+
return !(val?.isObject3D === true);
|
|
557
|
+
});
|
|
560
558
|
}
|
|
561
559
|
|
|
562
560
|
if (!this.playableAsset || !this.playableAsset.tracks) return;
|
|
@@ -569,15 +567,13 @@ export class PlayableDirector extends Behaviour {
|
|
|
569
567
|
|
|
570
568
|
for (const track of this.playableAsset.tracks) {
|
|
571
569
|
for (let i = track.outputs.length - 1; i >= 0; i--) {
|
|
572
|
-
|
|
570
|
+
const binding = track.outputs[i];
|
|
573
571
|
if (typeof binding === "string") {
|
|
574
|
-
if (this._guidsMap && this._guidsMap[binding])
|
|
575
|
-
binding = this._guidsMap[binding];
|
|
576
572
|
const obj = GameObject.findByGuid(binding, root);
|
|
577
573
|
if (obj === null || typeof obj !== "object") {
|
|
578
574
|
// if the binding is missing remove it to avoid unnecessary loops
|
|
579
575
|
track.outputs.splice(i, 1);
|
|
580
|
-
console.warn(
|
|
576
|
+
console.warn(`[Timeline] Failed to resolve binding on track '${track.name}' of type '${track.type}' in director '${this.name}' with timeline asset '${this.playableAsset.name}' ('${binding}' not found in scene)`);
|
|
581
577
|
}
|
|
582
578
|
else {
|
|
583
579
|
if (debug)
|
|
@@ -592,21 +588,20 @@ export class PlayableDirector extends Behaviour {
|
|
|
592
588
|
continue;
|
|
593
589
|
}
|
|
594
590
|
// if the binding is missing remove it to avoid unnecessary loops
|
|
595
|
-
if (track.type !== Models.TrackType.Audio && track.type !== Models.TrackType.Control && track.type !== Models.TrackType.Marker && track.type !== Models.TrackType.Signal)
|
|
596
|
-
console.warn(
|
|
591
|
+
if (track.type !== Models.TrackType.Audio && track.type !== Models.TrackType.Control && track.type !== Models.TrackType.Marker && track.type !== Models.TrackType.Signal) {
|
|
592
|
+
console.warn(`[Timeline] Missing binding on track '${track.name}' of type '${track.type}' in director '${this.name}' with timeline asset '${this.playableAsset.name}' (null binding)`);
|
|
593
|
+
}
|
|
597
594
|
}
|
|
598
595
|
}
|
|
599
596
|
if (track.type === Models.TrackType.Control) {
|
|
600
597
|
if (track.clips) {
|
|
601
598
|
for (let i = 0; i < track.clips.length; i++) {
|
|
602
599
|
const clip = track.clips[i];
|
|
603
|
-
|
|
600
|
+
const binding = clip.asset.sourceObject;
|
|
604
601
|
if (typeof binding === "string") {
|
|
605
|
-
if (this._guidsMap && this._guidsMap[binding])
|
|
606
|
-
binding = this._guidsMap[binding];
|
|
607
602
|
const obj = GameObject.findByGuid(binding, root);
|
|
608
603
|
if (obj === null || typeof obj !== "object") {
|
|
609
|
-
console.warn(
|
|
604
|
+
console.warn(`[Timeline] Failed to resolve sourceObject binding on track '${track.name}' of type '${track.type}' in director '${this.name}' with timeline asset '${this.playableAsset.name}' ('${binding}' not found in scene)`);
|
|
610
605
|
}
|
|
611
606
|
else {
|
|
612
607
|
if (debug)
|
|
@@ -649,6 +644,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
649
644
|
this._animationTracks.length = 0;
|
|
650
645
|
this._audioTracks.length = 0;
|
|
651
646
|
this._signalTracks.length = 0;
|
|
647
|
+
this._activationTracks.length = 0;
|
|
652
648
|
|
|
653
649
|
if (!this.playableAsset) return;
|
|
654
650
|
let audioListener: AudioListener | null = GameObject.findObjectOfType(AudioListener, this.context);
|
|
@@ -656,7 +652,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
656
652
|
const type = track.type;
|
|
657
653
|
const registered = PlayableDirector.createTrackFunctions[type];
|
|
658
654
|
if (registered !== null && registered !== undefined) {
|
|
659
|
-
const res = registered(this, track) as Tracks.
|
|
655
|
+
const res = registered(this, track) as Tracks.TimelineTrackHandler;
|
|
660
656
|
if (typeof res.evaluate === "function") {
|
|
661
657
|
res.director = this;
|
|
662
658
|
res.track = track;
|
|
@@ -679,7 +675,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
679
675
|
}
|
|
680
676
|
const animationClips = binding?.gameObject?.animations;
|
|
681
677
|
if (animationClips) {
|
|
682
|
-
const handler = new Tracks.
|
|
678
|
+
const handler = new Tracks.TimelineAnimationTrack();
|
|
683
679
|
handler.trackOffset = track.trackOffset;
|
|
684
680
|
handler.director = this;
|
|
685
681
|
handler.track = track;
|
|
@@ -729,7 +725,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
729
725
|
}
|
|
730
726
|
else if (track.type === Models.TrackType.Audio) {
|
|
731
727
|
if (!track.clips || track.clips.length <= 0) continue;
|
|
732
|
-
const audio = new Tracks.
|
|
728
|
+
const audio = new Tracks.TimelineAudioTrack();
|
|
733
729
|
audio.director = this;
|
|
734
730
|
audio.track = track;
|
|
735
731
|
audio.audioSource = track.outputs.find(o => o instanceof AudioSource) as AudioSource;
|
|
@@ -753,7 +749,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
753
749
|
signalHandler.director = this;
|
|
754
750
|
signalHandler.track = track;
|
|
755
751
|
|
|
756
|
-
const markerHandler: Tracks.
|
|
752
|
+
const markerHandler: Tracks.TimelineMarkerTrack = new Tracks.TimelineMarkerTrack();
|
|
757
753
|
markerHandler.director = this;
|
|
758
754
|
markerHandler.track = track;
|
|
759
755
|
|
|
@@ -799,7 +795,7 @@ export class PlayableDirector extends Behaviour {
|
|
|
799
795
|
this._signalTracks.push(handler);
|
|
800
796
|
}
|
|
801
797
|
else if (track.type === Models.TrackType.Control) {
|
|
802
|
-
const handler = new Tracks.
|
|
798
|
+
const handler = new Tracks.TimelineControlTrack();
|
|
803
799
|
handler.director = this;
|
|
804
800
|
handler.track = track;
|
|
805
801
|
if (track.clips) {
|
|
@@ -810,6 +806,12 @@ export class PlayableDirector extends Behaviour {
|
|
|
810
806
|
handler.resolveSourceObjects(this.context);
|
|
811
807
|
this._controlTracks.push(handler);
|
|
812
808
|
}
|
|
809
|
+
else if (track.type === Models.TrackType.Activation) {
|
|
810
|
+
const handler = new Tracks.TimelineActivationTrack();
|
|
811
|
+
handler.director = this;
|
|
812
|
+
handler.track = track;
|
|
813
|
+
this._activationTracks.push(handler);
|
|
814
|
+
}
|
|
813
815
|
}
|
|
814
816
|
}
|
|
815
817
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { serializable } from "../../engine/engine_serialization_decorator.js";
|
|
2
|
+
import { ISignalReceiver } from "../../engine/engine_types.js";
|
|
2
3
|
import { getParam } from "../../engine/engine_utils.js";
|
|
3
4
|
import { Behaviour } from "../Component.js";
|
|
4
5
|
import { EventList } from "../EventList.js";
|
|
@@ -33,7 +34,9 @@ export class SignalReceiverEvent {
|
|
|
33
34
|
* @category Animation and Sequencing
|
|
34
35
|
* @group Components
|
|
35
36
|
*/
|
|
36
|
-
export class SignalReceiver extends Behaviour {
|
|
37
|
+
export class SignalReceiver extends Behaviour implements ISignalReceiver {
|
|
38
|
+
|
|
39
|
+
readonly isSignalReceiver = true;
|
|
37
40
|
|
|
38
41
|
private static receivers: { [key: string]: SignalReceiver[] } = {};
|
|
39
42
|
|