@needle-tools/engine 3.5.2-alpha → 3.5.3-alpha

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.
Files changed (99) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/needle-engine.js +17123 -16970
  3. package/dist/needle-engine.min.js +349 -349
  4. package/dist/needle-engine.umd.cjs +347 -347
  5. package/lib/engine/codegen/register_types.js +4 -0
  6. package/lib/engine/codegen/register_types.js.map +1 -1
  7. package/lib/engine/debug/debug_overlay.js +2 -1
  8. package/lib/engine/debug/debug_overlay.js.map +1 -1
  9. package/lib/engine/engine_components.js +2 -1
  10. package/lib/engine/engine_components.js.map +1 -1
  11. package/lib/engine/engine_element_loading.js +2 -2
  12. package/lib/engine/engine_element_loading.js.map +1 -1
  13. package/lib/engine/engine_gameobject.js +2 -0
  14. package/lib/engine/engine_gameobject.js.map +1 -1
  15. package/lib/engine/engine_input.js +4 -1
  16. package/lib/engine/engine_input.js.map +1 -1
  17. package/lib/engine/engine_physics_rapier.js +2 -1
  18. package/lib/engine/engine_physics_rapier.js.map +1 -1
  19. package/lib/engine/engine_serialization_core.js +16 -1
  20. package/lib/engine/engine_serialization_core.js.map +1 -1
  21. package/lib/engine/extensions/NEEDLE_lighting_settings.js +10 -1
  22. package/lib/engine/extensions/NEEDLE_lighting_settings.js.map +1 -1
  23. package/lib/engine-components/Component.js +0 -3
  24. package/lib/engine-components/Component.js.map +1 -1
  25. package/lib/engine-components/codegen/components.d.ts +2 -0
  26. package/lib/engine-components/codegen/components.js +2 -0
  27. package/lib/engine-components/codegen/components.js.map +1 -1
  28. package/lib/engine-components/export/usdz/Extension.d.ts +3 -2
  29. package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +41 -13
  30. package/lib/engine-components/export/usdz/ThreeUSDZExporter.js.map +1 -1
  31. package/lib/engine-components/export/usdz/USDZExporter.d.ts +1 -0
  32. package/lib/engine-components/export/usdz/USDZExporter.js +30 -4
  33. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  34. package/lib/engine-components/export/usdz/extensions/behavior/AudioExtension.d.ts +9 -0
  35. package/lib/engine-components/export/usdz/extensions/behavior/AudioExtension.js +48 -0
  36. package/lib/engine-components/export/usdz/extensions/behavior/AudioExtension.js.map +1 -0
  37. package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.d.ts +3 -0
  38. package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js +18 -0
  39. package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js.map +1 -1
  40. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.d.ts +9 -0
  41. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js +71 -1
  42. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js.map +1 -1
  43. package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.d.ts +20 -0
  44. package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js +45 -0
  45. package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js.map +1 -1
  46. package/lib/engine-components/ui/BaseUIComponent.d.ts +1 -0
  47. package/lib/engine-components/ui/BaseUIComponent.js +8 -4
  48. package/lib/engine-components/ui/BaseUIComponent.js.map +1 -1
  49. package/lib/engine-components/ui/Canvas.js +1 -1
  50. package/lib/engine-components/ui/Canvas.js.map +1 -1
  51. package/lib/engine-components/ui/EventSystem.js +3 -0
  52. package/lib/engine-components/ui/EventSystem.js.map +1 -1
  53. package/lib/engine-components/ui/Image.d.ts +3 -1
  54. package/lib/engine-components/ui/Image.js +15 -1
  55. package/lib/engine-components/ui/Image.js.map +1 -1
  56. package/lib/engine-components/ui/Interfaces.d.ts +1 -1
  57. package/lib/engine-components/ui/Layout.js +2 -0
  58. package/lib/engine-components/ui/Layout.js.map +1 -1
  59. package/lib/engine-components/ui/PointerEvents.d.ts +8 -1
  60. package/lib/engine-components/ui/PointerEvents.js +9 -1
  61. package/lib/engine-components/ui/PointerEvents.js.map +1 -1
  62. package/lib/engine-components/ui/RaycastUtils.js +5 -0
  63. package/lib/engine-components/ui/RaycastUtils.js.map +1 -1
  64. package/lib/engine-components/ui/RectTransform.d.ts +2 -2
  65. package/lib/engine-components/ui/RectTransform.js +11 -12
  66. package/lib/engine-components/ui/RectTransform.js.map +1 -1
  67. package/lib/engine-components/ui/Text.d.ts +0 -2
  68. package/lib/engine-components/ui/Text.js +0 -5
  69. package/lib/engine-components/ui/Text.js.map +1 -1
  70. package/lib/tsconfig.tsbuildinfo +1 -1
  71. package/package.json +1 -1
  72. package/src/engine/codegen/register_types.js +6 -2
  73. package/src/engine/debug/debug_overlay.ts +2 -1
  74. package/src/engine/engine_components.ts +2 -1
  75. package/src/engine/engine_element_loading.ts +2 -2
  76. package/src/engine/engine_gameobject.ts +3 -0
  77. package/src/engine/engine_input.ts +4 -1
  78. package/src/engine/engine_physics_rapier.ts +2 -1
  79. package/src/engine/engine_serialization_core.ts +17 -1
  80. package/src/engine/extensions/NEEDLE_lighting_settings.ts +11 -1
  81. package/src/engine-components/Component.ts +1 -3
  82. package/src/engine-components/codegen/components.ts +2 -0
  83. package/src/engine-components/export/usdz/Extension.ts +3 -2
  84. package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +53 -14
  85. package/src/engine-components/export/usdz/USDZExporter.ts +34 -4
  86. package/src/engine-components/export/usdz/extensions/behavior/AudioExtension.ts +63 -0
  87. package/src/engine-components/export/usdz/extensions/behavior/Behaviour.ts +23 -1
  88. package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +79 -2
  89. package/src/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.ts +46 -0
  90. package/src/engine-components/ui/BaseUIComponent.ts +8 -3
  91. package/src/engine-components/ui/Canvas.ts +1 -1
  92. package/src/engine-components/ui/EventSystem.ts +5 -1
  93. package/src/engine-components/ui/Image.ts +16 -1
  94. package/src/engine-components/ui/Interfaces.ts +1 -1
  95. package/src/engine-components/ui/Layout.ts +2 -0
  96. package/src/engine-components/ui/PointerEvents.ts +16 -2
  97. package/src/engine-components/ui/RaycastUtils.ts +6 -1
  98. package/src/engine-components/ui/RectTransform.ts +11 -11
  99. package/src/engine-components/ui/Text.ts +1 -3
