Needle Engine

Changes between version 3.37.11-alpha and 3.37.12-alpha
Files changed (6) hide show
  1. src/engine-components/ContactShadows.ts +20 -0
  2. src/engine/engine_context_registry.ts +2 -0
  3. src/engine/engine_context.ts +5 -0
  4. src/engine/engine_lifecycle_api.ts +17 -0
  5. src/engine/engine_loaders.ts +5 -1
  6. src/engine-components/OrbitControls.ts +48 -27
src/engine-components/ContactShadows.ts CHANGED
@@ -57,14 +57,34 @@
57
57
  */
58
58
  @serializable()
59
59
  autoFit: boolean = false;
60
+ /**
61
+ * Darkness of the shadows.
62
+ * @default 0.5
63
+ */
60
64
  @serializable()
61
65
  darkness: number = 0.5;
66
+ /**
67
+ * Opacity of the shadows.
68
+ * @default 0.5
69
+ */
62
70
  @serializable()
63
71
  opacity: number = 0.5;
72
+ /**
73
+ * Blur of the shadows.
74
+ * @default 4.0
75
+ */
64
76
  @serializable()
65
77
  blur: number = 4.0;
78
+ /**
79
+ * When enabled objects will not be visible below the shadow plane
80
+ * @default false
81
+ */
66
82
  @serializable()
67
83
  occludeBelowGround: boolean = false;
84
+ /**
85
+ * When enabled the backfaces of objects will cast shadows as well.
86
+ * @default true
87
+ */
68
88
  @serializable()
69
89
  backfaceShadows: boolean = true;
70
90
 
src/engine/engine_context_registry.ts CHANGED
@@ -11,6 +11,8 @@
11
11
  ContextCreated = "ContextCreated",
12
12
  /** Called after the first frame has been rendered after creation */
13
13
  ContextFirstFrameRendered = "ContextFirstFrameRendered",
14
+ /** Called before the context gets destroyed */
15
+ ContextDestroying = "ContextDestroying",
14
16
  /** Called when the context has been destroyed */
15
17
  ContextDestroyed = "ContextDestroyed",
16
18
  /** Called when the context could not find a camera during creation */
src/engine/engine_context.ts CHANGED
@@ -571,6 +571,7 @@
571
571
  */
