@needle-tools/engine 4.4.0-ci.1 → 4.4.2
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 +67 -0
- package/dist/assets/generateMeshBVH.worker-b7788939.js +25 -0
- package/dist/needle-engine.bundle.js +7043 -6766
- package/dist/needle-engine.bundle.light.js +7205 -6928
- package/dist/needle-engine.bundle.light.min.js +169 -139
- package/dist/needle-engine.bundle.light.umd.cjs +173 -143
- package/dist/needle-engine.bundle.min.js +169 -139
- package/dist/needle-engine.bundle.umd.cjs +172 -142
- package/dist/needle-engine.js +468 -467
- package/dist/needle-engine.light.js +468 -467
- package/dist/needle-engine.light.min.js +1 -1
- package/dist/needle-engine.light.umd.cjs +1 -1
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/vendor.js +5108 -5122
- package/dist/vendor.light.js +5108 -5122
- package/dist/vendor.light.min.js +84 -84
- package/dist/vendor.light.umd.cjs +78 -78
- package/dist/vendor.min.js +84 -84
- package/dist/vendor.umd.cjs +78 -78
- package/lib/engine/codegen/register_types.js +2 -0
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_components.js +3 -1
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_context.d.ts +141 -14
- package/lib/engine/engine_context.js +164 -26
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_element.js +12 -10
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_gameobject.js +5 -0
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_license.d.ts +2 -0
- package/lib/engine/engine_license.js +103 -62
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_networking_blob.js +40 -24
- package/lib/engine/engine_networking_blob.js.map +1 -1
- package/lib/engine/engine_physics_rapier.js +10 -9
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_serialization_core.js +6 -2
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_utils_screenshot.js +1 -1
- package/lib/engine/engine_utils_screenshot.js.map +1 -1
- package/lib/engine/js-extensions/RGBAColor.d.ts +1 -0
- package/lib/engine/js-extensions/RGBAColor.js +56 -7
- package/lib/engine/js-extensions/RGBAColor.js.map +1 -1
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +4 -3
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +6 -6
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +4 -0
- package/lib/engine/webcomponents/needle menu/needle-menu.js +13 -2
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/xr/NeedleXRController.js +2 -3
- package/lib/engine/xr/NeedleXRController.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.js +12 -12
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine-components/AudioSource.js +7 -0
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/Camera.js +18 -12
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/CameraUtils.js +8 -14
- package/lib/engine-components/CameraUtils.js.map +1 -1
- package/lib/engine-components/GroundProjection.js +1 -1
- package/lib/engine-components/GroundProjection.js.map +1 -1
- package/lib/engine-components/NeedleMenu.js +1 -1
- package/lib/engine-components/NeedleMenu.js.map +1 -1
- package/lib/engine-components/OrbitControls.js +3 -1
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.d.ts +1 -0
- package/lib/engine-components/ReflectionProbe.js +16 -9
- package/lib/engine-components/ReflectionProbe.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.js +28 -7
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/SyncedTransform.d.ts +6 -0
- package/lib/engine-components/SyncedTransform.js +10 -5
- package/lib/engine-components/SyncedTransform.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +1 -0
- package/lib/engine-components/codegen/components.js +1 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/USDZUI.js +2 -1
- package/lib/engine-components/export/usdz/extensions/USDZUI.js.map +1 -1
- package/lib/engine-components/ui/BaseUIComponent.d.ts +0 -1
- package/lib/engine-components/ui/BaseUIComponent.js +1 -1
- package/lib/engine-components/ui/BaseUIComponent.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.js +1 -1
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/lib/engine-components/ui/Graphic.js +1 -0
- package/lib/engine-components/ui/Graphic.js.map +1 -1
- package/lib/engine-components/ui/RaycastUtils.js +1 -1
- package/lib/engine-components/ui/RaycastUtils.js.map +1 -1
- package/lib/engine-components/ui/RectTransform.d.ts +2 -2
- package/lib/engine-components/ui/RectTransform.js +9 -6
- package/lib/engine-components/ui/RectTransform.js.map +1 -1
- package/lib/engine-components/ui/Symbols.d.ts +1 -0
- package/lib/engine-components/ui/Symbols.js +2 -0
- package/lib/engine-components/ui/Symbols.js.map +1 -0
- package/lib/engine-components/ui/Utils.js +1 -1
- package/lib/engine-components/ui/Utils.js.map +1 -1
- package/lib/engine-components/utils/EnvironmentScene.d.ts +1 -1
- package/lib/engine-components/utils/EnvironmentScene.js +1 -1
- package/lib/engine-components/utils/EnvironmentScene.js.map +1 -1
- package/package.json +3 -3
- package/plugins/common/license.js +115 -27
- package/plugins/types/userconfig.d.ts +8 -0
- package/plugins/vite/build-pipeline.js +1 -1
- package/plugins/vite/defines.js +3 -1
- package/plugins/vite/dependencies.js +23 -4
- package/plugins/vite/facebook-instant-games.js +7 -4
- package/plugins/vite/index.js +1 -1
- package/plugins/vite/license.js +2 -1
- package/src/engine/codegen/register_types.ts +2 -0
- package/src/engine/engine_addressables.ts +3 -2
- package/src/engine/engine_components.ts +2 -1
- package/src/engine/engine_context.ts +169 -33
- package/src/engine/engine_element.ts +10 -9
- package/src/engine/engine_gameobject.ts +7 -0
- package/src/engine/engine_license.ts +116 -67
- package/src/engine/engine_networking_blob.ts +47 -26
- package/src/engine/engine_physics_rapier.ts +10 -12
- package/src/engine/engine_serialization_core.ts +6 -1
- package/src/engine/engine_utils_screenshot.ts +1 -1
- package/src/engine/js-extensions/RGBAColor.ts +59 -8
- package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +6 -6
- package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +6 -6
- package/src/engine/webcomponents/needle menu/needle-menu.ts +13 -2
- package/src/engine/xr/NeedleXRController.ts +2 -3
- package/src/engine/xr/NeedleXRSession.ts +12 -12
- package/src/engine-components/AudioSource.ts +8 -3
- package/src/engine-components/Camera.ts +34 -22
- package/src/engine-components/CameraUtils.ts +8 -16
- package/src/engine-components/GroundProjection.ts +1 -1
- package/src/engine-components/NeedleMenu.ts +1 -1
- package/src/engine-components/OrbitControls.ts +2 -1
- package/src/engine-components/ReflectionProbe.ts +15 -8
- package/src/engine-components/SceneSwitcher.ts +28 -11
- package/src/engine-components/SyncedTransform.ts +11 -6
- package/src/engine-components/codegen/components.ts +1 -0
- package/src/engine-components/export/usdz/extensions/USDZUI.ts +2 -2
- package/src/engine-components/ui/BaseUIComponent.ts +1 -1
- package/src/engine-components/ui/EventSystem.ts +1 -1
- package/src/engine-components/ui/Graphic.ts +1 -1
- package/src/engine-components/ui/RaycastUtils.ts +1 -1
- package/src/engine-components/ui/RectTransform.ts +10 -7
- package/src/engine-components/ui/Symbols.ts +2 -0
- package/src/engine-components/ui/Utils.ts +2 -1
- package/src/engine-components/utils/EnvironmentScene.ts +1 -1
|
@@ -278,26 +278,43 @@ export class Context implements IContext {
|
|
|
278
278
|
if (this.isInAR) return window.innerHeight;
|
|
279
279
|
return this.domElement.clientHeight;
|
|
280
280
|
}
|
|
281
|
-
/** the X position of the
|
|
281
|
+
/** the X position of the `<needle-engine>` element on the website */
|
|
282
282
|
get domX(): number {
|
|
283
283
|
this.calculateBoundingClientRect();
|
|
284
284
|
return this._domX;
|
|
285
285
|
}
|
|
286
|
-
/** the Y position of the
|
|
286
|
+
/** the Y position of the `<needle-engine>` element on the website */
|
|
287
287
|
get domY(): number {
|
|
288
288
|
this.calculateBoundingClientRect();
|
|
289
289
|
return this._domY;
|
|
290
290
|
}
|
|
291
|
+
/**
|
|
292
|
+
* Is a XR session currently active and presenting?
|
|
293
|
+
* @returns true if the xr renderer is currently presenting
|
|
294
|
+
*/
|
|
291
295
|
get isInXR() { return this.renderer?.xr?.isPresenting || false; }
|
|
292
296
|
/** shorthand for `NeedleXRSession.active`
|
|
293
297
|
* Automatically set by NeedleXRSession when a XR session is active
|
|
294
298
|
* @returns the active XR session or null if no session is active
|
|
295
299
|
* */
|
|
296
300
|
xr: NeedleXRSession | null = null;
|
|
301
|
+
/**
|
|
302
|
+
* Shorthand for `this.xr?.mode`. AR or VR
|
|
303
|
+
* @returns the current XR session mode (immersive-vr or immersive-ar)
|
|
304
|
+
*/
|
|
297
305
|
get xrSessionMode() { return this.xr?.mode; }
|
|
306
|
+
/** Shorthand for `this.xrSessionMode === "immersive-vr"`
|
|
307
|
+
* @returns true if a webxr VR session is currently active.
|
|
308
|
+
*/
|
|
298
309
|
get isInVR() { return this.xrSessionMode === "immersive-vr"; }
|
|
310
|
+
/**
|
|
311
|
+
* Shorthand for `this.xrSessionMode === "immersive-ar"`
|
|
312
|
+
* @returns true if a webxr AR session is currently active.
|
|
313
|
+
*/
|
|
299
314
|
get isInAR() { return this.xrSessionMode === "immersive-ar"; }
|
|
300
|
-
/** If a XR session is active and in pass through mode (immersive-ar on e.g. Quest)
|
|
315
|
+
/** If a XR session is active and in pass through mode (immersive-ar on e.g. Quest)
|
|
316
|
+
* @returns true if the XR session is in pass through mode
|
|
317
|
+
*/
|
|
301
318
|
get isInPassThrough() { return this.xr ? this.xr.isPassThrough : false; }
|
|
302
319
|
/** access the raw `XRSession` object (shorthand for `context.renderer.xr.getSession()`). For more control use `NeedleXRSession.active` */
|
|
303
320
|
get xrSession() { return this.renderer?.xr?.getSession(); }
|
|
@@ -308,34 +325,79 @@ export class Context implements IContext {
|
|
|
308
325
|
/** @returns the current WebXR camera while the WebXRManager is active (shorthand for `context.renderer.xr.getCamera()`) */
|
|
309
326
|
get xrCamera(): WebXRArrayCamera | undefined { return this.renderer.xr.isPresenting ? this.renderer?.xr?.getCamera() : undefined }
|
|
310
327
|
private _xrFrame: XRFrame | null = null;
|
|
328
|
+
/**
|
|
329
|
+
* The AR overlay element is used to display 2D HTML elements while a AR session is active.
|
|
330
|
+
*/
|
|
311
331
|
get arOverlayElement(): HTMLElement {
|
|
312
332
|
const el = this.domElement as any;
|
|
313
333
|
if (typeof el.getAROverlayContainer === "function")
|
|
314
334
|
return el.getAROverlayContainer();
|
|
315
335
|
return this.domElement;
|
|
316
336
|
}
|
|
317
|
-
/**
|
|
337
|
+
/**
|
|
338
|
+
* Current event of the update cycle (e.g. `FrameEvent.EarlyUpdate` or `FrameEvent.OnBeforeRender`)
|
|
339
|
+
*/
|
|
318
340
|
get currentFrameEvent(): FrameEvent {
|
|
319
341
|
return this._currentFrameEvent;
|
|
320
342
|
}
|
|
321
343
|
private _currentFrameEvent: FrameEvent = FrameEvent.Undefined;
|
|
322
344
|
|
|
345
|
+
/**
|
|
346
|
+
* The scene contains all objects in the hierarchy and is automatically rendered by the context every frane.
|
|
347
|
+
*/
|
|
323
348
|
scene: Scene;
|
|
349
|
+
/**
|
|
350
|
+
* The renderer is used to render the scene. It is automatically created when the context is created.
|
|
351
|
+
*/
|
|
324
352
|
renderer!: WebGLRenderer;
|
|
353
|
+
/**
|
|
354
|
+
* The effect composer can be used to render postprocessing effects. If assigned then it will automatically render the scene every frame.
|
|
355
|
+
*/
|
|
325
356
|
composer: EffectComposer | ThreeEffectComposer | null = null;
|
|
326
357
|
|
|
327
|
-
|
|
358
|
+
/**
|
|
359
|
+
* @internal All known components. Don't use directly
|
|
360
|
+
*/
|
|
328
361
|
readonly scripts: IComponent[] = [];
|
|
362
|
+
/**
|
|
363
|
+
* @internal All paused components. Don't use directly
|
|
364
|
+
*/
|
|
329
365
|
readonly scripts_pausedChanged: IComponent[] = [];
|
|
330
|
-
|
|
366
|
+
/**
|
|
367
|
+
* @internal All components that have a early update event. Don't use directly
|
|
368
|
+
*/
|
|
331
369
|
readonly scripts_earlyUpdate: IComponent[] = [];
|
|
370
|
+
/**
|
|
371
|
+
* @internal All components that have a update event. Don't use directly
|
|
372
|
+
*/
|
|
332
373
|
readonly scripts_update: IComponent[] = [];
|
|
374
|
+
/**
|
|
375
|
+
* @internal All components that have a late update event. Don't use directly
|
|
376
|
+
*/
|
|
333
377
|
readonly scripts_lateUpdate: IComponent[] = [];
|
|
378
|
+
/**
|
|
379
|
+
* @internal All components that have a onBeforeRender event. Don't use directly
|
|
380
|
+
*/
|
|
334
381
|
readonly scripts_onBeforeRender: IComponent[] = [];
|
|
382
|
+
/**
|
|
383
|
+
* @internal All components that have a onAfterRender event. Don't use directly
|
|
384
|
+
*/
|
|
335
385
|
readonly scripts_onAfterRender: IComponent[] = [];
|
|
386
|
+
/**
|
|
387
|
+
* @internal All components that have coroutines. Don't use directly
|
|
388
|
+
*/
|
|
336
389
|
readonly scripts_WithCorroutines: IComponent[] = [];
|
|
390
|
+
/**
|
|
391
|
+
* @internal Components with immersive-vr event methods. Don't use directly
|
|
392
|
+
*/
|
|
337
393
|
readonly scripts_immersive_vr: INeedleXRSessionEventReceiver[] = [];
|
|
394
|
+
/**
|
|
395
|
+
* @internal Components with immersive-ar event methods. Don't use directly
|
|
396
|
+
*/
|
|
338
397
|
readonly scripts_immersive_ar: INeedleXRSessionEventReceiver[] = [];
|
|
398
|
+
/**
|
|
399
|
+
* @internal Coroutine data
|
|
400
|
+
*/
|
|
339
401
|
readonly coroutines: { [FrameEvent: number]: Array<CoroutineData> } = {}
|
|
340
402
|
|
|
341
403
|
/** callbacks called once after the context has been created */
|
|
@@ -346,20 +408,30 @@ export class Context implements IContext {
|
|
|
346
408
|
readonly pre_render_callbacks: Array<(frame: XRFrame | null) => void> = [];
|
|
347
409
|
/** called every frame after rendering (after all component events) */
|
|
348
410
|
readonly post_render_callbacks: Function[] = [];
|
|
349
|
-
|
|
350
411
|
/** called every frame befroe update (this list is emptied every frame) */
|
|
351
412
|
readonly pre_update_oneshot_callbacks: Function[] = [];
|
|
352
413
|
|
|
414
|
+
/** @internal */
|
|
353
415
|
readonly new_scripts: IComponent[] = [];
|
|
416
|
+
/** @internal */
|
|
354
417
|
readonly new_script_start: IComponent[] = [];
|
|
418
|
+
/** @internal */
|
|
355
419
|
readonly new_scripts_pre_setup_callbacks: Function[] = [];
|
|
420
|
+
/** @internal */
|
|
356
421
|
readonly new_scripts_post_setup_callbacks: Function[] = [];
|
|
422
|
+
/** @internal */
|
|
357
423
|
readonly new_scripts_xr: INeedleXRSessionEventReceiver[] = [];
|
|
358
424
|
|
|
359
|
-
/**
|
|
425
|
+
/**
|
|
426
|
+
* The **main camera component** of the scene - this camera is used for rendering.
|
|
427
|
+
* Use `setCurrentCamera` for updating the main camera.
|
|
428
|
+
*/
|
|
360
429
|
mainCameraComponent: ICamera | undefined = undefined;
|
|
361
430
|
|
|
362
|
-
/**
|
|
431
|
+
/**
|
|
432
|
+
* The main camera of the scene - this camera is used for rendering
|
|
433
|
+
* Use `setCurrentCamera` for updating the main camera.
|
|
434
|
+
*/
|
|
363
435
|
get mainCamera(): Camera {
|
|
364
436
|
if (this._mainCamera) {
|
|
365
437
|
return this._mainCamera;
|
|
@@ -382,11 +454,13 @@ export class Context implements IContext {
|
|
|
382
454
|
private _mainCamera: Camera | null = null;
|
|
383
455
|
private _fallbackCamera: PerspectiveCamera | null = null;
|
|
384
456
|
|
|
457
|
+
/** access application state (e.g. if all audio should be muted) */
|
|
385
458
|
application: Application;
|
|
386
459
|
/** access animation mixer used by components in the scene */
|
|
387
460
|
animations: AnimationsRegistry;
|
|
388
461
|
/** access timings (current frame number, deltaTime, timeScale, ...) */
|
|
389
462
|
time: Time;
|
|
463
|
+
/** access input data (e.g. click or touch events) */
|
|
390
464
|
input: Input;
|
|
391
465
|
/** access physics related methods (e.g. raycasting). To access the phyiscs engine use `context.physics.engine` */
|
|
392
466
|
physics: Physics;
|
|
@@ -396,6 +470,7 @@ export class Context implements IContext {
|
|
|
396
470
|
* @deprecated AssetDataBase is deprecated
|
|
397
471
|
*/
|
|
398
472
|
assets: AssetDatabase;
|
|
473
|
+
/** The main light in the scene */
|
|
399
474
|
mainLight: ILight | null = null;
|
|
400
475
|
/** @deprecated Use sceneLighting */
|
|
401
476
|
get rendererData() { return this.sceneLighting }
|
|
@@ -404,11 +479,13 @@ export class Context implements IContext {
|
|
|
404
479
|
lightmaps: ILightDataRegistry;
|
|
405
480
|
players: PlayerViewManager;
|
|
406
481
|
readonly lodsManager: LODsManager;
|
|
482
|
+
/** Access the needle menu to add or remove buttons to the menu element */
|
|
407
483
|
readonly menu: NeedleMenu;
|
|
408
484
|
|
|
485
|
+
/** @returns true if the context is fully created and ready */
|
|
409
486
|
get isCreated() { return this._isCreated; }
|
|
410
487
|
|
|
411
|
-
private
|
|
488
|
+
private _needsUpdateSize: boolean = false;
|
|
412
489
|
private _isCreated: boolean = false;
|
|
413
490
|
private _isCreating: boolean = false;
|
|
414
491
|
private _isVisible: boolean = false;
|
|
@@ -446,11 +523,11 @@ export class Context implements IContext {
|
|
|
446
523
|
this.animations = new AnimationsRegistry(this);
|
|
447
524
|
|
|
448
525
|
|
|
449
|
-
const resizeCallback = () => this.
|
|
526
|
+
const resizeCallback = () => this._needsUpdateSize = true;
|
|
450
527
|
window.addEventListener('resize', resizeCallback);
|
|
451
528
|
this._disposeCallbacks.push(() => window.removeEventListener('resize', resizeCallback));
|
|
452
529
|
|
|
453
|
-
const resizeObserver = new ResizeObserver(_ => this.
|
|
530
|
+
const resizeObserver = new ResizeObserver(_ => this._needsUpdateSize = true);
|
|
454
531
|
resizeObserver.observe(this.domElement);
|
|
455
532
|
this._disposeCallbacks.push(() => resizeObserver.disconnect());
|
|
456
533
|
|
|
@@ -462,7 +539,12 @@ export class Context implements IContext {
|
|
|
462
539
|
ContextRegistry.register(this);
|
|
463
540
|
}
|
|
464
541
|
|
|
465
|
-
/**
|
|
542
|
+
/**
|
|
543
|
+
* Calling this function will dispose the current renderer and create a new one which will then be assigned to the context. It can be used to create a new renderer with custom WebGLRendererParameters.
|
|
544
|
+
* **Note**: Instead you can also modify the static `Context.DefaultWebGlRendererParameters` before the context is created.
|
|
545
|
+
* **Note**: This method is recommended because it re-uses an potentially already existing canvas element. This is necessary to keep input event handlers from working (e.g. components like OrbitControls subscribe to input events on the canvas)
|
|
546
|
+
* @returns {WebGLRenderer} the newly created renderer
|
|
547
|
+
*/
|
|
466
548
|
createNewRenderer(params?: WebGLRendererParameters) {
|
|
467
549
|
this.renderer?.dispose();
|
|
468
550
|
|
|
@@ -506,6 +588,8 @@ export class Context implements IContext {
|
|
|
506
588
|
this.lodsManager.setRenderer(this.renderer);
|
|
507
589
|
|
|
508
590
|
this.input.bindEvents();
|
|
591
|
+
|
|
592
|
+
return this.renderer;
|
|
509
593
|
}
|
|
510
594
|
|
|
511
595
|
|
|
@@ -519,15 +603,32 @@ export class Context implements IContext {
|
|
|
519
603
|
|
|
520
604
|
|
|
521
605
|
/** will request a renderer size update the next render call (will call updateSize the next update) */
|
|
522
|
-
requestSizeUpdate() { this.
|
|
606
|
+
requestSizeUpdate() { this._needsUpdateSize = true; }
|
|
523
607
|
|
|
524
608
|
/** Clamps the renderer max resolution. If undefined the max resolution is not clamped. Default is undefined */
|
|
525
609
|
maxRenderResolution?: Vec2;
|
|
526
610
|
|
|
527
|
-
/**
|
|
611
|
+
/** Control the renderer devicePixelRatio.
|
|
612
|
+
* **Options**
|
|
613
|
+
* - `auto` - Needle Engine automatically sets the pixel ratio to the current window.devicePixelRatio.
|
|
614
|
+
* - `manual` - Needle Engine will not change the renderer pixel ratio. You can set it manually.
|
|
615
|
+
* - `number` - Needle Engine will set the pixel ratio to the given number. The change will be applied to the renderer and the composer (if used) at the end of the current frame.
|
|
616
|
+
*/
|
|
617
|
+
get devicePixelRatio() { return this._devicePixelRatio; }
|
|
618
|
+
set devicePixelRatio(val: "auto" | "manual" | number) {
|
|
619
|
+
if (val !== this._devicePixelRatio) {
|
|
620
|
+
this._devicePixelRatio = val;
|
|
621
|
+
this._needsUpdateSize = true;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
private _devicePixelRatio: "auto" | "manual" | number = "auto";
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Update the renderer and canvas size. This is also automatically called when a DOM size change is detected.
|
|
628
|
+
*/
|
|
528
629
|
updateSize(force: boolean = false) {
|
|
529
630
|
if (force || (!this.isManagedExternally && this.renderer.xr?.isPresenting === false)) {
|
|
530
|
-
this.
|
|
631
|
+
this._needsUpdateSize = false;
|
|
531
632
|
const scaleFactor = this.resolutionScaleFactor;
|
|
532
633
|
let width = this.domWidth * scaleFactor;
|
|
533
634
|
let height = this.domHeight * scaleFactor;
|
|
@@ -540,20 +641,32 @@ export class Context implements IContext {
|
|
|
540
641
|
const camera = this.mainCamera as PerspectiveCamera;
|
|
541
642
|
this.updateAspect(camera);
|
|
542
643
|
this.renderer.setSize(width, height, true);
|
|
543
|
-
this.renderer.setPixelRatio(window.devicePixelRatio);
|
|
544
644
|
// avoid setting pixel values here since this can cause pingpong updates
|
|
545
645
|
// e.g. when system scale is set to 125%
|
|
546
646
|
// https://github.com/needle-tools/needle-engine-support/issues/69
|
|
547
647
|
this.renderer.domElement.style.width = "100%";
|
|
548
648
|
this.renderer.domElement.style.height = "100%";
|
|
649
|
+
|
|
650
|
+
const devicePixelRatio = typeof this.devicePixelRatio === "number"
|
|
651
|
+
? this.devicePixelRatio
|
|
652
|
+
: this.devicePixelRatio === "auto"
|
|
653
|
+
? window.devicePixelRatio
|
|
654
|
+
: undefined;
|
|
655
|
+
if (devicePixelRatio !== undefined) {
|
|
656
|
+
this.renderer.setPixelRatio(devicePixelRatio);
|
|
657
|
+
}
|
|
658
|
+
|
|
549
659
|
if (this.composer) {
|
|
550
660
|
this.composer.setSize?.call(this.composer, width, height);
|
|
551
|
-
if ("setPixelRatio" in this.composer && typeof this.composer.setPixelRatio === "function")
|
|
661
|
+
if (devicePixelRatio !== undefined && "setPixelRatio" in this.composer && typeof this.composer.setPixelRatio === "function")
|
|
552
662
|
this.composer.setPixelRatio?.call(this.composer, window.devicePixelRatio);
|
|
553
663
|
}
|
|
554
664
|
}
|
|
555
665
|
}
|
|
556
666
|
|
|
667
|
+
/**
|
|
668
|
+
* Update the camera aspect ratio or orthorgraphic camera size. This is automatically called when a DOM size change is detected.
|
|
669
|
+
*/
|
|
557
670
|
updateAspect(camera: PerspectiveCamera | OrthographicCamera, width?: number, height?: number) {
|
|
558
671
|
if (!camera) return;
|
|
559
672
|
if (width === undefined)
|
|
@@ -601,6 +714,7 @@ export class Context implements IContext {
|
|
|
601
714
|
async onCreate(opts?: ContextCreateArgs) {
|
|
602
715
|
return this.create(opts);
|
|
603
716
|
}
|
|
717
|
+
/** @internal */
|
|
604
718
|
async create(opts?: ContextCreateArgs) {
|
|
605
719
|
try {
|
|
606
720
|
this._isCreating = true;
|
|
@@ -626,7 +740,11 @@ export class Context implements IContext {
|
|
|
626
740
|
this.domElement.dispatchEvent(new CustomEvent("error", { detail: error }));
|
|
627
741
|
}
|
|
628
742
|
|
|
629
|
-
/**
|
|
743
|
+
/**
|
|
744
|
+
* Clears the context and destroys all scenes and objects in the scene.
|
|
745
|
+
* The ContextCleared event is called at the end.
|
|
746
|
+
* This is automatically called when e.g. the `src` attribute changes on `<needle-engine>`
|
|
747
|
+
* or when the web component is removed from the DOM
|
|
630
748
|
*/
|
|
631
749
|
clear() {
|
|
632
750
|
ContextRegistry.dispatchCallback(ContextEvent.ContextClearing, this);
|
|
@@ -652,12 +770,16 @@ export class Context implements IContext {
|
|
|
652
770
|
ContextRegistry.dispatchCallback(ContextEvent.ContextCleared, this);
|
|
653
771
|
}
|
|
654
772
|
|
|
773
|
+
/**
|
|
774
|
+
* Dispose all allocated resources and clears the scene. This is automatically called e.g. when the `<needle-engine>` component is removed from the DOM.
|
|
775
|
+
*/
|
|
655
776
|
dispose() {
|
|
656
777
|
this.internalOnDestroy();
|
|
657
778
|
}
|
|
658
779
|
|
|
659
780
|
/**@deprecated use dispose() */
|
|
660
781
|
onDestroy() { this.internalOnDestroy(); }
|
|
782
|
+
|
|
661
783
|
private internalOnDestroy() {
|
|
662
784
|
Context.Current = this;
|
|
663
785
|
ContextRegistry.dispatchCallback(ContextEvent.ContextDestroying, this);
|
|
@@ -698,6 +820,7 @@ export class Context implements IContext {
|
|
|
698
820
|
}
|
|
699
821
|
}
|
|
700
822
|
|
|
823
|
+
/** @internal Automatically called by components when you call `startCoroutine`. Use `startCoroutine` instead */
|
|
701
824
|
registerCoroutineUpdate(script: IComponent, coroutine: Generator, evt: FrameEvent): Generator {
|
|
702
825
|
if (typeof coroutine?.next !== "function") {
|
|
703
826
|
console.error("Registered invalid coroutine function from " + script.name + "\nCoroutine functions must be generators: \"*myCoroutine() {...}\"\nStart a coroutine from a component by calling \"this.startCoroutine(myCoroutine())\"")
|
|
@@ -708,12 +831,14 @@ export class Context implements IContext {
|
|
|
708
831
|
return coroutine;
|
|
709
832
|
}
|
|
710
833
|
|
|
834
|
+
/** @internal Automatically called by components. */
|
|
711
835
|
unregisterCoroutineUpdate(coroutine: Generator, evt: FrameEvent): void {
|
|
712
836
|
if (!this.coroutines[evt]) return;
|
|
713
837
|
const idx = this.coroutines[evt].findIndex(c => c.main === coroutine);
|
|
714
838
|
if (idx >= 0) this.coroutines[evt].splice(idx, 1);
|
|
715
839
|
}
|
|
716
840
|
|
|
841
|
+
/** @internal Automatically called */
|
|
717
842
|
stopAllCoroutinesFrom(script: IComponent) {
|
|
718
843
|
for (const evt in this.coroutines) {
|
|
719
844
|
const rout: CoroutineData[] = this.coroutines[evt];
|
|
@@ -728,6 +853,7 @@ export class Context implements IContext {
|
|
|
728
853
|
|
|
729
854
|
private _cameraStack: ICamera[] = [];
|
|
730
855
|
|
|
856
|
+
/** Change the main camera */
|
|
731
857
|
setCurrentCamera(cam: ICamera) {
|
|
732
858
|
if (!cam) return;
|
|
733
859
|
if (!cam.threeCamera) cam.buildCamera(); // < to build camera
|
|
@@ -745,6 +871,9 @@ export class Context implements IContext {
|
|
|
745
871
|
(this.mainCameraComponent as ICamera)?.applyClearFlagsIfIsActiveCamera();
|
|
746
872
|
}
|
|
747
873
|
|
|
874
|
+
/**
|
|
875
|
+
* Remove the camera from the mainCamera stack (if it has been set before with `setCurrentCamera`)
|
|
876
|
+
*/
|
|
748
877
|
removeCamera(cam?: ICamera | null) {
|
|
749
878
|
if (!cam) return;
|
|
750
879
|
const index = this._cameraStack.indexOf(cam);
|
|
@@ -760,12 +889,12 @@ export class Context implements IContext {
|
|
|
760
889
|
}
|
|
761
890
|
}
|
|
762
891
|
|
|
763
|
-
|
|
764
|
-
|
|
765
892
|
private _onBeforeRenderListeners = new Map<string, OnRenderCallback[]>();
|
|
766
893
|
private _onAfterRenderListeners = new Map<string, OnRenderCallback[]>();
|
|
767
894
|
|
|
768
|
-
/**
|
|
895
|
+
/** Use to subscribe to onBeforeRender events on threejs objects.
|
|
896
|
+
* @link https://threejs.org/docs/#api/en/core/Object3D.onBeforeRender
|
|
897
|
+
*/
|
|
769
898
|
addBeforeRenderListener(target: Object3D, callback: OnRenderCallback) {
|
|
770
899
|
if (!this._onBeforeRenderListeners.has(target.uuid)) {
|
|
771
900
|
this._onBeforeRenderListeners.set(target.uuid, []);
|
|
@@ -773,6 +902,9 @@ export class Context implements IContext {
|
|
|
773
902
|
}
|
|
774
903
|
this._onBeforeRenderListeners.get(target.uuid)!.push(callback);
|
|
775
904
|
}
|
|
905
|
+
/** Remove callback from three `onBeforeRender` event (if it has been added with `addBeforeRenderListener(...)`)
|
|
906
|
+
* @link https://threejs.org/docs/#api/en/core/Object3D.onBeforeRender
|
|
907
|
+
*/
|
|
776
908
|
removeBeforeRenderListener(target: Object3D, callback: OnRenderCallback) {
|
|
777
909
|
if (this._onBeforeRenderListeners.has(target.uuid)) {
|
|
778
910
|
const arr = this._onBeforeRenderListeners.get(target.uuid)!;
|
|
@@ -781,7 +913,10 @@ export class Context implements IContext {
|
|
|
781
913
|
}
|
|
782
914
|
}
|
|
783
915
|
|
|
784
|
-
/**
|
|
916
|
+
/**
|
|
917
|
+
* Subscribe to onAfterRender events on threejs objects
|
|
918
|
+
* @link https://threejs.org/docs/#api/en/core/Object3D.onAfterRender
|
|
919
|
+
*/
|
|
785
920
|
addAfterRenderListener(target: Object3D, callback: OnRenderCallback) {
|
|
786
921
|
if (!this._onAfterRenderListeners.has(target.uuid)) {
|
|
787
922
|
this._onAfterRenderListeners.set(target.uuid, []);
|
|
@@ -789,6 +924,10 @@ export class Context implements IContext {
|
|
|
789
924
|
}
|
|
790
925
|
this._onAfterRenderListeners.get(target.uuid)?.push(callback);
|
|
791
926
|
}
|
|
927
|
+
/**
|
|
928
|
+
* Remove from onAfterRender events on threejs objects
|
|
929
|
+
* @link https://threejs.org/docs/#api/en/core/Object3D.onAfterRender
|
|
930
|
+
*/
|
|
792
931
|
removeAfterRenderListener(target: Object3D, callback: OnRenderCallback) {
|
|
793
932
|
if (this._onAfterRenderListeners.has(target.uuid)) {
|
|
794
933
|
const arr = this._onAfterRenderListeners.get(target.uuid)!;
|
|
@@ -816,25 +955,23 @@ export class Context implements IContext {
|
|
|
816
955
|
private _renderTarget?: WebGLRenderTarget;
|
|
817
956
|
private _isRendering: boolean = false;
|
|
818
957
|
|
|
958
|
+
/** @returns true while the WebGL renderer is rendering (between onBeforeRender and onAfterRender events) */
|
|
819
959
|
get isRendering() { return this._isRendering; }
|
|
820
960
|
|
|
821
961
|
setRequireDepth(val: boolean) {
|
|
822
962
|
this._requireDepthTexture = val;
|
|
823
963
|
}
|
|
824
|
-
|
|
825
964
|
setRequireColor(val: boolean) {
|
|
826
965
|
this._requireColorTexture = val;
|
|
827
966
|
}
|
|
828
|
-
|
|
829
967
|
get depthTexture(): DepthTexture | null {
|
|
830
968
|
return this._renderTarget?.depthTexture || null;
|
|
831
969
|
}
|
|
832
|
-
|
|
833
970
|
get opaqueColorTexture(): Texture | null {
|
|
834
971
|
return this._renderTarget?.texture || null;
|
|
835
972
|
}
|
|
836
973
|
|
|
837
|
-
/** returns true if the
|
|
974
|
+
/** @returns true if the `<needle-engine>` DOM element is visible on screen (`context.domElement`) */
|
|
838
975
|
get isVisibleToUser() {
|
|
839
976
|
if (this.isInXR) return true;
|
|
840
977
|
if (!this._isVisible) return false;
|
|
@@ -842,7 +979,6 @@ export class Context implements IContext {
|
|
|
842
979
|
return style.visibility !== "hidden" && style.display !== "none" && style.opacity !== "0";
|
|
843
980
|
}
|
|
844
981
|
|
|
845
|
-
|
|
846
982
|
private _createId: number = 0;
|
|
847
983
|
private async internalOnCreate(opts?: ContextCreateArgs): Promise<boolean> {
|
|
848
984
|
const createId = ++this._createId;
|
|
@@ -1016,7 +1152,7 @@ export class Context implements IContext {
|
|
|
1016
1152
|
// this.composer.setSize(this.domWidth, this.domHeight);
|
|
1017
1153
|
}
|
|
1018
1154
|
|
|
1019
|
-
this.
|
|
1155
|
+
this._needsUpdateSize = true;
|
|
1020
1156
|
|
|
1021
1157
|
if (this._stats) {
|
|
1022
1158
|
this._stats.showPanel(0);
|
|
@@ -1186,11 +1322,11 @@ export class Context implements IContext {
|
|
|
1186
1322
|
if (frame === undefined) frame = null;
|
|
1187
1323
|
if (isDevEnvironment() || debug || looputils.hasNewScripts()) {
|
|
1188
1324
|
try {
|
|
1189
|
-
performance.mark('update.start');
|
|
1325
|
+
//performance.mark('update.start');
|
|
1190
1326
|
this.internalStep(timestamp, frame);
|
|
1191
1327
|
this._renderlooperrors = 0;
|
|
1192
|
-
performance.mark('update.end');
|
|
1193
|
-
performance.measure('NE Frame', 'update.start', 'update.end');
|
|
1328
|
+
//performance.mark('update.end');
|
|
1329
|
+
//performance.measure('NE Frame', 'update.start', 'update.end');
|
|
1194
1330
|
}
|
|
1195
1331
|
catch (err) {
|
|
1196
1332
|
this._renderlooperrors += 1;
|
|
@@ -1361,7 +1497,7 @@ export class Context implements IContext {
|
|
|
1361
1497
|
this.executeCoroutines(FrameEvent.OnBeforeRender);
|
|
1362
1498
|
invokeLifecycleFunctions(this, FrameEvent.OnBeforeRender);
|
|
1363
1499
|
|
|
1364
|
-
if (this.
|
|
1500
|
+
if (this._needsUpdateSize)
|
|
1365
1501
|
this.updateSize();
|
|
1366
1502
|
|
|
1367
1503
|
if (this.pre_render_callbacks) {
|
|
@@ -12,6 +12,7 @@ import { NeedleLoader } from "./engine_scenetools.js";
|
|
|
12
12
|
import { Context, ContextCreateArgs } from "./engine_setup.js";
|
|
13
13
|
import { type INeedleEngineComponent, type LoadedModel } from "./engine_types.js";
|
|
14
14
|
import { getParam } from "./engine_utils.js";
|
|
15
|
+
import { RGBAColor } from "./js-extensions/RGBAColor.js";
|
|
15
16
|
import { ensureFonts } from "./webcomponents/fonts.js";
|
|
16
17
|
|
|
17
18
|
//
|
|
@@ -177,6 +178,9 @@ export class NeedleEngineHTMLElement extends HTMLElement implements INeedleEngin
|
|
|
177
178
|
-webkit-touch-callout: none;
|
|
178
179
|
-webkit-user-drag: none;
|
|
179
180
|
-webkit-user-modify: none;
|
|
181
|
+
|
|
182
|
+
left: 0;
|
|
183
|
+
top: 0;
|
|
180
184
|
}
|
|
181
185
|
:host .content {
|
|
182
186
|
position: absolute;
|
|
@@ -517,7 +521,7 @@ export class NeedleEngineHTMLElement extends HTMLElement implements INeedleEngin
|
|
|
517
521
|
|
|
518
522
|
private applyAttributes() {
|
|
519
523
|
// set tonemapping if configured
|
|
520
|
-
if (this._context
|
|
524
|
+
if (this._context?.renderer) {
|
|
521
525
|
const attribute = this.getAttribute("tonemapping") || this.getAttribute("tone-mapping") as TonemappingAttributeOptions | null | undefined;
|
|
522
526
|
switch (attribute?.toLowerCase()) {
|
|
523
527
|
case "none":
|
|
@@ -555,15 +559,12 @@ export class NeedleEngineHTMLElement extends HTMLElement implements INeedleEngin
|
|
|
555
559
|
}
|
|
556
560
|
|
|
557
561
|
const backgroundColor = this.getAttribute("background-color");
|
|
558
|
-
if (this._context) {
|
|
562
|
+
if (this._context?.renderer) {
|
|
559
563
|
if (typeof backgroundColor === "string" && backgroundColor.length > 0) {
|
|
560
|
-
const
|
|
561
|
-
if (
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
else {
|
|
565
|
-
this._context.scene.background = new Color(backgroundColor);
|
|
566
|
-
}
|
|
564
|
+
const rgbaColor = RGBAColor.fromColorRepresentation(backgroundColor);
|
|
565
|
+
if(debug) console.debug("<needle-engine> background-color changed, str:", backgroundColor, "→", rgbaColor)
|
|
566
|
+
this._context.renderer.setClearColor(rgbaColor, rgbaColor.alpha);
|
|
567
|
+
this.context.scene.background = null;
|
|
567
568
|
}
|
|
568
569
|
}
|
|
569
570
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Bone, Object3D, Quaternion, SkinnedMesh, Vector3 } from "three";
|
|
2
2
|
|
|
3
|
+
import { $shadowDomOwner } from "../engine-components/ui/Symbols.js";
|
|
3
4
|
import { type AssetReference } from "./engine_addressables.js";
|
|
4
5
|
import { __internalNotifyObjectDestroyed as __internalRemoveReferences, disposeObjectResources } from "./engine_assetdatabase.js";
|
|
5
6
|
import { ComponentLifecycleEvents } from "./engine_components_internal.js";
|
|
@@ -380,6 +381,12 @@ function internalInstantiate(
|
|
|
380
381
|
)
|
|
381
382
|
: GameObject | Object3D | null {
|
|
382
383
|
if (!instance) return null;
|
|
384
|
+
|
|
385
|
+
// Don't clone UI shadow objects
|
|
386
|
+
if (instance[$shadowDomOwner]) {
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
|
|
383
390
|
// prepare, remove things that dont work out of the box
|
|
384
391
|
// e.g. user data we want to manually clone
|
|
385
392
|
// also children throw errors (e.g. recursive toJson with nested meshes)
|