@luma.gl/engine 9.0.0-alpha.9 → 9.0.0-beta.10

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 (187) hide show
  1. package/LICENSE +3 -1
  2. package/dist/animation/key-frames.d.ts +1 -1
  3. package/dist/animation/key-frames.d.ts.map +1 -1
  4. package/dist/animation/key-frames.js +51 -72
  5. package/dist/animation/timeline.d.ts +8 -8
  6. package/dist/animation/timeline.d.ts.map +1 -1
  7. package/dist/animation/timeline.js +95 -131
  8. package/dist/animation-loop/animation-loop-template.d.ts +23 -0
  9. package/dist/animation-loop/animation-loop-template.d.ts.map +1 -0
  10. package/dist/animation-loop/animation-loop-template.js +21 -0
  11. package/dist/{lib → animation-loop}/animation-loop.d.ts +31 -23
  12. package/dist/animation-loop/animation-loop.d.ts.map +1 -0
  13. package/dist/animation-loop/animation-loop.js +442 -0
  14. package/dist/{lib → animation-loop}/animation-props.d.ts +4 -5
  15. package/dist/animation-loop/animation-props.d.ts.map +1 -0
  16. package/dist/animation-loop/animation-props.js +1 -0
  17. package/dist/animation-loop/make-animation-loop.d.ts +6 -0
  18. package/dist/animation-loop/make-animation-loop.d.ts.map +1 -0
  19. package/dist/animation-loop/make-animation-loop.js +32 -0
  20. package/dist/computation.d.ts +95 -0
  21. package/dist/computation.d.ts.map +1 -0
  22. package/dist/computation.js +248 -0
  23. package/dist/debug/copy-texture-to-image.d.ts +26 -0
  24. package/dist/debug/copy-texture-to-image.d.ts.map +1 -0
  25. package/dist/debug/copy-texture-to-image.js +43 -0
  26. package/dist/debug/debug-framebuffer.d.ts +11 -0
  27. package/dist/debug/debug-framebuffer.d.ts.map +1 -0
  28. package/dist/debug/debug-framebuffer.js +46 -0
  29. package/dist/debug/debug-shader-layout.d.ts +9 -0
  30. package/dist/debug/debug-shader-layout.d.ts.map +1 -0
  31. package/dist/debug/debug-shader-layout.js +27 -0
  32. package/dist/debug/pixel-data-utils.d.ts +24 -0
  33. package/dist/debug/pixel-data-utils.d.ts.map +1 -0
  34. package/dist/debug/pixel-data-utils.js +39 -0
  35. package/dist/dist.dev.js +9592 -0
  36. package/dist/dist.min.js +102 -0
  37. package/dist/geometries/cone-geometry.d.ts +2 -2
  38. package/dist/geometries/cone-geometry.d.ts.map +1 -1
  39. package/dist/geometries/cone-geometry.js +13 -18
  40. package/dist/geometries/cube-geometry.d.ts +2 -2
  41. package/dist/geometries/cube-geometry.d.ts.map +1 -1
  42. package/dist/geometries/cube-geometry.js +192 -57
  43. package/dist/geometries/cylinder-geometry.d.ts +2 -2
  44. package/dist/geometries/cylinder-geometry.d.ts.map +1 -1
  45. package/dist/geometries/cylinder-geometry.js +11 -15
  46. package/dist/geometries/ico-sphere-geometry.d.ts +2 -2
  47. package/dist/geometries/ico-sphere-geometry.d.ts.map +1 -1
  48. package/dist/geometries/ico-sphere-geometry.js +143 -171
  49. package/dist/geometries/plane-geometry.d.ts +2 -2
  50. package/dist/geometries/plane-geometry.d.ts.map +1 -1
  51. package/dist/geometries/plane-geometry.js +95 -122
  52. package/dist/geometries/sphere-geometry.d.ts +2 -2
  53. package/dist/geometries/sphere-geometry.d.ts.map +1 -1
  54. package/dist/geometries/sphere-geometry.js +78 -101
  55. package/dist/geometries/truncated-cone-geometry.d.ts +2 -4
  56. package/dist/geometries/truncated-cone-geometry.d.ts.map +1 -1
  57. package/dist/geometries/truncated-cone-geometry.js +100 -134
  58. package/dist/geometry/geometry-table.d.ts +2 -2
  59. package/dist/geometry/geometry-table.d.ts.map +1 -1
  60. package/dist/geometry/geometry-table.js +3 -1
  61. package/dist/geometry/geometry-utils.d.ts.map +1 -1
  62. package/dist/geometry/geometry-utils.js +35 -41
  63. package/dist/geometry/geometry.d.ts +43 -43
  64. package/dist/geometry/geometry.d.ts.map +1 -1
  65. package/dist/geometry/geometry.js +82 -139
  66. package/dist/geometry/gpu-geometry.d.ts +37 -0
  67. package/dist/geometry/gpu-geometry.d.ts.map +1 -0
  68. package/dist/geometry/gpu-geometry.js +90 -0
  69. package/dist/geometry/gpu-table.d.ts +1 -0
  70. package/dist/geometry/gpu-table.d.ts.map +1 -0
  71. package/dist/geometry/gpu-table.js +42 -0
  72. package/dist/index.cjs +3444 -0
  73. package/dist/index.cjs.map +7 -0
  74. package/dist/index.d.ts +43 -24
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +29 -15
  77. package/dist/lib/clip-space.d.ts +8 -0
  78. package/dist/lib/clip-space.d.ts.map +1 -1
  79. package/dist/lib/clip-space.js +43 -2
  80. package/dist/lib/pipeline-factory.d.ts +17 -51
  81. package/dist/lib/pipeline-factory.d.ts.map +1 -1
  82. package/dist/lib/pipeline-factory.js +84 -209
  83. package/dist/lib/shader-factory.d.ts +17 -0
  84. package/dist/lib/shader-factory.d.ts.map +1 -0
  85. package/dist/lib/shader-factory.js +46 -0
  86. package/dist/model/model.d.ts +219 -0
  87. package/dist/model/model.d.ts.map +1 -0
  88. package/dist/model/model.js +659 -0
  89. package/dist/scenegraph/group-node.d.ts +21 -0
  90. package/dist/scenegraph/group-node.d.ts.map +1 -0
  91. package/dist/scenegraph/group-node.js +84 -0
  92. package/dist/scenegraph/model-node.d.ts +18 -0
  93. package/dist/scenegraph/model-node.d.ts.map +1 -0
  94. package/dist/scenegraph/model-node.js +35 -0
  95. package/dist/scenegraph/scenegraph-node.d.ts +56 -0
  96. package/dist/scenegraph/scenegraph-node.d.ts.map +1 -0
  97. package/dist/scenegraph/scenegraph-node.js +153 -0
  98. package/dist/shader-inputs.d.ts +63 -0
  99. package/dist/shader-inputs.d.ts.map +1 -0
  100. package/dist/shader-inputs.js +107 -0
  101. package/dist/transform/buffer-transform.d.ts +35 -0
  102. package/dist/transform/buffer-transform.d.ts.map +1 -0
  103. package/dist/transform/buffer-transform.js +70 -0
  104. package/dist/transform/texture-transform.d.ts +57 -0
  105. package/dist/transform/texture-transform.d.ts.map +1 -0
  106. package/dist/transform/texture-transform.js +117 -0
  107. package/dist.min.js +25 -0
  108. package/package.json +24 -14
  109. package/src/animation/timeline.ts +35 -34
  110. package/src/animation-loop/animation-loop-template.ts +25 -0
  111. package/src/{lib → animation-loop}/animation-loop.ts +114 -93
  112. package/src/{lib → animation-loop}/animation-props.ts +2 -2
  113. package/src/animation-loop/make-animation-loop.ts +53 -0
  114. package/src/computation.ts +346 -0
  115. package/src/debug/copy-texture-to-image.ts +70 -0
  116. package/src/debug/debug-framebuffer.ts +70 -0
  117. package/src/debug/debug-shader-layout.ts +38 -0
  118. package/src/debug/pixel-data-utils.ts +54 -0
  119. package/src/geometries/cone-geometry.ts +1 -1
  120. package/src/geometries/cube-geometry.ts +62 -56
  121. package/src/geometries/cylinder-geometry.ts +2 -2
  122. package/src/geometries/ico-sphere-geometry.ts +6 -5
  123. package/src/geometries/plane-geometry.ts +5 -4
  124. package/src/geometries/sphere-geometry.ts +4 -3
  125. package/src/geometries/truncated-cone-geometry.ts +6 -14
  126. package/src/geometry/geometry-table.ts +10 -7
  127. package/src/geometry/geometry-utils.ts +19 -3
  128. package/src/geometry/geometry.ts +68 -110
  129. package/src/geometry/gpu-geometry.ts +132 -0
  130. package/src/geometry/gpu-table.ts +41 -0
  131. package/src/index.ts +37 -10
  132. package/src/lib/clip-space.ts +32 -34
  133. package/src/lib/pipeline-factory.ts +83 -193
  134. package/src/lib/shader-factory.ts +57 -0
  135. package/src/model/model.ts +835 -0
  136. package/src/scenegraph/group-node.ts +107 -0
  137. package/src/scenegraph/model-node.ts +50 -0
  138. package/src/scenegraph/scenegraph-node.ts +204 -0
  139. package/src/shader-inputs.ts +157 -0
  140. package/src/transform/buffer-transform.ts +102 -0
  141. package/src/transform/texture-transform.ts +168 -0
  142. package/dist/animation/key-frames.js.map +0 -1
  143. package/dist/animation/timeline.js.map +0 -1
  144. package/dist/bundle.d.ts +0 -2
  145. package/dist/bundle.d.ts.map +0 -1
  146. package/dist/bundle.js +0 -5
  147. package/dist/bundle.js.map +0 -1
  148. package/dist/geometries/cone-geometry.js.map +0 -1
  149. package/dist/geometries/cube-geometry.js.map +0 -1
  150. package/dist/geometries/cylinder-geometry.js.map +0 -1
  151. package/dist/geometries/ico-sphere-geometry.js.map +0 -1
  152. package/dist/geometries/plane-geometry.js.map +0 -1
  153. package/dist/geometries/sphere-geometry.js.map +0 -1
  154. package/dist/geometries/truncated-cone-geometry.js.map +0 -1
  155. package/dist/geometry/geometry-table.js.map +0 -1
  156. package/dist/geometry/geometry-utils.js.map +0 -1
  157. package/dist/geometry/geometry.js.map +0 -1
  158. package/dist/geometry/primitive-utils.d.ts +0 -1
  159. package/dist/geometry/primitive-utils.d.ts.map +0 -1
  160. package/dist/geometry/primitive-utils.js +0 -2
  161. package/dist/geometry/primitive-utils.js.map +0 -1
  162. package/dist/index.js.map +0 -1
  163. package/dist/lib/animation-loop.d.ts.map +0 -1
  164. package/dist/lib/animation-loop.js +0 -480
  165. package/dist/lib/animation-loop.js.map +0 -1
  166. package/dist/lib/animation-props.d.ts.map +0 -1
  167. package/dist/lib/animation-props.js +0 -2
  168. package/dist/lib/animation-props.js.map +0 -1
  169. package/dist/lib/clip-space.js.map +0 -1
  170. package/dist/lib/model-utils.d.ts +0 -5
  171. package/dist/lib/model-utils.d.ts.map +0 -1
  172. package/dist/lib/model-utils.js +0 -45
  173. package/dist/lib/model-utils.js.map +0 -1
  174. package/dist/lib/model.d.ts +0 -41
  175. package/dist/lib/model.d.ts.map +0 -1
  176. package/dist/lib/model.js +0 -182
  177. package/dist/lib/model.js.map +0 -1
  178. package/dist/lib/pipeline-factory.js.map +0 -1
  179. package/dist/lib/render-loop.d.ts +0 -14
  180. package/dist/lib/render-loop.d.ts.map +0 -1
  181. package/dist/lib/render-loop.js +0 -49
  182. package/dist/lib/render-loop.js.map +0 -1
  183. package/src/bundle.ts +0 -4
  184. package/src/geometry/primitive-utils.ts +0 -30
  185. package/src/lib/model-utils.ts +0 -124
  186. package/src/lib/model.ts +0 -183
  187. package/src/lib/render-loop.ts +0 -58
