@needle-tools/engine 5.1.0-canary.30cc545 → 5.1.0-canary.40da791
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.needle/generated/needle-bindings.gen.d.ts +5 -0
- package/CHANGELOG.md +91 -0
- package/SKILL.md +4 -1
- package/components.needle.json +1 -1
- package/dist/{needle-engine.bundle-d_9mSxN4.js → needle-engine.bundle-Cu2B9CsR.js} +16112 -15269
- package/dist/needle-engine.bundle-ZoVUaB89.umd.cjs +1733 -0
- package/dist/needle-engine.bundle-hBWUJPxm.min.js +1733 -0
- package/dist/needle-engine.d.ts +1527 -384
- package/dist/needle-engine.js +573 -569
- 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 +6 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/codegen/register_types.js +10 -18
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/debug/debug_spatial_console.d.ts +2 -0
- package/lib/engine/debug/debug_spatial_console.js +10 -7
- package/lib/engine/debug/debug_spatial_console.js.map +1 -1
- package/lib/engine/engine_addressables.d.ts +2 -0
- package/lib/engine/engine_addressables.js +6 -3
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_audio.d.ts +68 -0
- package/lib/engine/engine_audio.js +172 -0
- package/lib/engine/engine_audio.js.map +1 -1
- package/lib/engine/engine_camera.fit.js +16 -4
- package/lib/engine/engine_camera.fit.js.map +1 -1
- package/lib/engine/engine_components.js +1 -1
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_context.d.ts +41 -27
- package/lib/engine/engine_context.js +57 -30
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_context_eventbus.d.ts +47 -0
- package/lib/engine/engine_context_eventbus.js +47 -0
- package/lib/engine/engine_context_eventbus.js.map +1 -0
- package/lib/engine/engine_disposable.d.ts +172 -0
- package/lib/engine/engine_disposable.js +136 -0
- package/lib/engine/engine_disposable.js.map +1 -0
- package/lib/engine/engine_gameobject.d.ts +1 -10
- package/lib/engine/engine_gameobject.js +22 -120
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_gltf_builtin_components.js +7 -69
- package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
- package/lib/engine/engine_init.js +16 -1
- package/lib/engine/engine_init.js.map +1 -1
- package/lib/engine/engine_input.d.ts +24 -5
- package/lib/engine/engine_input.js +3 -2
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_instantiate_resolve.d.ts +42 -0
- package/lib/engine/engine_instantiate_resolve.js +372 -0
- package/lib/engine/engine_instantiate_resolve.js.map +1 -0
- package/lib/engine/engine_license.d.ts +2 -0
- package/lib/engine/engine_license.js +14 -6
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_lifecycle_functions_internal.js +5 -0
- package/lib/engine/engine_lifecycle_functions_internal.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.js +7 -4
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_networking.d.ts +51 -37
- package/lib/engine/engine_networking.js +132 -82
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine/engine_networking.transport.websocket.d.ts +15 -0
- package/lib/engine/engine_networking.transport.websocket.js +38 -0
- package/lib/engine/engine_networking.transport.websocket.js.map +1 -0
- package/lib/engine/engine_networking_blob.js +1 -1
- 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.d.ts +13 -17
- package/lib/engine/engine_scenedata.js +58 -31
- package/lib/engine/engine_scenedata.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.d.ts +10 -16
- package/lib/engine/engine_serialization_builtin_serializer.js +56 -46
- package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
- package/lib/engine/engine_serialization_core.d.ts +1 -0
- package/lib/engine/engine_serialization_core.js +7 -0
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_ssr.d.ts +2 -0
- package/lib/engine/engine_ssr.js +2 -0
- package/lib/engine/engine_ssr.js.map +1 -1
- package/lib/engine/engine_types.d.ts +31 -11
- package/lib/engine/engine_types.js +1 -1
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_util_decorator.js +7 -2
- package/lib/engine/engine_util_decorator.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +1 -1
- package/lib/engine/engine_utils.js +19 -5
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
- package/lib/engine/webcomponents/jsx.d.ts +51 -0
- package/lib/engine/webcomponents/logo-element.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +3 -4
- package/lib/engine/webcomponents/needle menu/needle-menu.js +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-button.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.d.ts +10 -4
- package/lib/engine/webcomponents/needle-engine.js +1 -1
- package/lib/engine/webcomponents/needle-engine.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/events.d.ts +1 -1
- package/lib/engine/xr/events.js.map +1 -1
- package/lib/engine-components/Animation.js +17 -16
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/AnimationBuilder.d.ts +158 -0
- package/lib/engine-components/AnimationBuilder.js +305 -0
- package/lib/engine-components/AnimationBuilder.js.map +1 -0
- package/lib/engine-components/Animator.d.ts +6 -0
- package/lib/engine-components/Animator.js +23 -13
- package/lib/engine-components/Animator.js.map +1 -1
- package/lib/engine-components/AnimatorController.builder.d.ts +191 -0
- package/lib/engine-components/AnimatorController.builder.js +263 -0
- package/lib/engine-components/AnimatorController.builder.js.map +1 -0
- package/lib/engine-components/AnimatorController.d.ts +4 -119
- package/lib/engine-components/AnimatorController.js +37 -233
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/AudioSource.d.ts +19 -3
- package/lib/engine-components/AudioSource.js +121 -68
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/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.d.ts +6 -8
- package/lib/engine-components/Light.js +48 -27
- package/lib/engine-components/Light.js.map +1 -1
- package/lib/engine-components/Networking.d.ts +1 -1
- package/lib/engine-components/Networking.js +1 -1
- package/lib/engine-components/OrbitControls.d.ts +0 -2
- package/lib/engine-components/OrbitControls.js +30 -12
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.js +2 -0
- package/lib/engine-components/ReflectionProbe.js.map +1 -1
- package/lib/engine-components/RigidBody.d.ts +12 -4
- package/lib/engine-components/RigidBody.js +18 -4
- package/lib/engine-components/RigidBody.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.js +3 -0
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/SeeThrough.js +2 -2
- package/lib/engine-components/SeeThrough.js.map +1 -1
- package/lib/engine-components/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/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
- package/lib/engine-components/postprocessing/VolumeParameter.d.ts +2 -0
- package/lib/engine-components/postprocessing/VolumeParameter.js +4 -1
- package/lib/engine-components/postprocessing/VolumeParameter.js.map +1 -1
- package/lib/engine-components/timeline/PlayableDirector.d.ts +21 -11
- package/lib/engine-components/timeline/PlayableDirector.js +75 -67
- package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
- package/lib/engine-components/timeline/SignalAsset.d.ts +3 -1
- package/lib/engine-components/timeline/SignalAsset.js +1 -0
- package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
- package/lib/engine-components/timeline/TimelineBuilder.d.ts +413 -0
- package/lib/engine-components/timeline/TimelineBuilder.js +506 -0
- package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -0
- package/lib/engine-components/timeline/TimelineModels.d.ts +2 -1
- package/lib/engine-components/timeline/TimelineModels.js +3 -0
- package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
- package/lib/engine-components/timeline/TimelineTracks.d.ts +37 -6
- package/lib/engine-components/timeline/TimelineTracks.js +92 -26
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/lib/engine-components/timeline/index.d.ts +2 -1
- package/lib/engine-components/timeline/index.js +2 -0
- package/lib/engine-components/timeline/index.js.map +1 -1
- package/lib/engine-components/ui/Canvas.d.ts +1 -1
- package/lib/engine-components/ui/Canvas.js +2 -8
- package/lib/engine-components/ui/Canvas.js.map +1 -1
- package/lib/engine-components/ui/Text.d.ts +1 -0
- package/lib/engine-components/ui/Text.js +10 -7
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/engine-components/web/CursorFollow.d.ts +0 -1
- package/lib/engine-components/web/CursorFollow.js +21 -13
- package/lib/engine-components/web/CursorFollow.js.map +1 -1
- package/lib/engine-components/webxr/WebXRImageTracking.js +4 -0
- package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
- package/lib/needle-engine.d.ts +2 -0
- package/lib/needle-engine.js +2 -0
- package/lib/needle-engine.js.map +1 -1
- package/package.json +3 -83
- package/plugins/common/license.js +5 -2
- package/plugins/common/worker.js +9 -4
- package/plugins/dts-generator/dts.codegen.js +255 -50
- package/plugins/dts-generator/dts.scan.js +37 -9
- package/plugins/dts-generator/dts.writer.js +1 -1
- package/plugins/dts-generator/glb.discovery.js +140 -23
- package/plugins/dts-generator/glb.extractor.js +48 -8
- package/plugins/dts-generator/glb.reader.js +80 -27
- package/plugins/dts-generator/index.js +1 -1
- package/plugins/types/needle-bindings.d.ts +25 -14
- package/plugins/types/userconfig.d.ts +12 -0
- package/plugins/vite/asap.js +18 -9
- package/plugins/vite/dependencies.js +29 -10
- package/plugins/vite/dependency-watcher.d.ts +2 -2
- package/plugins/vite/dependency-watcher.js +5 -6
- package/plugins/vite/drop.d.ts +2 -2
- package/plugins/vite/drop.js +3 -4
- package/plugins/vite/dts-generator.d.ts +2 -2
- package/plugins/vite/dts-generator.js +43 -9
- package/plugins/vite/editor-connection.js +3 -3
- package/plugins/vite/index.d.ts +9 -3
- package/plugins/vite/index.js +23 -10
- package/plugins/vite/license.js +19 -1
- package/plugins/vite/local-files-core.js +3 -3
- package/plugins/vite/local-files-utils.d.ts +3 -1
- package/plugins/vite/local-files-utils.js +29 -5
- package/plugins/vite/meta.js +4 -2
- package/plugins/vite/poster.d.ts +2 -2
- package/plugins/vite/poster.js +3 -5
- package/plugins/vite/reload.d.ts +2 -2
- package/plugins/vite/reload.js +23 -23
- package/plugins/vite/server.js +2 -1
- package/src/engine/api.ts +11 -1
- package/src/engine/codegen/register_types.ts +10 -18
- package/src/engine/debug/debug_spatial_console.ts +10 -7
- package/src/engine/engine_addressables.ts +6 -3
- package/src/engine/engine_audio.ts +184 -0
- package/src/engine/engine_camera.fit.ts +15 -4
- package/src/engine/engine_components.ts +1 -1
- package/src/engine/engine_context.ts +67 -37
- package/src/engine/engine_context_eventbus.ts +73 -0
- package/src/engine/engine_disposable.ts +214 -0
- package/src/engine/engine_gameobject.ts +54 -159
- package/src/engine/engine_gltf_builtin_components.ts +7 -76
- package/src/engine/engine_init.ts +15 -1
- package/src/engine/engine_input.ts +28 -7
- package/src/engine/engine_instantiate_resolve.ts +407 -0
- package/src/engine/engine_license.ts +12 -10
- package/src/engine/engine_lifecycle_functions_internal.ts +7 -0
- package/src/engine/engine_mainloop_utils.ts +7 -4
- package/src/engine/engine_networking.transport.websocket.ts +45 -0
- package/src/engine/engine_networking.ts +161 -137
- package/src/engine/engine_networking_blob.ts +1 -1
- 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 +56 -30
- package/src/engine/engine_serialization_builtin_serializer.ts +64 -52
- package/src/engine/engine_serialization_core.ts +9 -0
- package/src/engine/engine_ssr.ts +3 -0
- package/src/engine/engine_types.ts +48 -27
- package/src/engine/engine_util_decorator.ts +7 -2
- package/src/engine/engine_utils.ts +16 -5
- package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
- package/src/engine/webcomponents/jsx.d.ts +51 -0
- package/src/engine/webcomponents/logo-element.ts +1 -0
- package/src/engine/webcomponents/needle menu/needle-menu.ts +3 -2
- package/src/engine/webcomponents/needle-button.ts +1 -0
- package/src/engine/webcomponents/needle-engine.ts +11 -4
- package/src/engine/xr/NeedleXRSession.ts +48 -13
- package/src/engine/xr/events.ts +1 -1
- package/src/engine-components/Animation.ts +19 -16
- package/src/engine-components/AnimationBuilder.ts +472 -0
- package/src/engine-components/Animator.ts +24 -12
- package/src/engine-components/AnimatorController.builder.ts +387 -0
- package/src/engine-components/AnimatorController.ts +24 -292
- package/src/engine-components/AudioSource.ts +130 -79
- package/src/engine-components/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 +49 -27
- package/src/engine-components/Networking.ts +1 -1
- package/src/engine-components/OrbitControls.ts +34 -14
- package/src/engine-components/ReflectionProbe.ts +2 -0
- package/src/engine-components/RigidBody.ts +18 -4
- package/src/engine-components/SceneSwitcher.ts +3 -0
- package/src/engine-components/SeeThrough.ts +2 -2
- package/src/engine-components/api.ts +2 -1
- package/src/engine-components/codegen/components.ts +7 -13
- package/src/engine-components/postprocessing/VolumeParameter.ts +4 -1
- package/src/engine-components/timeline/PlayableDirector.ts +83 -81
- package/src/engine-components/timeline/SignalAsset.ts +4 -1
- package/src/engine-components/timeline/TimelineBuilder.ts +824 -0
- package/src/engine-components/timeline/TimelineModels.ts +5 -1
- package/src/engine-components/timeline/TimelineTracks.ts +96 -27
- package/src/engine-components/timeline/index.ts +2 -1
- package/src/engine-components/ui/Canvas.ts +2 -8
- package/src/engine-components/ui/Text.ts +12 -8
- package/src/engine-components/web/CursorFollow.ts +21 -14
- package/src/engine-components/webxr/WebXRImageTracking.ts +2 -0
- package/src/needle-engine.ts +3 -0
- package/dist/needle-engine.bundle-BMlLSACE.umd.cjs +0 -1732
- package/dist/needle-engine.bundle-BXPPQRer.min.js +0 -1732
- package/lib/engine-components/AvatarLoader.d.ts +0 -80
- package/lib/engine-components/AvatarLoader.js +0 -232
- package/lib/engine-components/AvatarLoader.js.map +0 -1
- package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +0 -11
- package/lib/engine-components/avatar/AvatarBlink_Simple.js +0 -77
- package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +0 -1
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +0 -14
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +0 -69
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +0 -1
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +0 -29
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +0 -122
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +0 -1
- package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +0 -15
- package/lib/engine-components/avatar/Avatar_MouthShapes.js +0 -80
- package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +0 -1
- package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +0 -9
- package/lib/engine-components/avatar/Avatar_MustacheShake.js +0 -30
- package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +0 -1
- package/src/engine-components/AvatarLoader.ts +0 -264
- package/src/engine-components/avatar/AvatarBlink_Simple.ts +0 -70
- package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +0 -64
- package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +0 -140
- package/src/engine-components/avatar/Avatar_MouthShapes.ts +0 -84
- package/src/engine-components/avatar/Avatar_MustacheShake.ts +0 -32
package/plugins/vite/reload.js
CHANGED
|
@@ -7,6 +7,7 @@ import { existsSync, readFileSync, statSync } from 'fs';
|
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
8
|
import { needleLog } from './logging.js';
|
|
9
9
|
|
|
10
|
+
const pluginName = "needle-reload";
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
12
|
const __dirname = path.dirname(__filename);
|
|
12
13
|
|
|
@@ -15,14 +16,12 @@ const filesUsingHotReload = new Set();
|
|
|
15
16
|
let assetsDirectory = "";
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
|
-
* @param {"build" | "serve"}
|
|
19
|
+
* @param {"build" | "serve" | undefined} _command
|
|
19
20
|
* @param {import('../types/needleConfig').needleMeta | null} config
|
|
20
21
|
* @param {import('../types').userSettings} userSettings
|
|
21
22
|
* @returns {import('vite').Plugin | undefined}
|
|
22
23
|
*/
|
|
23
|
-
export function needleReload(
|
|
24
|
-
if (command === "build") return undefined;
|
|
25
|
-
|
|
24
|
+
export function needleReload(_command, config, userSettings) {
|
|
26
25
|
if (userSettings?.noReload === true) return undefined;
|
|
27
26
|
|
|
28
27
|
|
|
@@ -41,7 +40,7 @@ export function needleReload(command, config, userSettings) {
|
|
|
41
40
|
const buildDirectory = projectConfig?.buildDirectory?.length ? process.cwd().replaceAll("\\", "/") + "/" + projectConfig?.buildDirectory : "";
|
|
42
41
|
if (buildDirectory?.length) {
|
|
43
42
|
const relativeBuildDirectory = path.relative(process.cwd(), buildDirectory).replaceAll("\\", "/") || ".";
|
|
44
|
-
setTimeout(() => needleLog(
|
|
43
|
+
setTimeout(() => needleLog(pluginName, "Build directory: " + relativeBuildDirectory), 100);
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
// These ignore patterns will be injected into user config to better control vite reloading
|
|
@@ -51,6 +50,7 @@ export function needleReload(command, config, userSettings) {
|
|
|
51
50
|
|
|
52
51
|
return {
|
|
53
52
|
name: 'needle:reload',
|
|
53
|
+
apply: 'serve',
|
|
54
54
|
/** @param {import('vite').UserConfig} config */
|
|
55
55
|
config(config) {
|
|
56
56
|
if (!config.server) config.server = { watch: { ignored: [] } };
|
|
@@ -60,7 +60,7 @@ export function needleReload(command, config, userSettings) {
|
|
|
60
60
|
// @ts-ignore - watch.ignored is guaranteed to be string[] by the guards above
|
|
61
61
|
config.server.watch.ignored.push(pattern);
|
|
62
62
|
if (userSettings?.debug === true)
|
|
63
|
-
setTimeout(() => needleLog(
|
|
63
|
+
setTimeout(() => needleLog(pluginName, "Updated server ignore patterns: " + JSON.stringify(config.server?.watch?.ignored)), 100);
|
|
64
64
|
},
|
|
65
65
|
/** @param {import('vite').HmrContext & {buildDirectory?: string}} args */
|
|
66
66
|
handleHotUpdate(args) {
|
|
@@ -119,7 +119,7 @@ function getHot(server) {
|
|
|
119
119
|
|
|
120
120
|
/** @param {import('vite').ViteDevServer} server @param {string} [file] */
|
|
121
121
|
function notifyClientWillReload(server, file) {
|
|
122
|
-
|
|
122
|
+
needleLog(pluginName, "Send reload notification");
|
|
123
123
|
getHot(server).send('needle:reload', { type: 'will-reload', file: file });
|
|
124
124
|
}
|
|
125
125
|
|
|
@@ -135,7 +135,7 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
|
|
|
135
135
|
|
|
136
136
|
// Dont reload the whole server when a file that is using hot reload changes
|
|
137
137
|
if (filesUsingHotReload.has(file)) {
|
|
138
|
-
|
|
138
|
+
needleLog(pluginName, "File is using hot reload: " + file);
|
|
139
139
|
return null;
|
|
140
140
|
}
|
|
141
141
|
|
|
@@ -154,7 +154,7 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
|
|
|
154
154
|
// instead of relying on the vite server watch ignore array
|
|
155
155
|
// we could here also match paths that we know we dont want to track
|
|
156
156
|
if (ignorePatterns.length > 0 && ignoreRegex.test(file)) {
|
|
157
|
-
|
|
157
|
+
needleLog(pluginName, "Ignore change in file: " + getFileNameLog(file));
|
|
158
158
|
return [];
|
|
159
159
|
}
|
|
160
160
|
|
|
@@ -164,7 +164,7 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
|
|
|
164
164
|
if (buildDirectory?.length) {
|
|
165
165
|
const dir = path.dirname(file).replaceAll("\\", "/");
|
|
166
166
|
if (dir.startsWith(buildDirectory)) {
|
|
167
|
-
|
|
167
|
+
needleLog(pluginName, "Ignore change in build directory: " + getFileNameLog(file));
|
|
168
168
|
return [];
|
|
169
169
|
}
|
|
170
170
|
}
|
|
@@ -174,18 +174,18 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
|
|
|
174
174
|
// meaning if its the first export after the server starts those will not trigger a reload
|
|
175
175
|
// Ignore d.ts
|
|
176
176
|
const shouldCheckIfContentChanged = file.includes("/codegen/") || file.includes("/generated/") || file.endsWith("gen.js");// || file.endsWith(".glb") || file.endsWith(".gltf") || file.endsWith(".bin");
|
|
177
|
-
if (
|
|
177
|
+
if (!file.includes("/.svelte-kit/") && !file.endsWith(".d.ts") && !file.endsWith("needle-html-data.json") && shouldCheckIfContentChanged) {
|
|
178
178
|
if (reloadIsScheduled) {
|
|
179
179
|
return [];
|
|
180
180
|
}
|
|
181
181
|
if (await testIfFileContentChanged(file, read) === false) {
|
|
182
|
-
|
|
182
|
+
needleLog(pluginName, "File content didnt change: " + getFileNameLog(file));
|
|
183
183
|
return [];
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
// these are known file types we export from integrations
|
|
188
|
-
const knownExportFileTypes = [
|
|
188
|
+
const knownExportFileTypes = [".glb", ".gltf", ".bin", "exr", ".ktx2", ".mp3", ".ogg", ".mp4", ".webm"];
|
|
189
189
|
if (!knownExportFileTypes.some((type) => file.endsWith(type)))
|
|
190
190
|
return null;
|
|
191
191
|
|
|
@@ -209,7 +209,7 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
|
|
212
|
+
needleLog(pluginName, "> Detected file change: " + getFileNameLog(file) + " (" + ((fileSize / (1024 * 1024)).toFixed(1)) + " MB)");
|
|
213
213
|
notifyClientWillReload(server);
|
|
214
214
|
scheduleReload(server);
|
|
215
215
|
return [];
|
|
@@ -224,8 +224,8 @@ async function scheduleReload(server, level = 0) {
|
|
|
224
224
|
const lockFile = path.join(process.cwd(), lockFileName);
|
|
225
225
|
if (existsSync(lockFile)) {
|
|
226
226
|
if (level === 0)
|
|
227
|
-
|
|
228
|
-
setTimeout(() => scheduleReload(server, level += 1), 300);
|
|
227
|
+
needleLog(pluginName, "Lock file exists, waiting for export to finish...");
|
|
228
|
+
setTimeout(() => scheduleReload(server, level += 1), 300).unref();
|
|
229
229
|
return;
|
|
230
230
|
}
|
|
231
231
|
|
|
@@ -235,13 +235,13 @@ async function scheduleReload(server, level = 0) {
|
|
|
235
235
|
if (timeDiff < 1000) {
|
|
236
236
|
// Sometimes file changes happen immediately after triggering a reload
|
|
237
237
|
// we dont want to reload again in that case
|
|
238
|
-
|
|
238
|
+
needleLog(pluginName, "Ignoring reload, last reload was too recent" + timeDiff + "ms ago");
|
|
239
239
|
return;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
lastReloadTime = Date.now();
|
|
243
243
|
const readableTime = new Date(lastReloadTime).toLocaleTimeString();
|
|
244
|
-
|
|
244
|
+
needleLog(pluginName, "< Reloading... " + readableTime);
|
|
245
245
|
getHot(server).send({
|
|
246
246
|
type: 'full-reload',
|
|
247
247
|
path: '*'
|
|
@@ -300,10 +300,10 @@ function removeVersionQueryArgument(content) {
|
|
|
300
300
|
function insertScriptRegisterHotReloadCode(src, filePath) {
|
|
301
301
|
|
|
302
302
|
// We only want to inject the hot reload code in the needle-engine root file
|
|
303
|
-
if(!filePath.includes("/src/needle-engine.ts")) {
|
|
303
|
+
if (!filePath.includes("/src/needle-engine.ts")) {
|
|
304
304
|
return src;
|
|
305
305
|
}
|
|
306
|
-
|
|
306
|
+
needleLog(pluginName, "[Needle HMR] Hot reload is enabled");
|
|
307
307
|
// this code let's the engine know that we are in hot reload mode
|
|
308
308
|
const code = `
|
|
309
309
|
globalThis.NEEDLE_HOT_RELOAD_ENABLED = true;
|
|
@@ -339,12 +339,12 @@ function insertScriptHotReloadCode(src, filePath) {
|
|
|
339
339
|
return undefined;
|
|
340
340
|
// make import path from engine package
|
|
341
341
|
const fullPathToHotReload = process.cwd() + "/node_modules/@needle-tools/engine/src/engine/engine_hot_reload.ts";
|
|
342
|
-
//
|
|
342
|
+
// needleLog(pluginName, fullPathToHotReload);
|
|
343
343
|
const fileDirectory = path.dirname(filePath);
|
|
344
|
-
//
|
|
344
|
+
// needleLog(pluginName, "DIR", fileDirectory)
|
|
345
345
|
const relativePath = path.relative(fileDirectory, fullPathToHotReload);
|
|
346
346
|
importPath = relativePath.replace(/\\/g, "/");
|
|
347
|
-
//
|
|
347
|
+
// needleLog(pluginName, "importPath: ", importPath);
|
|
348
348
|
}
|
|
349
349
|
|
|
350
350
|
// console.log(importPath, ">", filePath);
|
package/plugins/vite/server.js
CHANGED
|
@@ -60,7 +60,8 @@ export function needleServer(command, config, userSettings) {
|
|
|
60
60
|
})
|
|
61
61
|
.catch((err) => console.error("ERR: [needle:server] 'open' package not found - please make sure to install 'open' in your package.json\n", err));
|
|
62
62
|
}
|
|
63
|
-
}, 100)
|
|
63
|
+
}, 100);
|
|
64
|
+
i.unref();
|
|
64
65
|
}
|
|
65
66
|
},
|
|
66
67
|
}
|
package/src/engine/api.ts
CHANGED
|
@@ -114,6 +114,9 @@ export * from "./engine_addressables.js";
|
|
|
114
114
|
/** Animation playback and control utilities */
|
|
115
115
|
export { AnimationUtils } from "./engine_animation.js";
|
|
116
116
|
|
|
117
|
+
/** Standalone audio clip for playback control */
|
|
118
|
+
export { AudioClip } from "./engine_audio.js";
|
|
119
|
+
|
|
117
120
|
/** Application-level state and utilities */
|
|
118
121
|
export { Application } from "./engine_application.js";
|
|
119
122
|
|
|
@@ -164,6 +167,9 @@ export * from "./engine_constants.js";
|
|
|
164
167
|
*/
|
|
165
168
|
export * from "./engine_context.js";
|
|
166
169
|
|
|
170
|
+
/** Typed event bus for decoupled component communication via {@link Context.events} */
|
|
171
|
+
export * from "./engine_context_eventbus.js";
|
|
172
|
+
|
|
167
173
|
/** Registry for managing multiple engine contexts */
|
|
168
174
|
export * from "./engine_context_registry.js";
|
|
169
175
|
|
|
@@ -173,6 +179,10 @@ export * from "./engine_context_registry.js";
|
|
|
173
179
|
*/
|
|
174
180
|
export * from "./engine_coroutine.js"
|
|
175
181
|
|
|
182
|
+
/** DisposableStore for managing lifecycle-bound cleanup in components */
|
|
183
|
+
export { DisposableStore, on, isDisposable } from "./engine_disposable.js";
|
|
184
|
+
export type { DisposeFn, IDisposable } from "./engine_disposable.js";
|
|
185
|
+
|
|
176
186
|
/** Factory functions for creating primitives and objects */
|
|
177
187
|
export * from "./engine_create_objects.js";
|
|
178
188
|
|
|
@@ -450,4 +460,4 @@ export * from "./xr/api.js"
|
|
|
450
460
|
* import type { SceneData } from "@needle-tools/engine";
|
|
451
461
|
* type OrbitSettings = SceneData["Camera"]["OrbitControls"];
|
|
452
462
|
*/
|
|
453
|
-
export type { SceneData } from "needle
|
|
463
|
+
export type { SceneData } from "needle-bindings";
|
|
@@ -7,11 +7,6 @@ import { Animation } from "../../engine-components/Animation.js";
|
|
|
7
7
|
import { Animator } from "../../engine-components/Animator.js";
|
|
8
8
|
import { AudioListener } from "../../engine-components/AudioListener.js";
|
|
9
9
|
import { AudioSource } from "../../engine-components/AudioSource.js";
|
|
10
|
-
import { Avatar_Brain_LookAt } from "../../engine-components/avatar/Avatar_Brain_LookAt.js";
|
|
11
|
-
import { Avatar_MouthShapes } from "../../engine-components/avatar/Avatar_MouthShapes.js";
|
|
12
|
-
import { Avatar_MustacheShake } from "../../engine-components/avatar/Avatar_MustacheShake.js";
|
|
13
|
-
import { AvatarBlink_Simple } from "../../engine-components/avatar/AvatarBlink_Simple.js";
|
|
14
|
-
import { AvatarEyeLook_Rotation } from "../../engine-components/avatar/AvatarEyeLook_Rotation.js";
|
|
15
10
|
import { AxesHelper } from "../../engine-components/AxesHelper.js";
|
|
16
11
|
import { BasicIKConstraint } from "../../engine-components/BasicIKConstraint.js";
|
|
17
12
|
import { BoxHelperComponent } from "../../engine-components/BoxHelperComponent.js";
|
|
@@ -106,11 +101,12 @@ import { TestRunner } from "../../engine-components/TestRunner.js";
|
|
|
106
101
|
import { TestSimulateUserData } from "../../engine-components/TestRunner.js";
|
|
107
102
|
import { PlayableDirector } from "../../engine-components/timeline/PlayableDirector.js";
|
|
108
103
|
import { SignalReceiver } from "../../engine-components/timeline/SignalAsset.js";
|
|
109
|
-
import {
|
|
110
|
-
import {
|
|
111
|
-
import {
|
|
104
|
+
import { TimelineAnimationTrack } from "../../engine-components/timeline/TimelineTracks.js";
|
|
105
|
+
import { TimelineAudioTrack } from "../../engine-components/timeline/TimelineTracks.js";
|
|
106
|
+
import { TimelineMarkerTrack } from "../../engine-components/timeline/TimelineTracks.js";
|
|
112
107
|
import { SignalTrackHandler } from "../../engine-components/timeline/TimelineTracks.js";
|
|
113
|
-
import {
|
|
108
|
+
import { TimelineActivationTrack } from "../../engine-components/timeline/TimelineTracks.js";
|
|
109
|
+
import { TimelineControlTrack } from "../../engine-components/timeline/TimelineTracks.js";
|
|
114
110
|
import { TransformGizmo } from "../../engine-components/TransformGizmo.js";
|
|
115
111
|
import { BaseUIComponent } from "../../engine-components/ui/BaseUIComponent.js";
|
|
116
112
|
import { UIRootComponent } from "../../engine-components/ui/BaseUIComponent.js";
|
|
@@ -167,11 +163,6 @@ export function initBuiltinTypes() {
|
|
|
167
163
|
TypeStore.add("Animator", Animator);
|
|
168
164
|
TypeStore.add("AudioListener", AudioListener);
|
|
169
165
|
TypeStore.add("AudioSource", AudioSource);
|
|
170
|
-
TypeStore.add("Avatar_Brain_LookAt", Avatar_Brain_LookAt);
|
|
171
|
-
TypeStore.add("Avatar_MouthShapes", Avatar_MouthShapes);
|
|
172
|
-
TypeStore.add("Avatar_MustacheShake", Avatar_MustacheShake);
|
|
173
|
-
TypeStore.add("AvatarBlink_Simple", AvatarBlink_Simple);
|
|
174
|
-
TypeStore.add("AvatarEyeLook_Rotation", AvatarEyeLook_Rotation);
|
|
175
166
|
TypeStore.add("AxesHelper", AxesHelper);
|
|
176
167
|
TypeStore.add("BasicIKConstraint", BasicIKConstraint);
|
|
177
168
|
TypeStore.add("BoxHelperComponent", BoxHelperComponent);
|
|
@@ -266,11 +257,12 @@ export function initBuiltinTypes() {
|
|
|
266
257
|
TypeStore.add("TestSimulateUserData", TestSimulateUserData);
|
|
267
258
|
TypeStore.add("PlayableDirector", PlayableDirector);
|
|
268
259
|
TypeStore.add("SignalReceiver", SignalReceiver);
|
|
269
|
-
TypeStore.add("
|
|
270
|
-
TypeStore.add("
|
|
271
|
-
TypeStore.add("
|
|
260
|
+
TypeStore.add("TimelineAnimationTrack", TimelineAnimationTrack);
|
|
261
|
+
TypeStore.add("TimelineAudioTrack", TimelineAudioTrack);
|
|
262
|
+
TypeStore.add("TimelineMarkerTrack", TimelineMarkerTrack);
|
|
272
263
|
TypeStore.add("SignalTrackHandler", SignalTrackHandler);
|
|
273
|
-
TypeStore.add("
|
|
264
|
+
TypeStore.add("TimelineActivationTrack", TimelineActivationTrack);
|
|
265
|
+
TypeStore.add("TimelineControlTrack", TimelineControlTrack);
|
|
274
266
|
TypeStore.add("TransformGizmo", TransformGizmo);
|
|
275
267
|
TypeStore.add("BaseUIComponent", BaseUIComponent);
|
|
276
268
|
TypeStore.add("UIRootComponent", UIRootComponent);
|
|
@@ -12,13 +12,16 @@ import { onError } from "./debug_overlay.js";
|
|
|
12
12
|
|
|
13
13
|
let _isActive = false;
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
/** @internal */
|
|
16
|
+
export function initSpatialConsole() {
|
|
17
|
+
// enable the spatial console if we receive an error while in dev session and in XR
|
|
18
|
+
onError((...args: any[]) => {
|
|
19
|
+
if (isDevEnvironment() && ContextRegistry.Current?.isInXR) {
|
|
20
|
+
enableSpatialConsole(true);
|
|
21
|
+
onLog("error", ...args);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
22
25
|
|
|
23
26
|
|
|
24
27
|
/** Enable a spatial debug console that follows the camera */
|
|
@@ -567,7 +567,6 @@ class AddressableSerializer extends TypeSerializer {
|
|
|
567
567
|
}
|
|
568
568
|
|
|
569
569
|
}
|
|
570
|
-
new AddressableSerializer();
|
|
571
570
|
|
|
572
571
|
|
|
573
572
|
|
|
@@ -703,7 +702,6 @@ export class ImageReferenceSerializer extends TypeSerializer {
|
|
|
703
702
|
return undefined;
|
|
704
703
|
}
|
|
705
704
|
}
|
|
706
|
-
new ImageReferenceSerializer();
|
|
707
705
|
|
|
708
706
|
|
|
709
707
|
|
|
@@ -772,4 +770,9 @@ export class FileReferenceSerializer extends TypeSerializer {
|
|
|
772
770
|
return undefined;
|
|
773
771
|
}
|
|
774
772
|
}
|
|
775
|
-
|
|
773
|
+
/** @internal */
|
|
774
|
+
export function initAddressableSerializers() {
|
|
775
|
+
new AddressableSerializer();
|
|
776
|
+
new ImageReferenceSerializer();
|
|
777
|
+
new FileReferenceSerializer();
|
|
778
|
+
}
|
|
@@ -21,4 +21,188 @@ export function ensureAudioContextIsResumed() {
|
|
|
21
21
|
}, 500);
|
|
22
22
|
});
|
|
23
23
|
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Represents an audio clip that can be loaded and played independently.
|
|
29
|
+
* The AudioClip class encapsulates the URL of the audio resource and provides
|
|
30
|
+
* methods for playback control (play, pause, stop) and querying duration.
|
|
31
|
+
*/
|
|
32
|
+
export class AudioClip {
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Creates a new AudioClip instance with the specified URL.
|
|
36
|
+
* @param url The URL of the audio resource to load. This can be a path to an audio file or a MediaStream URL.
|
|
37
|
+
*/
|
|
38
|
+
constructor(public readonly url: string) {
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Whether the clip is currently playing.
|
|
42
|
+
* @returns `true` if the clip is actively playing audio.
|
|
43
|
+
*/
|
|
44
|
+
get isPlaying(): boolean {
|
|
45
|
+
return this._audioElement !== undefined
|
|
46
|
+
&& !this._audioElement.paused
|
|
47
|
+
&& !this._audioElement.ended;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The total duration of the audio clip in seconds.
|
|
52
|
+
* Loads the audio metadata if not already available.
|
|
53
|
+
* @returns A promise that resolves with the duration in seconds.
|
|
54
|
+
*/
|
|
55
|
+
getDuration(): Promise<number> {
|
|
56
|
+
if (this._duration !== undefined) {
|
|
57
|
+
return Promise.resolve(this._duration);
|
|
58
|
+
}
|
|
59
|
+
return this.ensureAudioElement().then(audio => {
|
|
60
|
+
this._duration = audio.duration;
|
|
61
|
+
return audio.duration;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Plays the audio clip from the current position.
|
|
67
|
+
* @returns A promise that resolves when playback finishes, or rejects on error.
|
|
68
|
+
* If the clip is looping, the promise will never resolve on its own – call {@link stop} or {@link pause} to end playback.
|
|
69
|
+
*/
|
|
70
|
+
// #region Play
|
|
71
|
+
play(): Promise<void> {
|
|
72
|
+
return this.ensureAudioElement().then(audio => {
|
|
73
|
+
return new Promise<void>((resolve, reject) => {
|
|
74
|
+
const onEnded = () => {
|
|
75
|
+
cleanup();
|
|
76
|
+
resolve();
|
|
77
|
+
};
|
|
78
|
+
const onError = () => {
|
|
79
|
+
cleanup();
|
|
80
|
+
reject(new Error(`Playback error for ${this.url}`));
|
|
81
|
+
};
|
|
82
|
+
const onPause = () => {
|
|
83
|
+
// pause/stop also resolve the promise
|
|
84
|
+
cleanup();
|
|
85
|
+
resolve();
|
|
86
|
+
};
|
|
87
|
+
const cleanup = () => {
|
|
88
|
+
audio.removeEventListener("ended", onEnded);
|
|
89
|
+
audio.removeEventListener("error", onError);
|
|
90
|
+
audio.removeEventListener("pause", onPause);
|
|
91
|
+
};
|
|
92
|
+
audio.addEventListener("ended", onEnded);
|
|
93
|
+
audio.addEventListener("error", onError);
|
|
94
|
+
audio.addEventListener("pause", onPause);
|
|
95
|
+
audio.play().catch(err => {
|
|
96
|
+
cleanup();
|
|
97
|
+
reject(err);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Pauses playback at the current position.
|
|
105
|
+
* Call {@link play} to resume.
|
|
106
|
+
*/
|
|
107
|
+
// #region Pause/Stop
|
|
108
|
+
pause(): void {
|
|
109
|
+
this._audioElement?.pause();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Stops playback and resets the position to the beginning.
|
|
114
|
+
*/
|
|
115
|
+
stop(): void {
|
|
116
|
+
if (this._audioElement) {
|
|
117
|
+
this._audioElement.pause();
|
|
118
|
+
this._audioElement.currentTime = 0;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Whether the clip should loop when reaching the end. */
|
|
123
|
+
get loop(): boolean { return this._loop; }
|
|
124
|
+
set loop(value: boolean) {
|
|
125
|
+
this._loop = value;
|
|
126
|
+
if (this._audioElement) this._audioElement.loop = value;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Playback volume from 0 (silent) to 1 (full). */
|
|
130
|
+
get volume(): number { return this._volume; }
|
|
131
|
+
set volume(value: number) {
|
|
132
|
+
this._volume = value;
|
|
133
|
+
if (this._audioElement) this._audioElement.volume = value;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Current playback position in seconds. */
|
|
137
|
+
get currentTime(): number { return this._audioElement?.currentTime ?? 0; }
|
|
138
|
+
set currentTime(value: number) {
|
|
139
|
+
if (this._audioElement) this._audioElement.currentTime = value;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Normalized playback progress from 0 to 1.
|
|
143
|
+
* @returns The current playback position as a value between 0 and 1, or 0 if the duration is unknown.
|
|
144
|
+
*/
|
|
145
|
+
get progress(): number {
|
|
146
|
+
if (!this._audioElement || !this._duration) return 0;
|
|
147
|
+
return this._audioElement.currentTime / this._duration;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Seeks to a normalized position (0–1) in the clip.
|
|
152
|
+
* @param position A value between 0 (start) and 1 (end).
|
|
153
|
+
*/
|
|
154
|
+
// #region Seek
|
|
155
|
+
seek(position: number): void {
|
|
156
|
+
if (this._audioElement && this._duration) {
|
|
157
|
+
this._audioElement.currentTime = Math.max(0, Math.min(1, position)) * this._duration;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** The underlying HTMLAudioElement, or `undefined` if not yet created.
|
|
162
|
+
* Use this to connect the element to the Web Audio API via `createMediaElementSource()`.
|
|
163
|
+
* @returns The HTMLAudioElement if the clip has been loaded or played, otherwise `undefined`.
|
|
164
|
+
*/
|
|
165
|
+
get audioElement(): HTMLAudioElement | undefined { return this._audioElement; }
|
|
166
|
+
|
|
167
|
+
private _audioElement?: HTMLAudioElement;
|
|
168
|
+
private _duration?: number;
|
|
169
|
+
private _loadPromise?: Promise<HTMLAudioElement>;
|
|
170
|
+
private _loop: boolean = false;
|
|
171
|
+
private _volume: number = 1;
|
|
172
|
+
|
|
173
|
+
/** Lazily creates and loads the shared HTMLAudioElement. */
|
|
174
|
+
private ensureAudioElement(): Promise<HTMLAudioElement> {
|
|
175
|
+
if (this._audioElement && this._loadPromise) {
|
|
176
|
+
return this._loadPromise;
|
|
177
|
+
}
|
|
178
|
+
const audio = this._audioElement ?? new Audio(this.url);
|
|
179
|
+
this._audioElement = audio;
|
|
180
|
+
audio.loop = this._loop;
|
|
181
|
+
audio.volume = this._volume;
|
|
182
|
+
|
|
183
|
+
if (audio.readyState >= HTMLMediaElement.HAVE_METADATA) {
|
|
184
|
+
this._duration = audio.duration;
|
|
185
|
+
this._loadPromise = Promise.resolve(audio);
|
|
186
|
+
return this._loadPromise;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
this._loadPromise = new Promise<HTMLAudioElement>((resolve, reject) => {
|
|
190
|
+
const onLoaded = () => {
|
|
191
|
+
cleanup();
|
|
192
|
+
this._duration = audio.duration;
|
|
193
|
+
resolve(audio);
|
|
194
|
+
};
|
|
195
|
+
const onError = (e: Event) => {
|
|
196
|
+
cleanup();
|
|
197
|
+
reject(new Error(`Failed to load audio clip from ${this.url}: ${e}`));
|
|
198
|
+
};
|
|
199
|
+
const cleanup = () => {
|
|
200
|
+
audio.removeEventListener("loadedmetadata", onLoaded);
|
|
201
|
+
audio.removeEventListener("error", onError);
|
|
202
|
+
};
|
|
203
|
+
audio.addEventListener("loadedmetadata", onLoaded);
|
|
204
|
+
audio.addEventListener("error", onError);
|
|
205
|
+
});
|
|
206
|
+
return this._loadPromise;
|
|
207
|
+
}
|
|
24
208
|
}
|
|
@@ -257,12 +257,23 @@ export function fitCamera(options?: FitCameraOptions): null | FitCameraReturnTyp
|
|
|
257
257
|
else {
|
|
258
258
|
direction.sub(camera.worldPosition);
|
|
259
259
|
}
|
|
260
|
-
if (centerCamera === "y")
|
|
261
|
-
|
|
260
|
+
if (centerCamera === "y") {
|
|
261
|
+
// Preserve the camera's current elevation angle when it's already above the center,
|
|
262
|
+
// but clamp to a minimum elevation to prevent the camera from ending up at or below
|
|
263
|
+
// the scene center (which causes a "looking up from below" effect).
|
|
264
|
+
// direction points FROM camera TO center, so negative Y = camera is above center.
|
|
265
|
+
const horizontalLen = Math.sqrt(direction.x * direction.x + direction.z * direction.z);
|
|
266
|
+
if (horizontalLen > 0.0001) {
|
|
267
|
+
const minY = -horizontalLen * verticalOffset * 4;
|
|
268
|
+
if (direction.y > minY) direction.y = minY;
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
// Camera is directly above/below center — pick a default slight angle from +Z
|
|
272
|
+
direction.set(0, -verticalOffset * 4, 1);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
262
275
|
direction.normalize();
|
|
263
276
|
direction.multiplyScalar(distance);
|
|
264
|
-
if (centerCamera === "y")
|
|
265
|
-
direction.y += -verticalOffset * 4 * distance;
|
|
266
277
|
|
|
267
278
|
let cameraLocalPosition = center.clone().sub(direction);
|
|
268
279
|
if (options.cameraOffset) {
|
|
@@ -8,9 +8,9 @@ import { InstantiateIdProvider } from "./engine_networking_instantiate.js";
|
|
|
8
8
|
import { Context, registerComponent } from "./engine_setup.js";
|
|
9
9
|
import type { ComponentInit, Constructor, ConstructorConcrete, IComponent, IGameObject } from "./engine_types.js";
|
|
10
10
|
import { $componentName } from "./engine_types.js";
|
|
11
|
+
import { TypeStore } from "./engine_typestore.js";
|
|
11
12
|
import { getParam } from "./engine_utils.js";
|
|
12
13
|
import { apply } from "./js-extensions/index.js";
|
|
13
|
-
import { TypeStore } from "./engine_typestore.js";
|
|
14
14
|
|
|
15
15
|
const COMPONENT_GUID_NAMESPACE = 'eff8ba80-635d-11ec-90d6-0242ac120003';
|
|
16
16
|
|