@@ -6,11 +6,12 @@ import { IPointerClickHandler } from "../../../../ui/PointerEvents";
6
6
  import { RegisteredAnimationInfo, UsdzAnimation } from "../Animation";
7
7
  import { getWorldPosition, getWorldQuaternion, getWorldScale, setWorldPosition, setWorldQuaternion, setWorldScale } from "../../../../../engine/engine_three_utils";
8
8
 
9
- import { Object3D, Material, Vector3, Quaternion, AnimationAction } from "three";
9
+ import { Object3D, Material, Vector3, Quaternion } from "three";
10
10
  import { USDDocument, USDObject } from "../../ThreeUSDZExporter";
11
11
 
12
12
  import { BehaviorExtension, UsdzBehaviour } from "./Behaviour";
13
- import { ActionBuilder, ActionModel, BehaviorModel, IBehaviorElement, MotionType, Space, TriggerBuilder } from "./BehavioursBuilder";
13
+ import { ActionBuilder, ActionModel, AuralMode, BehaviorModel, IBehaviorElement, MotionType, PlayAction, Space, TriggerBuilder } from "./BehavioursBuilder";
14
+ import { AudioSource } from "../../../../AudioSource";
14
15
 
15
16
  export class ChangeTransformOnClick extends Behaviour implements IPointerClickHandler, UsdzBehaviour {
16
17
 
@@ -407,6 +408,82 @@ export class EmphasizeOnClick extends Behaviour implements UsdzBehaviour {
407
408
  afterCreateDocument(_ext, _context) { }
408
409
  }
409
410
 
411
+ export class PlayAudioOnClick extends Behaviour implements IPointerClickHandler, UsdzBehaviour {
412
+
413
+ @serializable(AudioSource)
414
+ target?: AudioSource;
415
+
416
+ @serializable(URL)
417
+ clip: string = "";
418
+
419
+ @serializable()
420
+ toggleOnClick: boolean = false;
421
+
422
+ onPointerClick() {
423
+ if (!this.target && !this.clip) return;
424
+
425
+ if (!this.target) {
426
+
427
+ const newAudioSource = this.gameObject.addNewComponent(AudioSource);
428
+ if (newAudioSource) {
429
+ newAudioSource.spatialBlend = 1;
430
+ newAudioSource.volume = 1;
431
+ newAudioSource.loop = false;
432
+
433
+ this.target = newAudioSource;
434
+ }
435
+ }
436
+
437
+ if (this.target) {
438
+
439
+ if (this.target.isPlaying && this.toggleOnClick) {
440
+ this.target.stop();
441
+ }
442
+ else {
443
+ if (!this.toggleOnClick && this.target.isPlaying) {
444
+ this.target.stop();
445
+ }
446
+ if (this.clip) this.target.play(this.clip);
447
+ else this.target.play();
448
+ }
449
+ }
450
+ }
451
+
452
+ createBehaviours(ext, model, _context) {
453
+ if (!this.target && !this.clip) return;
454
+ if (model.uuid === this.gameObject.uuid) {
455
+
456
+ const clipUrl = this.clip ? this.clip : this.target ? this.target.clip : undefined;
457
+ if (!clipUrl) return;
458
+
459
+ const playbackTarget = this.target ? this.target.gameObject : this.gameObject;
460
+ const clipName = clipUrl.split("/").pop();
461
+ const volume = this.target ? this.target.volume : 1;
462
+ const auralMode = this.target && this.target.spatialBlend == 0 ? AuralMode.NonSpatial : AuralMode.Spatial;
463
+ const playClip = new BehaviorModel("playAudio " + this.name,
464
+ TriggerBuilder.tapTrigger(this.gameObject),
465
+ ActionBuilder.playAudioAction(playbackTarget, "audio/" + clipName, PlayAction.Play, volume, auralMode),
466
+ );
467
+ ext.addBehavior(playClip);
468
+ }
469
+ }
470
+
471
+ async afterSerialize(_ext, context) {
472
+ if (!this.target && !this.clip) return;
473
+ const clipUrl = this.clip ? this.clip : this.target ? this.target.clip : undefined;
474
+ if (!clipUrl) return;
475
+ const clipName = clipUrl.split("/").pop();
476
+
477
+ const audio = await fetch(this.clip);
478
+ const audioBlob = await audio.blob();
479
+ const arrayBuffer = await audioBlob.arrayBuffer();
480
+
481
+ const audioData: Uint8Array = new Uint8Array(arrayBuffer)
482
+
483
+ context.files["audio/" + clipName] = audioData;
484
+ }
485
+ }
486
+
410
487
  export class PlayAnimationOnClick extends Behaviour implements IPointerClickHandler, UsdzBehaviour, UsdzAnimation {
411
488
 
412
489
  @serializable(Object3D)
@@ -237,6 +237,13 @@ export enum Space {
237
237
  Absolute = "absolute"
238
238
  };
239
239
 
240
+ // https://developer.apple.com/documentation/arkit/usdz_schemas_for_ar/actions_and_triggers/preliminary_action/multipleperformoperation
241
+ export enum MultiplePerformOperation {
242
+ Allow = "allow",
243
+ Ignore = "ignore",
244
+ Stop = "stop",
245
+ }
246
+
240
247
  export class ActionModel implements IBehaviorElement {
241
248
 
242
249
  private static global_id: number = 0;
@@ -257,6 +264,10 @@ export class ActionModel implements IBehaviorElement {
257
264
  reversed?: boolean;
258
265
  pingPong?: boolean;
259
266
  xFormTarget?: Target | string;
267
+ audio?: string;
268
+ gain?: number;
269
+ auralMode?: string;
270
+ multiplePerformOperation?: string;
260
271
 
261
272
  clone(): ActionModel {
262
273
  const copy = new ActionModel();
@@ -319,6 +330,18 @@ export class ActionModel implements IBehaviorElement {
319
330
  this.xFormTarget = resolve(this.xFormTarget, document);
320
331
  writer.appendLine(`rel xformTarget = ${this.xFormTarget}`)
321
332
  }
333
+ if (typeof this.audio === "string") {
334
+ writer.appendLine(`asset audio = @${this.audio}@`);
335
+ }
336
+ if (typeof this.gain ==="number") {
337
+ writer.appendLine(`double gain = ${this.gain}`);
338
+ }
339
+ if (typeof this.auralMode === "string") {
340
+ writer.appendLine(`token auralMode = "${this.auralMode}"`);
341
+ }
342
+ if (typeof this.multiplePerformOperation === "string") {
343
+ writer.appendLine(`token multiplePerformOperation = "${this.multiplePerformOperation}"`);
344
+ }
322
345
  writer.closeBlock();
323
346
  }
324
347
  }
@@ -355,6 +378,18 @@ class Vec3 {
355
378
  }
356
379
  }
357
380
 
381
+ export enum PlayAction {
382
+ Play = "play",
383
+ Pause = "pause",
384
+ Stop = "stop",
385
+ }
386
+
387
+ export enum AuralMode {
388
+ Spatial = "spatial",
389
+ NonSpatial = "nonSpatial",
390
+ Ambient = "ambient",
391
+ }
392
+
358
393
  export class ActionBuilder {
359
394
 
360
395
  static sequence(...params: IBehaviorElement[]) {
@@ -454,6 +489,17 @@ export class ActionBuilder {
454
489
  return act;
455
490
  }
456
491
 
492
+ static playAudioAction(targets: Target, audio: string, type: PlayAction = PlayAction.Play, gain: number = 1, auralMode: AuralMode = AuralMode.Spatial) {
493
+ const act = new ActionModel(targets);
494
+ act.tokenId = "Audio";
495
+ act.type = type;
496
+ act.audio = audio;
497
+ act.gain = gain;
498
+ act.auralMode = auralMode;
499
+ act.multiplePerformOperation = MultiplePerformOperation.Allow;
500
+ return act;
501
+ }
502
+
457
503
  }
458
504
 
459
505
  export { Vec3 as USDVec3 }
@@ -26,6 +26,12 @@ export class BaseUIComponent extends Behaviour {
26
26
 
27
27
  isRoot() { return this.Root?.gameObject === this.gameObject; }
28
28
 
29
+ get canvas() {
30
+ const cv = this.Root as any as ICanvas;
31
+ if (cv?.isCanvas) return cv;
32
+ return null;
33
+ }
34
+
29
35
  markDirty() {
30
36
  EventSystem.markUIDirty(this.context);
31
37
  }
@@ -50,10 +56,9 @@ export class BaseUIComponent extends Behaviour {
50
56
  return this._root;
51
57
  }
52
58
 
59
+ // TODO: rename to canvas
53
60
  protected get Canvas() {
54
- const cv = this.Root as any as ICanvas;
55
- if (cv?.isCanvas) return cv;
56
- return null;
61
+ return this.canvas;
57
62
  }
58
63
 
59
64
  // private _intermediate?: Object3D;
@@ -193,7 +193,7 @@ export class Canvas extends UIRootComponent implements ICanvas {
193
193
  this.previousParent = this.gameObject.parent;
194
194
  // console.log(this.previousParent?.name + "/" + this.gameObject.name);
195
195
 
196
- if (this.renderOnTop) {
196
+ if (this.renderOnTop || this.screenspace) {
197
197
  // This is just a test but in reality it should be combined with all world canvases with render on top in one render pass
198
198
  this.gameObject.removeFromParent();
199
199
  }
@@ -255,7 +255,7 @@ export class EventSystem extends Behaviour {
255
255
  if (!hits) return;
256
256
  this.lastPointerEvent = args;
257
257
 
258
- const evt : AfterHandleInputEvent = {
258
+ const evt: AfterHandleInputEvent = {
259
259
  sender: this,
260
260
  args: args,
261
261
  hasActiveUI: this.currentActiveMeshUIComponents.length > 0,
@@ -433,6 +433,10 @@ export class EventSystem extends Behaviour {
433
433
  }
434
434
  }
435
435
 
436
+ if (comp.onPointerMove) {
437
+ comp.onPointerMove(args);
438
+ }
439
+
436
440
  if (args.isDown) {
437
441
  if (comp.onPointerDown && !this.raisedPointerDownEvents.includes(comp)) {
438
442
  comp.onPointerDown(args);
@@ -5,13 +5,28 @@ import { MaskableGraphic } from './Graphic';
5
5
 
6
6
  class Sprite {
7
7
  @serializable(Texture)
8
- texture?: THREE.Texture;
8
+ texture: Texture | null = null;
9
9
 
10
10
  rect?: { width: number, height: number };
11
11
  }
12
12
 
13
13
  export class Image extends MaskableGraphic {
14
14
 
15
+ set image(img: Texture | null) {
16
+ if (this.sprite)
17
+ this.sprite.texture = img;
18
+ else {
19
+ this.sprite = new Sprite();
20
+ this.sprite.texture = img;
21
+ }
22
+ this.onAfterCreated();
23
+ }
24
+ get image(): Texture | null {
25
+ if (this.sprite)
26
+ return this.sprite.texture;
27
+ return null;
28
+ }
29
+
15
30
  @serializable(Sprite)
16
31
  get sprite(): Sprite | undefined {
17
32
  return this._sprite;
@@ -1,7 +1,7 @@
1
1
  import { Behaviour } from "../Component";
2
2
  import { IComponent } from "../../engine/engine_types";
3
3
 
4
- export interface ICanvas {
4
+ export interface ICanvas extends IComponent {
5
5
  get isCanvas(): boolean;
6
6
  get screenspace(): boolean;
7
7
  registerTransform(rt: IRectTransform);
@@ -250,6 +250,8 @@ export abstract class HorizontalOrVerticalLayoutGroup extends LayoutGroup {
250
250
  const rt = GameObject.getComponent(ch, RectTransform);
251
251
  if (rt?.activeAndEnabled) {
252
252
  rt.pivot?.set(.5, .5);
253
+ rt.anchorMin.set(0, 1);
254
+ rt.anchorMax.set(0, 1);
253
255
  // Horizontal padding
254
256
  const x = totalWidth * .5 + leftOffset * .5;
255
257
  if (rt.anchoredPosition.x !== x)
@@ -11,12 +11,22 @@ export class PointerEventData implements IInputEventArgs {
11
11
  // TODO: should we make this a getter and return the input used state instead? -> this.context.getPointerUsed(this.pointerId);
12
12
  used: boolean = false;
13
13
 
14
- Use() {
14
+ use() {
15
15
  this.used = true;
16
16
  if (this.pointerId !== undefined)
17
17
  this.input.setPointerUsed(this.pointerId);
18
18
  }
19
19
 
20
+ stopPropagation() {
21
+ this.event?.stopImmediatePropagation();
22
+ }
23
+
24
+ /**@deprecated use use() */
25
+ Use() {
26
+ this.use();
27
+ }
28
+
29
+ /**@deprecated use stopPropagation() */
20
30
  StopPropagation() {
21
31
  this.event?.stopImmediatePropagation();
22
32
  }
@@ -52,6 +62,10 @@ export interface IPointerEnterHandler {
52
62
  onPointerEnter?(args: PointerEventData);
53
63
  }
54
64
 
65
+ export interface IPointerMoveHandler {
66
+ onPointerMove?(args: PointerEventData);
67
+ }
68
+
55
69
  export interface IPointerExitHandler {
56
70
  onPointerExit?(args: PointerEventData);
57
71
  }
@@ -61,4 +75,4 @@ export interface IPointerClickHandler {
61
75
  }
62
76
 
63
77
  export interface IPointerEventHandler extends IPointerDownHandler,
64
- IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler { }
78
+ IPointerUpHandler, IPointerEnterHandler, IPointerMoveHandler, IPointerExitHandler, IPointerClickHandler { }
@@ -20,7 +20,12 @@ export class UIRaycastUtils {
20
20
  };
21
21
 
22
22
  static isInteractable(obj: THREE.Object3D, out?: { canvasGroup?: ICanvasGroup, graphic?: IGraphic }): boolean {
23
- if(obj === null || obj === undefined || !obj.visible) return false;
23
+ // reset state
24
+ if (out) {
25
+ out.canvasGroup = undefined;
26
+ out.graphic = undefined;
27
+ }
28
+ if (obj === null || obj === undefined || !obj.visible) return false;
24
29
 
25
30
  obj = this.getObject(obj);
26
31
 
@@ -31,6 +31,9 @@ const tempQuaternion = new Quaternion();
31
31
 
32
32
  export class RectTransform extends BaseUIComponent implements IRectTransform, IRectTransformChangedReceiver {
33
33
 
34
+ get parent() {
35
+ return this._parentRectTransform;
36
+ }
34
37
  offset: number = .01;
35
38
 
36
39
  // @serializable(Object3D)
@@ -51,24 +54,21 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
51
54
  this._anchoredPosition = value;
52
55
  }
53
56
 
54
- @serializable(Rect)
55
- private rect?: Rect; // TODO: should we use the rect or sizeDelta?
56
-
57
57
  @serializable(Vector2)
58
- sizeDelta!: Vector2;
58
+ sizeDelta: Vector2 = new Vector2(100, 100);
59
59
 
60
60
  @serializable(Vector2)
61
- pivot?: Vector2;
61
+ pivot: Vector2 = new Vector2(.5, .5);
62
62
 
63
63
  @serializable(Vector2)
64
- anchorMin!: Vector2;
64
+ anchorMin: Vector2 = new Vector2(0, 0);
65
65
  @serializable(Vector2)
66
- anchorMax!: Vector2;
66
+ anchorMax: Vector2 = new Vector2(1, 1);
67
67
 
68
68
  @serializable(Vector2)
69
- offsetMin!: Vector2;
69
+ offsetMin: Vector2 = new Vector2(0, 0);
70
70
  @serializable(Vector2)
71
- offsetMax!: Vector2;
71
+ offsetMax: Vector2 = new Vector2(0, 0);
72
72
 
73
73
  get width() {
74
74
  if (this.anchorMin.x !== this.anchorMax.x) {
@@ -301,8 +301,8 @@ export class RectTransform extends BaseUIComponent implements IRectTransform, IR
301
301
  // })
302
302
 
303
303
  const opts = {
304
- width: this.rect!.width,
305
- height: this.rect!.height,// * this.context.mainCameraComponent!.aspect,
304
+ width: this.sizeDelta!.x,
305
+ height: this.sizeDelta!.y,// * this.context.mainCameraComponent!.aspect,
306
306
  offset: this.offset,
307
307
  backgroundOpacity: 0,
308
308
  borderWidth: 0, // if we dont specify width here a border will automatically propagated to child blocks
@@ -40,8 +40,6 @@ export enum FontStyle {
40
40
 
41
41
  export class Text extends Graphic {
42
42
 
43
- @serializable(Canvas)
44
- canvas?: Canvas;
45
43
  @serializable()
46
44
  alignment: TextAnchor = TextAnchor.UpperLeft;
47
45
  @serializable()
@@ -334,7 +332,7 @@ export class Text extends Graphic {
334
332
  private * renderOnTopCoroutine() {
335
333
  if (!this.canvas) return;
336
334
  const updatedRendering: boolean[] = [];
337
- const canvas = this.canvas;
335
+ const canvas = this.canvas as Canvas;
338
336
  const settings = {
339
337
  renderOnTop: canvas.renderOnTop,
340
338
  depthWrite: canvas.depthWrite,