572
572
  clear() {
573
573
  ContextRegistry.dispatchCallback(ContextEvent.ContextClearing, this);
574
+ invokeLifecycleFunctions(this, ContextEvent.ContextClearing);
574
575
  // NOTE: this does dispose the environment/background image too
575
576
  // which is probably not desired if it is set via the skybox-image attribute
576
577
  destroy(this.scene, true, true);
@@ -598,6 +599,9 @@
598
599
  /**@deprecated use dispose() */
599
600
  onDestroy() { this.internalOnDestroy(); }
600
601
  private internalOnDestroy() {
602
+ Context.Current = this;
603
+ ContextRegistry.dispatchCallback(ContextEvent.ContextDestroying, this);
604
+ invokeLifecycleFunctions(this, ContextEvent.ContextDestroying);
601
605
  this.clear();
602
606
  this.renderer?.setAnimationLoop(null);
603
607
  if (this.renderer) {
@@ -625,6 +629,7 @@
625
629
  }
626
630
  this._isCreated = false;
627
631
  ContextRegistry.dispatchCallback(ContextEvent.ContextDestroyed, this);
632
+ invokeLifecycleFunctions(this, ContextEvent.ContextDestroyed);
628
633
  ContextRegistry.unregister(this);
629
634
  if (Context.Current === this) {
630
635
  //@ts-ignore
src/engine/engine_lifecycle_api.ts CHANGED
@@ -19,7 +19,24 @@
19
19
  registerFrameEventCallback(cb, ContextEvent.ContextCreated);
20
20
  return () => unregisterFrameEventCallback(cb, ContextEvent.ContextCreated);
21
21
  }
22
+ /**
23
+ * Register a callback before the engine context is cleared.
24
+ * This happens if e.g. `<needle-engine src>` changes
25
+ */
26
+ export function onClear(cb: LifecycleMethod): () => void {
27
+ registerFrameEventCallback(cb, ContextEvent.ContextClearing);
28
+ return () => unregisterFrameEventCallback(cb, ContextEvent.ContextClearing);
29
+ }
22
30
 
31
+ /**
32
+ * Register a callback in the engine before the context is destroyed
33
+ * This happens once per context (before the context is destroyed)
34
+ */
35
+ export function onDestroy(cb: LifecycleMethod): () => void {
36
+ registerFrameEventCallback(cb, ContextEvent.ContextDestroying);
37
+ return () => unregisterFrameEventCallback(cb, ContextEvent.ContextDestroying);
38
+ }
39
+
23
40
  /** Register a callback in the engine start event.
24
41
  * This happens at the beginning of each frame
25
42
  * @param cb The callback to be called
src/engine/engine_loaders.ts CHANGED
@@ -1,4 +1,5 @@
1
1
 
2
+ import { setDracoDecoderLocation, setKTX2TranscoderLocation } from '@needle-tools/gltf-progressive';
2
3
  import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
3
4
  import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
4
5
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
@@ -10,9 +11,9 @@
10
11
 
11
12
  const debug = getParam("debugdecoders");
12
13
 
14
+ // NOTE: keep in sync with gltf-progressive
13
15
  let DEFAULT_DRACO_DECODER_LOCATION = 'https://www.gstatic.com/draco/versioned/decoders/1.4.1/';
14
16
  let DEFAULT_KTX2_TRANSCODER_LOCATION = 'https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/';
15
-
16
17
  fetch(DEFAULT_DRACO_DECODER_LOCATION + "draco_decoder.js", { method: "head" })
17
18
  .catch(_ => {
18
19
  if (isDevEnvironment()) console.warn("Failed to load draco decoder from \"" + DEFAULT_DRACO_DECODER_LOCATION + "\".\nFalling back to local version at \"./include/draco\"");
@@ -20,6 +21,7 @@
20
21
  DEFAULT_KTX2_TRANSCODER_LOCATION = "./include/ktx2/";
21
22
  });
22
23
 
24
+
23
25
  let dracoLoader: DRACOLoader;
24
26
  let meshoptDecoder: typeof MeshoptDecoder;
25
27
  let ktx2Loader: KTX2Loader;
@@ -30,6 +32,7 @@
30
32
  dracoLoader = new DRACOLoader();
31
33
  if (debug) console.log("Setting draco decoder path to", path);
32
34
  dracoLoader.setDecoderPath(path);
35
+ setDracoDecoderLocation(path);
33
36
  }
34
37
  }
35
38
 
@@ -48,6 +51,7 @@
48
51
  ktx2Loader = new KTX2Loader();
49
52
  if (debug) console.log("Setting ktx2 transcoder path to", path);
50
53
  ktx2Loader.setTranscoderPath(path);
54
+ setKTX2TranscoderLocation(path);
51
55
  }
52
56
  }
53
57
 
src/engine-components/OrbitControls.ts CHANGED
@@ -75,20 +75,30 @@
75
75
  this.controls?.addEventListener("start", callback as any);
76
76
  }
77
77
 
78
- /** When enabled OrbitControls will automatically raycast find a look at target in start */
78
+ /** When enabled OrbitControls will automatically raycast find a look at target in start
79
+ * @default true
80
+ */
79
81
  @serializable()
80
82
  autoTarget: boolean = true;
81
- /** When enabled the scene will be automatically fitted into the camera view in onEnable */
83
+ /** When enabled the scene will be automatically fitted into the camera view in onEnable
84
+ * @default false
85
+ */
82
86
  @serializable()
83
87
  autoFit: boolean = false;
84
88
 
85
- /** When enabled the camera can be rotated */
89
+ /** When enabled the camera can be rotated
90
+ * @default true
91
+ */
86
92
  @serializable()
87
93
  enableRotate: boolean = true;
88
- /** When enabled the camera will rotate automatically */
94
+ /** When enabled the camera will rotate automatically
95
+ * @default false
96
+ */
89
97
  @serializable()
90
98
  autoRotate: boolean = false;
91
- /** The speed at which the camera will rotate automatically. Will only be used when `autoRotate` is enabled */
99
+ /** The speed at which the camera will rotate automatically. Will only be used when `autoRotate` is enabled
100
+ * @default 1.0
101
+ */
92
102
  @serializable()
93
103
  autoRotateSpeed: number = 1.0;
94
104
  /** The minimum azimuth angle in radians */
@@ -97,30 +107,46 @@
97
107
  /** The maximum azimuth angle in radians */
98
108
  @serializable()
99
109
  maxAzimuthAngle: number = Infinity;
100
- /** The minimum polar angle in radians */
110
+ /** The minimum polar angle in radians
111
+ * @default 0
112
+ */
101
113
  @serializable()
102
114
  minPolarAngle: number = 0;
103
- /** The maximum polar angle in radians */
115
+ /** The maximum polar angle in radians
116
+ * @default Math.PI
117
+ */
104
118
  @serializable()
105
119
  maxPolarAngle: number = Math.PI;
106
120
 
107
- /** When enabled the camera can be moved using keyboard keys. The keys are defined in the `controls.keys` property */
121
+ /** When enabled the camera can be moved using keyboard keys. The keys are defined in the `controls.keys` property
122
+ * @default true
123
+ */
108
124
  @serializable()
109
125
  enableKeys: boolean = true;
110
- /** When enabled the camera movement will be damped */
126
+ /** When enabled the camera movement will be damped
127
+ * @default true
128
+ */
111
129
  @serializable()
112
130
  enableDamping: boolean = true;
113
- /** The damping factor for the camera movement. For more information see the [three.js documentation](https://threejs.org/docs/#examples/en/controls/OrbitControls.dampingFactor) */
131
+ /** The damping factor for the camera movement. For more information see the [three.js documentation](https://threejs.org/docs/#examples/en/controls/OrbitControls.dampingFactor)
132
+ * @default 0.1
133
+ */
114
134
  @serializable()
115
135
  dampingFactor: number = 0.1;
116
136
 
117
- /** When enabled the camera can be zoomed */
137
+ /** When enabled the camera can be zoomed
138
+ * @default true
139
+ */
118
140
  @serializable()
119
141
  enableZoom: boolean = true;
120
- /** The minimum zoom level */
142
+ /** The minimum zoom level
143
+ * @default 0
144
+ */
121
145
  @serializable()
122
146
  minZoom: number = 0;
123
- /** The maximum zoom level */
147
+ /** The maximum zoom level
148
+ * @default Infinity
149
+ */
124
150
  @serializable()
125
151
  maxZoom: number = Infinity;
126
152
 
@@ -128,28 +154,21 @@
128
154
  * Sets the zoom speed of the OrbitControls
129
155
  * @default 1
130
156
  */
131
- set zoomSpeed(value: number) {
132
- if (this._controls) this._controls.zoomSpeed = value;
133
- }
134
- get zoomSpeed() {
135
- return this._controls?.zoomSpeed ?? 0;
136
- }
157
+ @serializable()
158
+ zoomSpeed: number = 1;
137
159
 
138
160
  /**
139
161
  * Set to true to enable zooming to the cursor position.
140
162
  * @default false
141
163
  */
142
- set zoomToCursor(value: boolean) {
143
- if (this._controls) this._controls.zoomToCursor = value;
144
- }
145
- get zoomToCursor() {
146
- return this._controls?.zoomToCursor ?? false;
147
- }
164
+ zoomToCursor: boolean = false;
148
165
 
149
- /** When enabled the camera can be panned */
166
+ /** When enabled the camera can be panned
167
+ * @default true
168
+ */
150
169
  @serializable()
151
170
  enablePan: boolean = true;
152
- /** Assigning a LookAtConstraint will make the camera look at the constraint source */
171
+ /** Assigning a {@link LookAtConstraint} will make the camera look at the constraint source */
153
172
  @serializable(LookAtConstraint)
154
173
  lookAtConstraint: LookAtConstraint | null = null;
155
174
  /** The weight of the first lookAtConstraint source */
@@ -402,6 +421,8 @@
402
421
  this._controls.autoRotate = this.autoRotate;
403
422
  this._controls.autoRotateSpeed = this.autoRotateSpeed;
404
423
  this._controls.enableZoom = this.enableZoom;
424
+ this._controls.zoomSpeed = this.zoomSpeed;
425
+ this._controls.zoomToCursor = this.zoomToCursor;
405
426
  this._controls.enableDamping = this.enableDamping;
406
427
  this._controls.dampingFactor = this.dampingFactor;
407
428
  this._controls.enablePan = this.enablePan;