@@ -1,53 +1,57 @@
1
- import {luma, Device, DeviceProps} from '@luma.gl/api';
2
- import {requestAnimationFrame, cancelAnimationFrame} from '@luma.gl/api';
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {luma, Device} from '@luma.gl/core';
6
+ import {requestAnimationFrame, cancelAnimationFrame} from '@luma.gl/core';
3
7
  import {Timeline} from '../animation/timeline';
4
- import {AnimationProps} from '../lib/animation-props';
8
+ import {AnimationProps} from './animation-props';
5
9
  import {Stats, Stat} from '@probe.gl/stats';
6
- import {isBrowser} from '@probe.gl/env';
7
-
8
- const isPage = isBrowser() && typeof document !== 'undefined';
9
10
 
10
11
  let statIdCounter = 0;
11
12
 
12
- type ContextProps = DeviceProps;
13
-
14
13
  /** AnimationLoop properties */
15
14
  export type AnimationLoopProps = {
16
- onCreateDevice?: (props: DeviceProps) => Promise<Device>;
15
+ device: Device | Promise<Device>;
16
+
17
17
  onAddHTML?: (div: HTMLDivElement) => string; // innerHTML
18
- onInitialize?: (animationProps: AnimationProps) => void;
19
- onRender?: (animationProps: AnimationProps) => void;
18
+ onInitialize?: (animationProps: AnimationProps) => Promise<unknown>;
19
+ onRender?: (animationProps: AnimationProps) => unknown;
20
20
  onFinalize?: (animationProps: AnimationProps) => void;
21
21
  onError?: (reason: Error) => void;
22
22
 
23
- device?: Device | null;
24
- deviceProps?: DeviceProps;
25
23
  stats?: Stats;
26
24
 
25
+ // view parameters - TODO move to CanvasContext?
26
+ autoResizeViewport?: boolean;
27
+ autoResizeDrawingBuffer?: boolean;
28
+ useDevicePixels?: number | boolean;
29
+ };
30
+
31
+ export type MutableAnimationLoopProps = {
27
32
  // view parameters
28
- debug?: boolean;
29
33
  autoResizeViewport?: boolean;
30
34
  autoResizeDrawingBuffer?: boolean;
31
35
  useDevicePixels?: number | boolean;
32
36
  };
