@needle-tools/engine 4.3.0-alpha.1 → 4.3.0-alpha.3
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 +4 -0
- package/dist/needle-engine.bundle.js +5222 -5177
- package/dist/needle-engine.bundle.light.js +5226 -5181
- package/dist/needle-engine.bundle.light.min.js +121 -118
- package/dist/needle-engine.bundle.light.umd.cjs +128 -125
- package/dist/needle-engine.bundle.min.js +119 -116
- package/dist/needle-engine.bundle.umd.cjs +124 -121
- package/dist/needle-engine.d.ts +9 -9
- package/lib/engine/engine_context.js +1 -1
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.js +2 -4
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_serialization_core.js +1 -1
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.d.ts +6 -1
- package/lib/engine/xr/NeedleXRSession.js +6 -1
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine-components/AudioSource.js +1 -3
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/particlesystem/ParticleSystem.js +1 -1
- package/lib/engine-components/particlesystem/ParticleSystem.js.map +1 -1
- package/lib/engine-components/webxr/WebARSessionRoot.d.ts +8 -3
- package/lib/engine-components/webxr/WebARSessionRoot.js +30 -9
- package/lib/engine-components/webxr/WebARSessionRoot.js.map +1 -1
- package/lib/engine-components/webxr/WebXR.d.ts +25 -3
- package/lib/engine-components/webxr/WebXR.js +28 -3
- package/lib/engine-components/webxr/WebXR.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/engine_context.ts +1 -1
- package/src/engine/engine_mainloop_utils.ts +2 -4
- package/src/engine/engine_serialization_core.ts +1 -1
- package/src/engine/xr/NeedleXRSession.ts +7 -1
- package/src/engine-components/AudioSource.ts +1 -2
- package/src/engine-components/particlesystem/ParticleSystem.ts +2 -2
- package/src/engine-components/webxr/WebARSessionRoot.ts +31 -8
- package/src/engine-components/webxr/WebXR.ts +39 -12
|
@@ -49,18 +49,25 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
private static _hasPlaced: boolean = false;
|
|
53
|
+
/**
|
|
54
|
+
* @returns true if the scene has been placed in AR by the user or automatic placement
|
|
55
|
+
*/
|
|
56
|
+
static get hasPlaced(): boolean {
|
|
57
|
+
return this._hasPlaced;
|
|
58
|
+
}
|
|
59
|
+
|
|
52
60
|
|
|
53
|
-
/** The scale of
|
|
54
|
-
*
|
|
61
|
+
/** The scale of the user in AR.
|
|
62
|
+
* **NOTE**: a large value makes the scene appear smaller
|
|
55
63
|
* @default 1
|
|
56
64
|
*/
|
|
57
65
|
get arScale(): number {
|
|
58
66
|
return this._arScale;
|
|
59
67
|
}
|
|
60
68
|
set arScale(val: number) {
|
|
61
|
-
|
|
62
|
-
this.
|
|
63
|
-
this.onScaleChanged();
|
|
69
|
+
this._arScale = Math.max(0.000001, val);
|
|
70
|
+
this.onSetScale();
|
|
64
71
|
}
|
|
65
72
|
private _arScale: number = 1;
|
|
66
73
|
|
|
@@ -134,6 +141,7 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
134
141
|
if (debug) console.log("ENTER WEBXR: SessionRoot start...");
|
|
135
142
|
|
|
136
143
|
this._anchor = null;
|
|
144
|
+
WebARSessionRoot._hasPlaced = false;
|
|
137
145
|
|
|
138
146
|
// if (_args.xr.session.enabledFeatures?.includes("image-tracking")) {
|
|
139
147
|
// console.warn("Image tracking is enabled - will not place scene");
|
|
@@ -193,6 +201,7 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
193
201
|
this.onRevertSceneChanges();
|
|
194
202
|
// this._anchor?.delete();
|
|
195
203
|
this._anchor = null;
|
|
204
|
+
WebARSessionRoot._hasPlaced = false;
|
|
196
205
|
this._rigPlacementMatrix = undefined;
|
|
197
206
|
}
|
|
198
207
|
onUpdateXR(args: NeedleXREventArgs): void {
|
|
@@ -405,6 +414,7 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
405
414
|
reticle.quaternion.copy(reticle["lastQuat"]);
|
|
406
415
|
|
|
407
416
|
this.onApplyPose(reticle);
|
|
417
|
+
WebARSessionRoot._hasPlaced = true;
|
|
408
418
|
|
|
409
419
|
if (this.useXRAnchor) {
|
|
410
420
|
this.onCreateAnchor(NeedleXRSession.active!, hit);
|
|
@@ -417,8 +427,16 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
417
427
|
}
|
|
418
428
|
}
|
|
419
429
|
|
|
420
|
-
private
|
|
421
|
-
|
|
430
|
+
private onSetScale() {
|
|
431
|
+
if (!WebARSessionRoot._hasPlaced) return;
|
|
432
|
+
const rig = NeedleXRSession.active?.rig?.gameObject;
|
|
433
|
+
if (rig) {
|
|
434
|
+
const currentScale = NeedleXRSession.active?.rigScale || 1;
|
|
435
|
+
const newScale = (1 / this._arScale) * currentScale;
|
|
436
|
+
const scaleMatrix = new Matrix4().makeScale(newScale, newScale, newScale).invert();
|
|
437
|
+
rig.matrix.premultiply(scaleMatrix);
|
|
438
|
+
rig.matrix.decompose(rig.position, rig.quaternion, rig.scale);
|
|
439
|
+
}
|
|
422
440
|
}
|
|
423
441
|
|
|
424
442
|
private onRevertSceneChanges() {
|
|
@@ -516,7 +534,7 @@ export class WebARSessionRoot extends Behaviour {
|
|
|
516
534
|
console.warn("No rig object to place");
|
|
517
535
|
return;
|
|
518
536
|
}
|
|
519
|
-
const rigScale = NeedleXRSession.active?.rigScale || 1;
|
|
537
|
+
// const rigScale = NeedleXRSession.active?.rigScale || 1;
|
|
520
538
|
|
|
521
539
|
// save the previous rig parent
|
|
522
540
|
const previousParent = rigObject.parent || this.context.scene;
|
|
@@ -578,6 +596,10 @@ class WebXRSessionRootUserInput {
|
|
|
578
596
|
private _scale: number = 1;
|
|
579
597
|
private _hasChanged: boolean = false;
|
|
580
598
|
|
|
599
|
+
get scale() {
|
|
600
|
+
return this._scale;
|
|
601
|
+
}
|
|
602
|
+
|
|
581
603
|
// readonly translate: Vector3 = new Vector3();
|
|
582
604
|
// readonly rotation: Quaternion = new Quaternion();
|
|
583
605
|
// readonly scale: Vector3 = new Vector3(1, 1, 1);
|
|
@@ -594,6 +616,7 @@ class WebXRSessionRootUserInput {
|
|
|
594
616
|
reset() {
|
|
595
617
|
this._scale = 1;
|
|
596
618
|
this.offset.identity();
|
|
619
|
+
this._hasChanged = true;
|
|
597
620
|
}
|
|
598
621
|
get hasChanged() { return this._hasChanged; }
|
|
599
622
|
|
|
@@ -58,7 +58,7 @@ export class WebXR extends Behaviour {
|
|
|
58
58
|
|
|
59
59
|
// VR Settings
|
|
60
60
|
/**
|
|
61
|
-
* When enabled, default movement controls will be automatically added to the scene when entering VR.
|
|
61
|
+
* When enabled, default movement controls will be automatically added to the scene when entering VR.
|
|
62
62
|
* This includes teleportation and smooth locomotion options for VR controllers.
|
|
63
63
|
*/
|
|
64
64
|
@serializable()
|
|
@@ -96,14 +96,14 @@ export class WebXR extends Behaviour {
|
|
|
96
96
|
usePlacementAdjustment: boolean = true;
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
|
-
* Determines the scale of the user relative to the scene in AR. Larger values make the 3D content appear smaller.
|
|
99
|
+
* Determines the scale of the user relative to the scene in AR. Larger values make the 3D content appear smaller.
|
|
100
100
|
* Only applies when `usePlacementReticle` is enabled.
|
|
101
101
|
*/
|
|
102
102
|
@serializable()
|
|
103
103
|
arScale: number = 1;
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
|
-
* When enabled, an XRAnchor will be created for the AR scene and its position will be regularly updated to match the anchor.
|
|
106
|
+
* When enabled, an XRAnchor will be created for the AR scene and its position will be regularly updated to match the anchor.
|
|
107
107
|
* This can help with spatial persistence in AR experiences.
|
|
108
108
|
* @experimental
|
|
109
109
|
*/
|
|
@@ -118,21 +118,21 @@ export class WebXR extends Behaviour {
|
|
|
118
118
|
autoPlace: boolean = false;
|
|
119
119
|
|
|
120
120
|
/**
|
|
121
|
-
* When enabled, the AR session root center will be automatically adjusted to place the center of the scene.
|
|
121
|
+
* When enabled, the AR session root center will be automatically adjusted to place the center of the scene.
|
|
122
122
|
* This helps ensure the scene is properly aligned with detected surfaces.
|
|
123
123
|
*/
|
|
124
124
|
@serializable()
|
|
125
125
|
autoCenter: boolean = false;
|
|
126
126
|
|
|
127
127
|
/**
|
|
128
|
-
* When enabled, a USDZExporter component will be automatically added to the scene if none is found.
|
|
128
|
+
* When enabled, a USDZExporter component will be automatically added to the scene if none is found.
|
|
129
129
|
* This allows iOS and visionOS devices to view 3D content using Apple's AR QuickLook.
|
|
130
130
|
*/
|
|
131
131
|
@serializable()
|
|
132
132
|
useQuicklookExport: boolean = false;
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
|
-
* When enabled, the 'depth-sensing' WebXR feature will be requested to provide real-time depth occlusion.
|
|
135
|
+
* When enabled, the 'depth-sensing' WebXR feature will be requested to provide real-time depth occlusion.
|
|
136
136
|
* Currently only supported on Oculus Quest devices.
|
|
137
137
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/XRDepthInformation
|
|
138
138
|
* @experimental
|
|
@@ -141,7 +141,7 @@ export class WebXR extends Behaviour {
|
|
|
141
141
|
useDepthSensing: boolean = false;
|
|
142
142
|
|
|
143
143
|
/**
|
|
144
|
-
* When enabled, a {@link SpatialGrabRaycaster} will be added or enabled in the scene,
|
|
144
|
+
* When enabled, a {@link SpatialGrabRaycaster} will be added or enabled in the scene,
|
|
145
145
|
* allowing users to interact with objects at a distance in VR/AR.
|
|
146
146
|
* @default true
|
|
147
147
|
*/
|
|
@@ -149,7 +149,7 @@ export class WebXR extends Behaviour {
|
|
|
149
149
|
useSpatialGrab: boolean = true;
|
|
150
150
|
|
|
151
151
|
/**
|
|
152
|
-
* Specifies the avatar representation that will be created when entering a WebXR session.
|
|
152
|
+
* Specifies the avatar representation that will be created when entering a WebXR session.
|
|
153
153
|
* Can be a reference to a 3D model or a boolean to use the default avatar.
|
|
154
154
|
*/
|
|
155
155
|
@serializable(AssetReference)
|
|
@@ -166,6 +166,7 @@ export class WebXR extends Behaviour {
|
|
|
166
166
|
|
|
167
167
|
/**
|
|
168
168
|
* Initializes the WebXR component by obtaining the XR sync object for this context.
|
|
169
|
+
* @internal
|
|
169
170
|
*/
|
|
170
171
|
awake() {
|
|
171
172
|
NeedleXRSession.getXRSync(this.context);
|
|
@@ -174,6 +175,7 @@ export class WebXR extends Behaviour {
|
|
|
174
175
|
/**
|
|
175
176
|
* Sets up the WebXR component when it's enabled. Checks for HTTPS connection,
|
|
176
177
|
* sets up USDZ export if enabled, creates UI buttons, and configures avatar settings.
|
|
178
|
+
* @internal
|
|
177
179
|
*/
|
|
178
180
|
onEnable(): void {
|
|
179
181
|
// check if we're on a secure connection:
|
|
@@ -216,6 +218,7 @@ export class WebXR extends Behaviour {
|
|
|
216
218
|
/**
|
|
217
219
|
* Cleans up resources when the component is disabled.
|
|
218
220
|
* Destroys the USDZ exporter if one was created and removes UI buttons.
|
|
221
|
+
* @internal
|
|
219
222
|
*/
|
|
220
223
|
onDisable(): void {
|
|
221
224
|
this._usdzExporter?.destroy();
|
|
@@ -251,23 +254,40 @@ export class WebXR extends Behaviour {
|
|
|
251
254
|
get sessionMode(): XRSessionMode | null {
|
|
252
255
|
return NeedleXRSession.activeMode ?? null;;
|
|
253
256
|
}
|
|
257
|
+
/** While AR: this will return the currently active WebARSessionRoot component.
|
|
258
|
+
* You can also query this component in your scene with `findObjectOfType(WebARSessionRoot)`
|
|
259
|
+
*/
|
|
260
|
+
get arSessionRoot() {
|
|
261
|
+
return this._activeWebARSessionRoot;
|
|
262
|
+
}
|
|
254
263
|
|
|
255
|
-
/** Call to start an WebVR session
|
|
264
|
+
/** Call to start an WebVR session.
|
|
265
|
+
*
|
|
266
|
+
* This is a shorthand for `NeedleXRSession.start("immersive-vr", init, this.context)`
|
|
267
|
+
*/
|
|
256
268
|
async enterVR(init?: XRSessionInit): Promise<NeedleXRSession | null> {
|
|
257
269
|
return NeedleXRSession.start("immersive-vr", init, this.context);
|
|
258
270
|
}
|
|
259
|
-
/** Call to start an WebAR session
|
|
271
|
+
/** Call to start an WebAR session
|
|
272
|
+
*
|
|
273
|
+
* This is a shorthand for `NeedleXRSession.start("immersive-ar", init, this.context)`
|
|
274
|
+
*/
|
|
260
275
|
async enterAR(init?: XRSessionInit): Promise<NeedleXRSession | null> {
|
|
261
276
|
return NeedleXRSession.start("immersive-ar", init, this.context);
|
|
262
277
|
}
|
|
263
|
-
|
|
278
|
+
|
|
279
|
+
/** Call to end a WebXR (AR or VR) session.
|
|
280
|
+
*
|
|
281
|
+
* This is a shorthand for `NeedleXRSession.stop()`
|
|
282
|
+
*/
|
|
264
283
|
exitXR() {
|
|
265
284
|
NeedleXRSession.stop();
|
|
266
285
|
}
|
|
267
286
|
|
|
268
|
-
|
|
287
|
+
private _exitXRMenuButton?: HTMLElement;
|
|
269
288
|
private _previousXRState: number = 0;
|
|
270
289
|
private _spatialGrabRaycaster?: SpatialGrabRaycaster;
|
|
290
|
+
private _activeWebARSessionRoot: WebARSessionRoot | null = null;
|
|
271
291
|
|
|
272
292
|
private get isActiveWebXR() {
|
|
273
293
|
return !WebXR.activeWebXRComponent || WebXR.activeWebXRComponent === this;
|
|
@@ -277,6 +297,7 @@ export class WebXR extends Behaviour {
|
|
|
277
297
|
* Called before entering a WebXR session. Sets up optional features like depth sensing, if needed.
|
|
278
298
|
* @param _mode The XR session mode being requested (immersive-ar or immersive-vr)
|
|
279
299
|
* @param args The XRSessionInit object that will be passed to the WebXR API
|
|
300
|
+
* @internal
|
|
280
301
|
*/
|
|
281
302
|
onBeforeXR(_mode: XRSessionMode, args: XRSessionInit): void {
|
|
282
303
|
if (!this.isActiveWebXR) {
|
|
@@ -295,6 +316,7 @@ export class WebXR extends Behaviour {
|
|
|
295
316
|
* Called when a WebXR session begins. Sets up the scene for XR by configuring controllers,
|
|
296
317
|
* AR placement, and other features based on component settings.
|
|
297
318
|
* @param args Event arguments containing information about the started XR session
|
|
319
|
+
* @internal
|
|
298
320
|
*/
|
|
299
321
|
async onEnterXR(args: NeedleXREventArgs) {
|
|
300
322
|
if (!this.isActiveWebXR) return;
|
|
@@ -323,6 +345,7 @@ export class WebXR extends Behaviour {
|
|
|
323
345
|
}
|
|
324
346
|
}
|
|
325
347
|
|
|
348
|
+
this._activeWebARSessionRoot = sessionroot;
|
|
326
349
|
if (sessionroot) {
|
|
327
350
|
// sessionroot.enabled = this.usePlacementReticle; // < not sure if we want to disable the session root when placement reticle if OFF...
|
|
328
351
|
sessionroot.customReticle = this.customARPlacementReticle;
|
|
@@ -371,6 +394,7 @@ export class WebXR extends Behaviour {
|
|
|
371
394
|
* Called every frame during an active WebXR session.
|
|
372
395
|
* Updates components that depend on the current XR state.
|
|
373
396
|
* @param _args Event arguments containing information about the current XR session frame
|
|
397
|
+
* @internal
|
|
374
398
|
*/
|
|
375
399
|
onUpdateXR(_args: NeedleXREventArgs): void {
|
|
376
400
|
if (!this.isActiveWebXR) return;
|
|
@@ -383,6 +407,7 @@ export class WebXR extends Behaviour {
|
|
|
383
407
|
* Called when a WebXR session ends. Restores pre-session state,
|
|
384
408
|
* removes temporary components, and cleans up resources.
|
|
385
409
|
* @param _ Event arguments containing information about the ended XR session
|
|
410
|
+
* @internal
|
|
386
411
|
*/
|
|
387
412
|
onLeaveXR(_: NeedleXREventArgs): void {
|
|
388
413
|
this._exitXRMenuButton?.remove();
|
|
@@ -399,6 +424,8 @@ export class WebXR extends Behaviour {
|
|
|
399
424
|
}
|
|
400
425
|
this._createdComponentsInSession.length = 0;
|
|
401
426
|
|
|
427
|
+
this._activeWebARSessionRoot = null;
|
|
428
|
+
|
|
402
429
|
this.handleOfferSession();
|
|
403
430
|
|
|
404
431
|
delayForFrames(1).then(() => WebXR.activeWebXRComponent = null);
|