33
37
 
34
38
  const DEFAULT_ANIMATION_LOOP_PROPS: Required<AnimationLoopProps> = {
35
- onCreateDevice: (props: DeviceProps): Promise<Device> => luma.createDevice(props),
39
+ device: null!,
40
+
36
41
  onAddHTML: () => '',
37
- onInitialize: () => ({}),
42
+ onInitialize: async () => {
43
+ return null;
44
+ },
38
45
  onRender: () => {},
39
46
  onFinalize: () => {},
40
- onError: (error) => console.error(error), // eslint-disable-line no-console
47
+ onError: error => console.error(error), // eslint-disable-line no-console
41
48
 
42
- device: null,
43
- deviceProps: {},
44
- debug: false,
45
49
  stats: luma.stats.get(`animation-loop-${statIdCounter++}`),
46
50
 
47
51
  // view parameters
48
52
  useDevicePixels: true,
49
- autoResizeViewport: true,
50
- autoResizeDrawingBuffer: true,
53
+ autoResizeViewport: false,
54
+ autoResizeDrawingBuffer: false
51
55
  };
52
56
 
53
57
  /** Convenient animation loop */
@@ -71,7 +75,7 @@ export class AnimationLoop {
71
75
  _running: boolean = false;
72
76
  _animationFrameId: any = null;
73
77
  _nextFramePromise: Promise<AnimationLoop> | null = null;
74
- _resolveNextFrame: ((AnimationLoop) => void) | null = null;
78
+ _resolveNextFrame: ((animationLoop: AnimationLoop) => void) | null = null;
75
79
  _cpuStartTime: number = 0;
76
80
 
77
81
  // _gpuTimeQuery: Query | null = null;
@@ -79,17 +83,17 @@ export class AnimationLoop {
79
83
  /*
80
84
  * @param {HTMLCanvasElement} canvas - if provided, width and height will be passed to context
81
85
  */
82
- constructor(props: AnimationLoopProps = {}) {
86
+ constructor(props: AnimationLoopProps) {
83
87
  this.props = {...DEFAULT_ANIMATION_LOOP_PROPS, ...props};
84
88
  props = this.props;
85
89
 
86
- let {useDevicePixels = true} = this.props;
90
+ if (!props.device) {
91
+ throw new Error('No device provided');
92
+ }
87
93
 
88
- // state
89
- this.device = props.device || null;
90
- // @ts-expect-error
91
- this.gl = (this.device && this.device.gl) || props.gl;
94
+ const {useDevicePixels = true} = this.props;
92
95
 
96
+ // state
93
97
  this.stats = props.stats || new Stats({id: 'animation-loop-stats'});
94
98
  this.cpuTime = this.stats.get('CPU Time');
95
99
  this.gpuTime = this.stats.get('GPU Time');
@@ -119,13 +123,14 @@ export class AnimationLoop {
119
123
  this.destroy();
120
124
  }
121
125
 
126
+ /** Flags this animation loop as needing redraw */
122
127
  setNeedsRedraw(reason: string): this {
123
128
  this.needsRedraw = this.needsRedraw || reason;
124
129
  return this;
125
130
  }
126
131
 
127
- // TODO - move to CanvasContext
128
- setProps(props: AnimationLoopProps): this {
132
+ /** TODO - move these props to CanvasContext? */
133
+ setProps(props: MutableAnimationLoopProps): this {
129
134
  if ('autoResizeViewport' in props) {
130
135
  this.props.autoResizeViewport = props.autoResizeViewport || false;
131
136
  }
@@ -146,16 +151,11 @@ export class AnimationLoop {
146
151
  this._running = true;
147
152
 
148
153
  try {
149
- // check that we haven't been stopped
150
- if (!this._running) {
151
- return null;
152
- }
153
-
154
154
  let appContext;
155
155
  if (!this._initialized) {
156
156
  this._initialized = true;
157
157
  // Create the WebGL context
158
- await this._createDevice();
158
+ await this._initDevice();
159
159
  this._initialize();
160
160
 
161
161
  // Note: onIntialize can return a promise (e.g. in case app needs to load resources)
@@ -176,20 +176,38 @@ export class AnimationLoop {
176
176
 
177
177
  return this;
178
178
  } catch (err: unknown) {
179
- const error = err instanceof Error ? err : new Error('Unknown error')
179
+ const error = err instanceof Error ? err : new Error('Unknown error');
180
180
  this.props.onError(error);
181
181
  // this._running = false; // TODO
182
182
  throw error;
183
183
  }
184
184
  }
185
185
 
186
+ /** Stops a render loop if already running, finalizing */
187
+ stop() {
188
+ // console.debug(`Stopping ${this.constructor.name}`);
189
+ if (this._running) {
190
+ // call callback
191
+ // If stop is called immediately, we can end up in a state where props haven't been initialized...
192
+ if (this.animationProps) {
193
+ this.props.onFinalize(this.animationProps);
194
+ }
195
+
196
+ this._cancelAnimationFrame();
197
+ this._nextFramePromise = null;
198
+ this._resolveNextFrame = null;
199
+ this._running = false;
200
+ }
201
+ return this;
202
+ }
203
+
186
204
  /** Explicitly draw a frame */
187
205
  redraw(): this {
188
206
  if (this.device?.isLost) {
189
207
  return this;
190
208
  }
191
209
 
192
- this._beginTimers();
210
+ this._beginFrameTimers();
193
211
 
194
212
  this._setupFrame();
195
213
  this._updateAnimationProps();
@@ -205,49 +223,35 @@ export class AnimationLoop {
205
223
  this._resolveNextFrame = null;
206
224
  }
207
225
 
208
- this._endTimers();
226
+ this._endFrameTimers();
209
227
 
210
228
  return this;
211
229
  }
212
230
 
213
- // Stops a render loop if already running, finalizing
214
- stop() {
215
- // console.debug(`Stopping ${this.constructor.name}`);
216
- if (this._running) {
217
- // call callback
218
- // If stop is called immediately, we can end up in a state where props haven't been initialized...
219
- if (this.animationProps) {
220
- this.props.onFinalize(this.animationProps);
221
- }
222
-
223
- this._cancelAnimationFrame();
224
- this._nextFramePromise = null;
225
- this._resolveNextFrame = null;
226
- this._running = false;
227
- }
228
- return this;
229
- }
230
-
231
+ /** Add a timeline, it will be automatically updated by the animation loop. */
231
232
  attachTimeline(timeline: Timeline): Timeline {
232
233
  this.timeline = timeline;
233
234
  return this.timeline;
234
235
  }
235
236
 
237
+ /** Remove a timeline */
236
238
  detachTimeline(): void {
237
239
  this.timeline = null;
238
240
  }
239
241
 
242
+ /** Wait until a render completes */
240
243
  waitForRender(): Promise<AnimationLoop> {
241
244
  this.setNeedsRedraw('waitForRender');
242
245
 
243
246
  if (!this._nextFramePromise) {
244
- this._nextFramePromise = new Promise((resolve) => {
247
+ this._nextFramePromise = new Promise(resolve => {
245
248
  this._resolveNextFrame = resolve;
246
249
  });
247
250
  }
248
251
  return this._nextFramePromise;
249
252
  }
250
253
 
254
+ /** TODO - should use device.deviceContext */
251
255
  async toDataURL(): Promise<string> {
252
256
  this.setNeedsRedraw('toDataURL');
253
257
  await this.waitForRender();
@@ -259,7 +263,7 @@ export class AnimationLoop {
259
263
 
260
264
  // PRIVATE METHODS
261
265
 
262
- _initialize() {
266
+ _initialize(): void {
263
267
  this._startEventHandling();
264
268
 
265
269
  // Initialize the callback data
@@ -273,9 +277,9 @@ export class AnimationLoop {
273
277
  // this._gpuTimeQuery = Query.isSupported(this.gl, ['timers']) ? new Query(this.gl) : null;
274
278
  }
275
279
 
276
- _setDisplay(display) {
280
+ _setDisplay(display: any): void {
277
281
  if (this.display) {
278
- this.display.delete();
282
+ this.display.destroy();
279
283
  this.display.animationLoop = null;
280
284
  }
281
285
 
@@ -287,7 +291,7 @@ export class AnimationLoop {
287
291
  this.display = display;
288
292
  }
289
293
 
290
- _requestAnimationFrame() {
294
+ _requestAnimationFrame(): void {
291
295
  if (!this._running) {
292
296
  return;
293
297
  }
@@ -301,8 +305,8 @@ export class AnimationLoop {
301
305
  this._animationFrameId = requestAnimationFrame(this._animationFrame.bind(this));
302
306
  }
303
307
 
304
- _cancelAnimationFrame() {
305
- if (this._animationFrameId !== null) {
308
+ _cancelAnimationFrame(): void {
309
+ if (this._animationFrameId === null) {
306
310
  return;
307
311
  }
308
312
 
@@ -312,11 +316,11 @@ export class AnimationLoop {
312
316
  // if (this.display && this.display.cancelAnimationFrame) {
313
317
  // this.display.cancelAnimationFrame(this._animationFrameId);
314
318
  // }
315
- cancelAnimationFrame(this._animationFrameId);
319
+ cancelAnimationFrame(this._animationFrameId);
316
320
  this._animationFrameId = null;
317
321
  }
318
322
 
319
- _animationFrame() {
323
+ _animationFrame(): void {
320
324
  if (!this._running) {
321
325
  return;
322
326
  }
@@ -326,36 +330,40 @@ export class AnimationLoop {
326
330
 
327
331
  // Called on each frame, can be overridden to call onRender multiple times
328
332
  // to support e.g. stereoscopic rendering
329
- _renderFrame(props: AnimationProps) {
333
+ _renderFrame(animationProps: AnimationProps): void {
330
334
  // Allow e.g. VR display to render multiple frames.
331
335
  if (this.display) {
332
- this.display._renderFrame(props);
336
+ this.display._renderFrame(animationProps);
333
337
  return;
334
338
  }
335
339
 
336
340
  // call callback
337
- this.props.onRender(props);
341
+ this.props.onRender(this._getAnimationProps());
338
342
  // end callback
343
+
344
+ // Submit commands (necessary on WebGPU)
345
+ this.device.submit();
339
346
  }
340
347
 
341
- _clearNeedsRedraw() {
348
+ _clearNeedsRedraw(): void {
342
349
  this.needsRedraw = false;
343
350
  }
344
351
 
345
- _setupFrame() {
352
+ _setupFrame(): void {
346
353
  this._resizeCanvasDrawingBuffer();
347
354
  this._resizeViewport();
348
355
  }
349
356
 
350
357
  // Initialize the object that will be passed to app callbacks
351
- _initializeAnimationProps() {
358
+ _initializeAnimationProps(): void {
352
359
  if (!this.device) {
353
360
  throw new Error('loop');
354
361
  }
355
362
  this.animationProps = {
356
363
  animationLoop: this,
364
+
357
365
  device: this.device,
358
- canvas: this.device?.canvasContext?.canvas!,
366
+ canvas: this.device?.canvasContext?.canvas,
359
367
  timeline: this.timeline,
360
368
 
361
369
  // Initial values
@@ -392,6 +400,7 @@ export class AnimationLoop {
392
400
  return;
393
401
  }
394
402
 
403
+ // Can this be replaced with canvas context?
395
404
  const {width, height, aspect} = this._getSizeAndAspect();
396
405
  if (width !== this.animationProps.width || height !== this.animationProps.height) {
397
406
  this.setNeedsRedraw('drawing buffer resized');
@@ -422,15 +431,17 @@ export class AnimationLoop {
422
431
  : this.animationProps.engineTime;
423
432
  }
424
433
 
425
- /** Either uses supplied or existing context, or calls provided callback to create one */
426
- async _createDevice() {
427
- const deviceProps = {...this.props, ...this.props.deviceProps};
428
- this.device = await this.props.onCreateDevice(deviceProps);
429
- this.canvas = this.device.canvasContext?.canvas!;
430
- this._createInfoDiv();
434
+ /** Wait for supplied device */
435
+ async _initDevice() {
436
+ this.device = await this.props.device;
437
+ if (!this.device) {
438
+ throw new Error('No device provided');
439
+ }
440
+ this.canvas = this.device.canvasContext?.canvas || null;
441
+ // this._createInfoDiv();
431
442
  }
432
443
 
433
- _createInfoDiv() {
444
+ _createInfoDiv(): void {
434
445
  if (this.canvas && this.props.onAddHTML) {
435
446
  const wrapperDiv = document.createElement('div');
436
447
  document.body.appendChild(wrapperDiv);
@@ -452,7 +463,7 @@ export class AnimationLoop {
452
463
  }
453
464
  }
454
465
 
455
- _getSizeAndAspect(): {width: number; height: number; aspect: number} {
466
+ _getSizeAndAspect(): {width: number; height: number; aspect: number} {
456
467
  if (!this.device) {
457
468
  return {width: 1, height: 1, aspect: 1};
458
469
  }
@@ -475,11 +486,19 @@ export class AnimationLoop {
475
486
  }
476
487
 
477
488
  /** Default viewport setup */
478
- _resizeViewport() {
489
+ _resizeViewport(): void {
490
+ // TODO can we use canvas context to code this in a portable way?
479
491
  // @ts-expect-error Expose on canvasContext
480
492
  if (this.props.autoResizeViewport && this.device.gl) {
481
493
  // @ts-expect-error Expose canvasContext
482
- this.device.gl.viewport(0, 0, this.device.gl.drawingBufferWidth, this.device.gl.drawingBufferHeight);
494
+ this.device.gl.viewport(
495
+ 0,
496
+ 0,
497
+ // @ts-expect-error Expose canvasContext
498
+ this.device.gl.drawingBufferWidth,
499
+ // @ts-expect-error Expose canvasContext
500
+ this.device.gl.drawingBufferHeight
501
+ );
483
502
  }
484
503
  }
485
504
 
@@ -487,13 +506,13 @@ export class AnimationLoop {
487
506
  * Resize the render buffer of the canvas to match canvas client size
488
507
  * Optionally multiplying with devicePixel ratio
489
508
  */
490
- _resizeCanvasDrawingBuffer() {
509
+ _resizeCanvasDrawingBuffer(): void {
491
510
  if (this.props.autoResizeDrawingBuffer) {
492
511
  this.device?.canvasContext?.resize({useDevicePixels: this.props.useDevicePixels});
493
512
  }
494
513
  }
495
514
 
496
- _beginTimers() {
515
+ _beginFrameTimers() {
497
516
  this.frameRate.timeEnd();
498
517
  this.frameRate.timeStart();
499
518
 
@@ -513,10 +532,10 @@ export class AnimationLoop {
513
532
  // this._gpuTimeQuery.beginTimeElapsedQuery();
514
533
  // }
515
534
 
516
- // this.cpuTime.timeStart();
535
+ this.cpuTime.timeStart();
517
536
  }
518
537
 
519
- _endTimers() {
538
+ _endFrameTimers() {
520
539
  this.cpuTime.timeEnd();
521
540
 
522
541
  // if (this._gpuTimeQuery) {
@@ -529,16 +548,18 @@ export class AnimationLoop {
529
548
 
530
549
  _startEventHandling() {
531
550
  if (this.canvas) {
532
- this.canvas.addEventListener('mousemove', this._onMousemove);
533
- this.canvas.addEventListener('mouseleave', this._onMouseleave);
551
+ this.canvas.addEventListener('mousemove', this._onMousemove.bind(this));
552
+ this.canvas.addEventListener('mouseleave', this._onMouseleave.bind(this));
534
553
  }
535
554
  }
536
555
 
537
- _onMousemove(e) {
538
- this._getAnimationProps()._mousePosition = [e.offsetX, e.offsetY];
556
+ _onMousemove(event: Event) {
557
+ if (event instanceof MouseEvent) {
558
+ this._getAnimationProps()._mousePosition = [event.offsetX, event.offsetY];
559
+ }
539
560
  }
540
561
 
541
- _onMouseleave(e) {
562
+ _onMouseleave(event: Event) {
542
563
  this._getAnimationProps()._mousePosition = null;
543
564
  }
544
565
  }
@@ -1,5 +1,5 @@
1
- import {Device} from '@luma.gl/api';
2
- import {Timeline} from '../animation/timeline'
1
+ import {Device} from '@luma.gl/core';
2
+ import {Timeline} from '../animation/timeline';
3
3
  import type {AnimationLoop} from './animation-loop';
4
4
 
5
5
  /** Properties passed to every render frame */
@@ -0,0 +1,53 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {luma} from '@luma.gl/core';
6
+ import {AnimationLoopTemplate} from './animation-loop-template';
7
+ import {AnimationLoop, AnimationLoopProps} from './animation-loop';
8
+ import type {AnimationProps} from './animation-props';
9
+
10
+ export type MakeAnimationLoopProps = Omit<
11
+ AnimationLoopProps,
12
+ 'onCreateDevice' | 'onInitialize' | 'onRedraw' | 'onFinalize'
13
+ >;
14
+
15
+ /** Instantiates and runs the render loop */
16
+ export function makeAnimationLoop(
17
+ AnimationLoopTemplateCtor: typeof AnimationLoopTemplate,
18
+ props?: MakeAnimationLoopProps
19
+ ): AnimationLoop {
20
+ let renderLoop: AnimationLoopTemplate | null = null;
21
+
22
+ const device = props?.device || luma.createDevice();
23
+
24
+ // Create an animation loop;
25
+ const animationLoop = new AnimationLoop({
26
+ ...props,
27
+
28
+ device,
29
+
30
+ async onInitialize(animationProps: AnimationProps): Promise<unknown> {
31
+ // @ts-expect-error abstract to prevent instantiation
32
+ renderLoop = new AnimationLoopTemplateCtor(animationProps);
33
+ // Any async loading can be handled here
34
+ return await renderLoop?.onInitialize(animationProps);
35
+ },
36
+
37
+ onRender: (animationProps: AnimationProps) => renderLoop?.onRender(animationProps),
38
+
39
+ onFinalize: (animationProps: AnimationProps) => renderLoop?.onFinalize(animationProps)
40
+ });
41
+
42
+ // @ts-expect-error Hack: adds info for the website to find
43
+ animationLoop.getInfo = () => {
44
+ // @ts-ignore
45
+ // eslint-disable-next-line no-invalid-this
46
+ return this.AnimationLoopTemplateCtor.info;
47
+ };
48
+
49
+ // Start the loop automatically
50
+ // animationLoop.start();
51
+
52
+ return animationLoop;
53
+ }