@luma.gl/engine 9.0.0-alpha.3 → 9.0.0-alpha.30

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 (148) hide show
  1. package/LICENSE +2 -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 +0 -20
  5. package/dist/animation/key-frames.js.map +1 -1
  6. package/dist/animation/timeline.d.ts +5 -5
  7. package/dist/animation/timeline.d.ts.map +1 -1
  8. package/dist/animation/timeline.js +0 -30
  9. package/dist/animation/timeline.js.map +1 -1
  10. package/dist/{lib → animation-loop}/animation-loop.d.ts +28 -29
  11. package/dist/animation-loop/animation-loop.d.ts.map +1 -0
  12. package/dist/{lib → animation-loop}/animation-loop.js +96 -175
  13. package/dist/animation-loop/animation-loop.js.map +1 -0
  14. package/dist/{lib → animation-loop}/animation-props.d.ts +7 -7
  15. package/dist/animation-loop/animation-props.d.ts.map +1 -0
  16. package/dist/animation-loop/animation-props.js.map +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 +28 -0
  20. package/dist/animation-loop/make-animation-loop.js.map +1 -0
  21. package/dist/animation-loop/render-loop.d.ts +23 -0
  22. package/dist/animation-loop/render-loop.d.ts.map +1 -0
  23. package/dist/animation-loop/render-loop.js +7 -0
  24. package/dist/animation-loop/render-loop.js.map +1 -0
  25. package/dist/dist.dev.js +14887 -0
  26. package/dist/geometries/cone-geometry.d.ts +1 -1
  27. package/dist/geometries/cone-geometry.d.ts.map +1 -1
  28. package/dist/geometries/cone-geometry.js +6 -5
  29. package/dist/geometries/cone-geometry.js.map +1 -1
  30. package/dist/geometries/cube-geometry.d.ts +2 -2
  31. package/dist/geometries/cube-geometry.d.ts.map +1 -1
  32. package/dist/geometries/cube-geometry.js +15 -8
  33. package/dist/geometries/cube-geometry.js.map +1 -1
  34. package/dist/geometries/cylinder-geometry.d.ts +1 -1
  35. package/dist/geometries/cylinder-geometry.d.ts.map +1 -1
  36. package/dist/geometries/cylinder-geometry.js +6 -5
  37. package/dist/geometries/cylinder-geometry.js.map +1 -1
  38. package/dist/geometries/ico-sphere-geometry.d.ts +2 -2
  39. package/dist/geometries/ico-sphere-geometry.d.ts.map +1 -1
  40. package/dist/geometries/ico-sphere-geometry.js +9 -18
  41. package/dist/geometries/ico-sphere-geometry.js.map +1 -1
  42. package/dist/geometries/plane-geometry.d.ts +2 -2
  43. package/dist/geometries/plane-geometry.d.ts.map +1 -1
  44. package/dist/geometries/plane-geometry.js +10 -19
  45. package/dist/geometries/plane-geometry.js.map +1 -1
  46. package/dist/geometries/sphere-geometry.d.ts +2 -2
  47. package/dist/geometries/sphere-geometry.d.ts.map +1 -1
  48. package/dist/geometries/sphere-geometry.js +9 -13
  49. package/dist/geometries/sphere-geometry.js.map +1 -1
  50. package/dist/geometries/truncated-cone-geometry.d.ts +2 -2
  51. package/dist/geometries/truncated-cone-geometry.d.ts.map +1 -1
  52. package/dist/geometries/truncated-cone-geometry.js +9 -14
  53. package/dist/geometries/truncated-cone-geometry.js.map +1 -1
  54. package/dist/geometry/geometry-table.d.ts +2 -2
  55. package/dist/geometry/geometry-table.d.ts.map +1 -1
  56. package/dist/geometry/geometry-table.js.map +1 -1
  57. package/dist/geometry/geometry-utils.d.ts.map +1 -1
  58. package/dist/geometry/geometry-utils.js +0 -9
  59. package/dist/geometry/geometry-utils.js.map +1 -1
  60. package/dist/geometry/geometry.d.ts +35 -58
  61. package/dist/geometry/geometry.d.ts.map +1 -1
  62. package/dist/geometry/geometry.js +26 -89
  63. package/dist/geometry/geometry.js.map +1 -1
  64. package/dist/geometry/primitive-utils.js.map +1 -1
  65. package/dist/index.cjs +2574 -0
  66. package/dist/index.d.ts +18 -9
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +20 -13
  69. package/dist/index.js.map +1 -1
  70. package/dist/lib/clip-space.d.ts +8 -0
  71. package/dist/lib/clip-space.d.ts.map +1 -1
  72. package/dist/lib/clip-space.js +36 -1
  73. package/dist/lib/clip-space.js.map +1 -1
  74. package/dist/lib/pipeline-factory.d.ts +19 -14
  75. package/dist/lib/pipeline-factory.d.ts.map +1 -1
  76. package/dist/lib/pipeline-factory.js +52 -63
  77. package/dist/lib/pipeline-factory.js.map +1 -1
  78. package/dist/{lib → model}/model-utils.d.ts +2 -2
  79. package/dist/model/model-utils.d.ts.map +1 -0
  80. package/dist/{lib → model}/model-utils.js +3 -8
  81. package/dist/model/model-utils.js.map +1 -0
  82. package/dist/model/model.d.ts +65 -0
  83. package/dist/model/model.d.ts.map +1 -0
  84. package/dist/{lib → model}/model.js +56 -75
  85. package/dist/model/model.js.map +1 -0
  86. package/dist/scenegraph/group-node.d.ts +21 -0
  87. package/dist/scenegraph/group-node.d.ts.map +1 -0
  88. package/dist/scenegraph/group-node.js +95 -0
  89. package/dist/scenegraph/group-node.js.map +1 -0
  90. package/dist/scenegraph/model-node.d.ts +18 -0
  91. package/dist/scenegraph/model-node.d.ts.map +1 -0
  92. package/dist/scenegraph/model-node.js +29 -0
  93. package/dist/scenegraph/model-node.js.map +1 -0
  94. package/dist/scenegraph/scenegraph-node.d.ts +56 -0
  95. package/dist/scenegraph/scenegraph-node.d.ts.map +1 -0
  96. package/dist/scenegraph/scenegraph-node.js +142 -0
  97. package/dist/scenegraph/scenegraph-node.js.map +1 -0
  98. package/dist/transform/transform.d.ts +98 -0
  99. package/dist/transform/transform.d.ts.map +1 -0
  100. package/dist/transform/transform.js +67 -0
  101. package/dist/transform/transform.js.map +1 -0
  102. package/dist.min.js +314 -0
  103. package/package.json +22 -12
  104. package/src/animation/timeline.ts +2 -2
  105. package/src/{lib → animation-loop}/animation-loop.ts +115 -97
  106. package/src/{lib → animation-loop}/animation-props.ts +6 -5
  107. package/src/animation-loop/make-animation-loop.ts +44 -0
  108. package/src/animation-loop/render-loop.ts +23 -0
  109. package/src/geometries/cone-geometry.ts +1 -1
  110. package/src/geometries/cube-geometry.ts +6 -3
  111. package/src/geometries/cylinder-geometry.ts +2 -2
  112. package/src/geometries/ico-sphere-geometry.ts +7 -6
  113. package/src/geometries/plane-geometry.ts +5 -4
  114. package/src/geometries/sphere-geometry.ts +4 -3
  115. package/src/geometries/truncated-cone-geometry.ts +4 -3
  116. package/src/geometry/geometry-table.ts +1 -1
  117. package/src/geometry/geometry-utils.ts +3 -3
  118. package/src/geometry/geometry.ts +72 -115
  119. package/src/index.ts +28 -12
  120. package/src/lib/clip-space.ts +17 -15
  121. package/src/lib/pipeline-factory.ts +60 -51
  122. package/src/{lib → model}/model-utils.ts +5 -4
  123. package/src/model/model.ts +226 -0
  124. package/src/scenegraph/group-node.ts +103 -0
  125. package/src/scenegraph/model-node.ts +50 -0
  126. package/src/scenegraph/scenegraph-node.ts +204 -0
  127. package/src/transform/transform.ts +246 -0
  128. package/dist/bundle.d.ts +0 -2
  129. package/dist/bundle.d.ts.map +0 -1
  130. package/dist/bundle.js +0 -5
  131. package/dist/bundle.js.map +0 -1
  132. package/dist/lib/animation-loop.d.ts.map +0 -1
  133. package/dist/lib/animation-loop.js.map +0 -1
  134. package/dist/lib/animation-props.d.ts.map +0 -1
  135. package/dist/lib/animation-props.js.map +0 -1
  136. package/dist/lib/model-utils.d.ts.map +0 -1
  137. package/dist/lib/model-utils.js.map +0 -1
  138. package/dist/lib/model.d.ts +0 -41
  139. package/dist/lib/model.d.ts.map +0 -1
  140. package/dist/lib/model.js.map +0 -1
  141. package/dist/lib/render-loop.d.ts +0 -14
  142. package/dist/lib/render-loop.d.ts.map +0 -1
  143. package/dist/lib/render-loop.js +0 -49
  144. package/dist/lib/render-loop.js.map +0 -1
  145. package/src/bundle.ts +0 -4
  146. package/src/lib/model.ts +0 -179
  147. package/src/lib/render-loop.ts +0 -58
  148. /package/dist/{lib → animation-loop}/animation-props.js +0 -0
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@luma.gl/engine",
3
- "version": "9.0.0-alpha.3",
3
+ "version": "9.0.0-alpha.30",
4
4
  "description": "WebGL2 Components for High Performance Rendering and Computation",
5
+ "type": "module",
5
6
  "license": "MIT",
6
7
  "publishConfig": {
7
8
  "access": "public"
@@ -16,27 +17,36 @@
16
17
  "animation",
17
18
  "3d"
18
19
  ],
19
- "types": "src/index.ts",
20
- "main": "dist/index.js",
20
+ "types": "dist/index.d.ts",
21
+ "main": "dist/index.cjs",
21
22
  "module": "dist/index.js",
23
+ "exports": {
24
+ ".": {
25
+ "import": "./dist/index.js",
26
+ "require": "./dist/index.cjs",
27
+ "types": "./dist/index.d.ts"
28
+ }
29
+ },
22
30
  "files": [
23
31
  "src",
24
32
  "dist",
33
+ "dist.min.js",
25
34
  "README.md"
26
35
  ],
27
36
  "sideEffects": false,
28
37
  "scripts": {
29
- "pre-build": "npm run build-bundle",
30
- "build-bundle": "webpack --display=minimal --config ../../scripts/bundle.config.js"
38
+ "build-bundle": "ocular-bundle ./src/index.ts",
39
+ "pre-build": "npm run build-bundle && npm run build-bundle -- --env=dev"
31
40
  },
32
41
  "dependencies": {
33
42
  "@babel/runtime": "^7.0.0",
34
- "@luma.gl/constants": "9.0.0-alpha.3",
35
- "@luma.gl/shadertools": "9.0.0-alpha.3",
36
- "@luma.gl/webgl": "9.0.0-alpha.3",
37
- "@math.gl/core": "^3.5.0",
38
- "@probe.gl/log": "^3.5.0",
39
- "@probe.gl/stats": "^3.5.0"
43
+ "@luma.gl/constants": "9.0.0-alpha.30",
44
+ "@luma.gl/core": "9.0.0-alpha.30",
45
+ "@luma.gl/shadertools": "9.0.0-alpha.30",
46
+ "@luma.gl/webgl": "9.0.0-alpha.30",
47
+ "@math.gl/core": "4.0.0-alpha.4",
48
+ "@probe.gl/log": "^4.0.2",
49
+ "@probe.gl/stats": "^4.0.2"
40
50
  },
41
- "gitHead": "3f259d0de774c6b98dd5ded61e64a0bd9f58b61e"
51
+ "gitHead": "7fb163f20d3400d59b59a17d36b4f3c466c559ba"
42
52
  }
@@ -7,7 +7,7 @@
7
7
  * @param rate = 1
8
8
  * @param repeat = 1
9
9
  */
10
- export type ChannelOptions = {
10
+ export type ChannelOptions = {
11
11
  delay?: number
12
12
  duration?: number
13
13
  rate?: number
@@ -27,7 +27,7 @@ export type AnimationOptions = {
27
27
  }
28
28
 
29
29
  type Animation = {
30
- channel: number;
30
+ channel?: number;
31
31
  animation: {
32
32
  setTime: (time: number) => void
33
33
  }
@@ -1,63 +1,64 @@
1
- import {luma, Device, DeviceProps} from '@luma.gl/api';
2
- import {requestAnimationFrame, cancelAnimationFrame} from '@luma.gl/api';
1
+ // luma.gl, MIT license
2
+
3
+ import {luma, Device} from '@luma.gl/core';
4
+ import {requestAnimationFrame, cancelAnimationFrame} from '@luma.gl/core';
3
5
  import {Timeline} from '../animation/timeline';
4
- import {AnimationProps} from '../lib/animation-props';
6
+ import {AnimationProps} from './animation-props';
5
7
  import {Stats, Stat} from '@probe.gl/stats';
6
- import {isBrowser} from '@probe.gl/env';
7
-
8
- const isPage = isBrowser() && typeof document !== 'undefined';
9
8
 
10
9
  let statIdCounter = 0;
11
10
 
12
- type ContextProps = DeviceProps;
13
-
14
11
  /** AnimationLoop properties */
15
12
  export type AnimationLoopProps = {
16
- onCreateDevice?: (props: DeviceProps) => Promise<Device>;
13
+ device: Device | Promise<Device>;
14
+
17
15
  onAddHTML?: (div: HTMLDivElement) => string; // innerHTML
18
- onInitialize?: (animationProps: AnimationProps) => void;
19
- onRender?: (animationProps: AnimationProps) => void;
16
+ onInitialize?: (animationProps: AnimationProps) => Promise<unknown>;
17
+ onRender?: (animationProps: AnimationProps) => unknown;
20
18
  onFinalize?: (animationProps: AnimationProps) => void;
21
19
  onError?: (reason: Error) => void;
22
20
 
23
- device?: Device;
24
- deviceProps?: DeviceProps;
25
21
  stats?: Stats;
26
22
 
27
- // view parameters
28
- debug?: boolean;
23
+ // view parameters - TODO move to CanvasContext?
29
24
  autoResizeViewport?: boolean;
30
25
  autoResizeDrawingBuffer?: boolean;
31
26
  useDevicePixels?: number | boolean;
32
27
  };
33
28
 
29
+ export type MutableAnimationLoopProps = {
30
+ // view parameters
31
+ autoResizeViewport?: boolean;
32
+ autoResizeDrawingBuffer?: boolean;
33
+ useDevicePixels?: number | boolean;
34
+ }
35
+
36
+
34
37
  const DEFAULT_ANIMATION_LOOP_PROPS: Required<AnimationLoopProps> = {
35
- onCreateDevice: (props: DeviceProps): Promise<Device> => luma.createDevice(props),
36
- onAddHTML: undefined,
37
- onInitialize: () => ({}),
38
+ device: null!,
39
+
40
+ onAddHTML: () => '',
41
+ onInitialize: async () => { return null; },
38
42
  onRender: () => {},
39
43
  onFinalize: () => {},
40
44
  onError: (error) => console.error(error), // eslint-disable-line no-console
41
45
 
42
- device: undefined,
43
- deviceProps: {},
44
- debug: false,
45
46
  stats: luma.stats.get(`animation-loop-${statIdCounter++}`),
46
47
 
47
48
  // view parameters
48
49
  useDevicePixels: true,
49
- autoResizeViewport: true,
50
- autoResizeDrawingBuffer: true,
50
+ autoResizeViewport: false,
51
+ autoResizeDrawingBuffer: false,
51
52
  };
52
53
 
53
54
  /** Convenient animation loop */
54
- export default class AnimationLoop {
55
- device: Device;
56
- canvas: HTMLCanvasElement; // | OffscreenCanvas;
55
+ export class AnimationLoop {
56
+ device: Device | null = null;
57
+ canvas: HTMLCanvasElement | OffscreenCanvas | null = null;
57
58
 
58
59
  props: Required<AnimationLoopProps>;
59
- animationProps: AnimationProps;
60
- timeline: Timeline = null;
60
+ animationProps: AnimationProps | null = null;
61
+ timeline: Timeline | null = null;
61
62
  stats: Stats;
62
63
  cpuTime: Stat;
63
64
  gpuTime: Stat;
@@ -65,13 +66,13 @@ export default class AnimationLoop {
65
66
 
66
67
  display: any;
67
68
 
68
- needsRedraw: string | null = 'initialized';
69
+ needsRedraw: string | false = 'initialized';
69
70
 
70
71
  _initialized: boolean = false;
71
72
  _running: boolean = false;
72
- _animationFrameId = null;
73
+ _animationFrameId: any = null;
73
74
  _nextFramePromise: Promise<AnimationLoop> | null = null;
74
- _resolveNextFrame: ((AnimationLoop) => void) | null = null;
75
+ _resolveNextFrame: ((animationLoop: AnimationLoop) => void) | null = null;
75
76
  _cpuStartTime: number = 0;
76
77
 
77
78
  // _gpuTimeQuery: Query | null = null;
@@ -79,18 +80,18 @@ export default class AnimationLoop {
79
80
  /*
80
81
  * @param {HTMLCanvasElement} canvas - if provided, width and height will be passed to context
81
82
  */
82
- constructor(props: AnimationLoopProps = {}) {
83
+ constructor(props: AnimationLoopProps) {
83
84
  this.props = {...DEFAULT_ANIMATION_LOOP_PROPS, ...props};
84
85
  props = this.props;
85
86
 
86
- let {useDevicePixels = true} = this.props;
87
+ if (!props.device) {
88
+ throw new Error('No device provided');
89
+ }
87
90
 
88
- // state
89
- this.device = props.device;
90
- // @ts-expect-error
91
- this.gl = (this.device && this.device.gl) || props.gl;
91
+ const {useDevicePixels = true} = this.props;
92
92
 
93
- this.stats = props.stats;
93
+ // state
94
+ this.stats = props.stats || new Stats({id: 'animation-loop-stats'});
94
95
  this.cpuTime = this.stats.get('CPU Time');
95
96
  this.gpuTime = this.stats.get('GPU Time');
96
97
  this.frameRate = this.stats.get('Frame Rate');
@@ -125,15 +126,15 @@ export default class AnimationLoop {
125
126
  }
126
127
 
127
128
  // TODO - move to CanvasContext
128
- setProps(props: AnimationLoopProps): this {
129
+ setProps(props: MutableAnimationLoopProps): this {
129
130
  if ('autoResizeViewport' in props) {
130
- this.props.autoResizeViewport = props.autoResizeViewport;
131
+ this.props.autoResizeViewport = props.autoResizeViewport || false;
131
132
  }
132
133
  if ('autoResizeDrawingBuffer' in props) {
133
- this.props.autoResizeDrawingBuffer = props.autoResizeDrawingBuffer;
134
+ this.props.autoResizeDrawingBuffer = props.autoResizeDrawingBuffer || false;
134
135
  }
135
136
  if ('useDevicePixels' in props) {
136
- this.props.useDevicePixels = props.useDevicePixels;
137
+ this.props.useDevicePixels = props.useDevicePixels || false;
137
138
  }
138
139
  return this;
139
140
  }
@@ -155,11 +156,11 @@ export default class AnimationLoop {
155
156
  if (!this._initialized) {
156
157
  this._initialized = true;
157
158
  // Create the WebGL context
158
- await this._createDevice();
159
+ await this._initDevice();
159
160
  this._initialize();
160
161
 
161
162
  // Note: onIntialize can return a promise (e.g. in case app needs to load resources)
162
- await this.onInitialize(this.animationProps);
163
+ await this.props.onInitialize(this._getAnimationProps());
163
164
  }
164
165
 
165
166
  // check that we haven't been stopped
@@ -185,16 +186,16 @@ export default class AnimationLoop {
185
186
 
186
187
  /** Explicitly draw a frame */
187
188
  redraw(): this {
188
- if (this.device.isLost) {
189
+ if (this.device?.isLost) {
189
190
  return this;
190
191
  }
191
192
 
192
193
  this._beginTimers();
193
194
 
194
195
  this._setupFrame();
195
- this._updateCallbackData();
196
+ this._updateAnimationProps();
196
197
 
197
- this._renderFrame(this.animationProps);
198
+ this._renderFrame(this._getAnimationProps());
198
199
 
199
200
  // clear needsRedraw flag
200
201
  this._clearNeedsRedraw();
@@ -215,7 +216,10 @@ export default class AnimationLoop {
215
216
  // console.debug(`Stopping ${this.constructor.name}`);
216
217
  if (this._running) {
217
218
  // call callback
218
- this.onFinalize(this.animationProps);
219
+ // If stop is called immediately, we can end up in a state where props haven't been initialized...
220
+ if (this.animationProps) {
221
+ this.props.onFinalize(this.animationProps);
222
+ }
219
223
 
220
224
  this._cancelAnimationFrame();
221
225
  this._nextFramePromise = null;
@@ -245,26 +249,13 @@ export default class AnimationLoop {
245
249
  return this._nextFramePromise;
246
250
  }
247
251
 
248
- async toDataURL() {
252
+ async toDataURL(): Promise<string> {
249
253
  this.setNeedsRedraw('toDataURL');
250
254
  await this.waitForRender();
251
- return this.canvas.toDataURL();
252
- }
253
-
254
- onCreateDevice(deviceProps: DeviceProps): Promise<Device> {
255
- return this.props.onCreateDevice(deviceProps);
256
- }
257
-
258
- onInitialize(animationProps: AnimationProps): {} | void {
259
- return this.props.onInitialize(animationProps);
260
- }
261
-
262
- onRender(animationProps: AnimationProps) {
263
- return this.props.onRender(animationProps);
264
- }
265
-
266
- onFinalize(animationProps: AnimationProps) {
267
- return this.props.onFinalize(animationProps);
255
+ if (this.canvas instanceof HTMLCanvasElement) {
256
+ return this.canvas.toDataURL();
257
+ }
258
+ throw new Error('OffscreenCanvas');
268
259
  }
269
260
 
270
261
  // PRIVATE METHODS
@@ -273,8 +264,8 @@ export default class AnimationLoop {
273
264
  this._startEventHandling();
274
265
 
275
266
  // Initialize the callback data
276
- this._initializeCallbackData();
277
- this._updateCallbackData();
267
+ this._initializeAnimationProps();
268
+ this._updateAnimationProps();
278
269
 
279
270
  // Default viewport setup, in case onInitialize wants to render
280
271
  this._resizeCanvasDrawingBuffer();
@@ -283,9 +274,9 @@ export default class AnimationLoop {
283
274
  // this._gpuTimeQuery = Query.isSupported(this.gl, ['timers']) ? new Query(this.gl) : null;
284
275
  }
285
276
 
286
- _setDisplay(display) {
277
+ _setDisplay(display: any) {
287
278
  if (this.display) {
288
- this.display.delete();
279
+ this.display.destroy();
289
280
  this.display.animationLoop = null;
290
281
  }
291
282
 
@@ -322,7 +313,7 @@ export default class AnimationLoop {
322
313
  // if (this.display && this.display.cancelAnimationFrame) {
323
314
  // this.display.cancelAnimationFrame(this._animationFrameId);
324
315
  // }
325
- cancelAnimationFrame(this._animationFrameId);
316
+ cancelAnimationFrame(this._animationFrameId);
326
317
  this._animationFrameId = null;
327
318
  }
328
319
 
@@ -336,20 +327,20 @@ export default class AnimationLoop {
336
327
 
337
328
  // Called on each frame, can be overridden to call onRender multiple times
338
329
  // to support e.g. stereoscopic rendering
339
- _renderFrame(props: AnimationProps) {
330
+ _renderFrame(animationProps: AnimationProps) {
340
331
  // Allow e.g. VR display to render multiple frames.
341
332
  if (this.display) {
342
- this.display._renderFrame(props);
333
+ this.display._renderFrame(animationProps);
343
334
  return;
344
335
  }
345
336
 
346
337
  // call callback
347
- this.onRender(props);
338
+ this.props.onRender(this._getAnimationProps());
348
339
  // end callback
349
340
  }
350
341
 
351
342
  _clearNeedsRedraw() {
352
- this.needsRedraw = null;
343
+ this.needsRedraw = false;
353
344
  }
354
345
 
355
346
  _setupFrame() {
@@ -358,16 +349,21 @@ export default class AnimationLoop {
358
349
  }
359
350
 
360
351
  // Initialize the object that will be passed to app callbacks
361
- _initializeCallbackData() {
352
+ _initializeAnimationProps() {
353
+ if (!this.device) {
354
+ throw new Error('loop');
355
+ }
362
356
  this.animationProps = {
363
357
  animationLoop: this,
358
+
364
359
  device: this.device,
365
- canvas: this.device.canvasContext.canvas,
360
+ canvas: this.device?.canvasContext?.canvas,
361
+ renderPass: this.device.getDefaultRenderPass(),
366
362
  timeline: this.timeline,
367
363
 
368
364
  // Initial values
369
365
  useDevicePixels: this.props.useDevicePixels,
370
- needsRedraw: null,
366
+ needsRedraw: false,
371
367
 
372
368
  // Placeholders
373
369
  width: 1,
@@ -386,8 +382,21 @@ export default class AnimationLoop {
386
382
  };
387
383
  }
388
384
 
385
+ _getAnimationProps(): AnimationProps {
386
+ if (!this.animationProps) {
387
+ throw new Error('animationProps');
388
+ }
389
+ return this.animationProps;
390
+ }
391
+
389
392
  // Update the context object that will be passed to app callbacks
390
- _updateCallbackData() {
393
+ _updateAnimationProps(): void {
394
+ if (!this.animationProps) {
395
+ return;
396
+ }
397
+
398
+ this.animationProps.renderPass = this.device.getDefaultRenderPass();
399
+
391
400
  const {width, height, aspect} = this._getSizeAndAspect();
392
401
  if (width !== this.animationProps.width || height !== this.animationProps.height) {
393
402
  this.setNeedsRedraw('drawing buffer resized');
@@ -418,13 +427,14 @@ export default class AnimationLoop {
418
427
  : this.animationProps.engineTime;
419
428
  }
420
429
 
421
- /** Either uses supplied or existing context, or calls provided callback to create one */
422
- async _createDevice() {
423
- const deviceProps = {...this.props, ...this.props.deviceProps};
424
- this.device = await this.onCreateDevice(deviceProps);
425
- // @ts-expect-error
426
- this.canvas = this.device.canvasContext.canvas;
427
- this._createInfoDiv();
430
+ /** Wait for supplied device */
431
+ async _initDevice() {
432
+ this.device = await this.props.device;
433
+ if (!this.device) {
434
+ throw new Error('No device provided');
435
+ }
436
+ this.canvas = this.device.canvasContext?.canvas || null;
437
+ // this._createInfoDiv();
428
438
  }
429
439
 
430
440
  _createInfoDiv() {
@@ -438,7 +448,9 @@ export default class AnimationLoop {
438
448
  div.style.bottom = '10px';
439
449
  div.style.width = '300px';
440
450
  div.style.background = 'white';
441
- wrapperDiv.appendChild(this.canvas);
451
+ if (this.canvas instanceof HTMLCanvasElement) {
452
+ wrapperDiv.appendChild(this.canvas);
453
+ }
442
454
  wrapperDiv.appendChild(div);
443
455
  const html = this.props.onAddHTML(div);
444
456
  if (html) {
@@ -447,13 +459,16 @@ export default class AnimationLoop {
447
459
  }
448
460
  }
449
461
 
450
- _getSizeAndAspect() {
462
+ _getSizeAndAspect(): {width: number; height: number; aspect: number} {
463
+ if (!this.device) {
464
+ return {width: 1, height: 1, aspect: 1};
465
+ }
451
466
  // https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
452
- const [width, height] = this.device.canvasContext.getPixelSize();
467
+ const [width, height] = this.device?.canvasContext?.getPixelSize() || [1, 1];
453
468
 
454
469
  // https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
455
470
  let aspect = 1;
456
- const canvas = this.device.canvasContext.canvas;
471
+ const canvas = this.device?.canvasContext?.canvas;
457
472
 
458
473
  // @ts-expect-error
459
474
  if (canvas && canvas.clientHeight) {
@@ -481,7 +496,7 @@ export default class AnimationLoop {
481
496
  */
482
497
  _resizeCanvasDrawingBuffer() {
483
498
  if (this.props.autoResizeDrawingBuffer) {
484
- this.device.canvasContext.resize({useDevicePixels: this.props.useDevicePixels});
499
+ this.device?.canvasContext?.resize({useDevicePixels: this.props.useDevicePixels});
485
500
  }
486
501
  }
487
502
 
@@ -521,15 +536,18 @@ export default class AnimationLoop {
521
536
 
522
537
  _startEventHandling() {
523
538
  if (this.canvas) {
524
- this.canvas.addEventListener('mousemove', this._onMousemove);
525
- this.canvas.addEventListener('mouseleave', this._onMouseleave);
539
+ this.canvas.addEventListener('mousemove', this._onMousemove.bind(this));
540
+ this.canvas.addEventListener('mouseleave', this._onMouseleave.bind(this));
526
541
  }
527
542
  }
528
543
 
529
- _onMousemove(e) {
530
- this.animationProps._mousePosition = [e.offsetX, e.offsetY];
544
+ _onMousemove(event: Event) {
545
+ if (event instanceof MouseEvent) {
546
+ this._getAnimationProps()._mousePosition = [event.offsetX, event.offsetY];
547
+ }
531
548
  }
532
- _onMouseleave(e) {
533
- this.animationProps._mousePosition = null;
549
+
550
+ _onMouseleave(event: Event) {
551
+ this._getAnimationProps()._mousePosition = null;
534
552
  }
535
553
  }
@@ -1,10 +1,11 @@
1
- import {Device} from '@luma.gl/api';
1
+ import {Device, RenderPass} from '@luma.gl/core';
2
2
  import {Timeline} from '../animation/timeline'
3
- import type AnimationLoop from './animation-loop';
3
+ import type {AnimationLoop} from './animation-loop';
4
4
 
5
5
  /** Properties passed to every render frame */
6
6
  export type AnimationProps = {
7
7
  device: Device;
8
+ renderPass: RenderPass;
8
9
  animationLoop: AnimationLoop;
9
10
 
10
11
  /** @todo Should be canvasContext */
@@ -22,10 +23,10 @@ export type AnimationProps = {
22
23
  tock: number;
23
24
 
24
25
  // Initial values
25
- needsRedraw?: string;
26
+ needsRedraw?: string | false;
26
27
 
27
- timeline: Timeline;
28
+ timeline: Timeline | null;
28
29
 
29
30
  // Experimental
30
- _mousePosition?: [number, number]; // [offsetX, offsetY],
31
+ _mousePosition?: [number, number] | null; // [offsetX, offsetY],
31
32
  };
@@ -0,0 +1,44 @@
1
+ // luma.gl, MIT license
2
+ import {luma} from '@luma.gl/core';
3
+ import {AnimationLoopTemplate} from './render-loop'
4
+ import {AnimationLoop, AnimationLoopProps} from './animation-loop'
5
+ import type {AnimationProps} from './animation-props';
6
+
7
+ export type MakeAnimationLoopProps = Omit<AnimationLoopProps, 'onCreateDevice' | 'onInitialize' | 'onRedraw' | 'onFinalize'>;
8
+
9
+ /** Instantiates and runs the render loop */
10
+ export function makeAnimationLoop(AnimationLoopTemplateCtor: typeof AnimationLoopTemplate, props?: MakeAnimationLoopProps): AnimationLoop {
11
+ let renderLoop: AnimationLoopTemplate | null = null;
12
+
13
+ const device = props?.device || luma.createDevice();
14
+
15
+ // Create an animation loop;
16
+ const animationLoop = new AnimationLoop({
17
+ ... props,
18
+
19
+ device,
20
+
21
+ async onInitialize(animationProps: AnimationProps): Promise<unknown> {
22
+ // @ts-expect-error abstract to prevent instantiation
23
+ renderLoop = new AnimationLoopTemplateCtor(animationProps);
24
+ // Any async loading can be handled here
25
+ return await renderLoop?.onInitialize(animationProps);
26
+ },
27
+
28
+ onRender: (animationProps: AnimationProps) => renderLoop?.onRender(animationProps),
29
+
30
+ onFinalize: (animationProps: AnimationProps) => renderLoop?.onFinalize(animationProps)
31
+ });
32
+
33
+ // @ts-expect-error Hack: adds info for the website to find
34
+ animationLoop.getInfo = () => {
35
+ // @ts-ignore
36
+ // eslint-disable-next-line no-invalid-this
37
+ return this.AnimationLoopTemplateCtor.info;
38
+ }
39
+
40
+ // Start the loop automatically
41
+ // animationLoop.start();
42
+
43
+ return animationLoop;
44
+ }
@@ -0,0 +1,23 @@
1
+ import type {AnimationProps} from './animation-props';
2
+
3
+ /**
4
+ * Minimal class that represents a "componentized" rendering life cycle
5
+ * (resource construction, repeated rendering, resource destruction)
6
+ *
7
+ * @note A motivation for this class compared to the raw animation loop is
8
+ * that it simplifies TypeScript code by allowing resources to be typed unconditionally
9
+ * since they are allocated in the constructor rather than in onInitialized
10
+ *
11
+ * @note Introduced in luma.gl v9
12
+ *
13
+ * @example AnimationLoopTemplate is intended to be subclassed,
14
+ * but the subclass should not be instantiated directly. Instead the subclass
15
+ * (i.e. the constructor of the subclass) should be used
16
+ * as an argument to create an AnimationLoop.
17
+ */
18
+ export abstract class AnimationLoopTemplate {
19
+ constructor(animationProps?: AnimationProps) {}
20
+ async onInitialize(animationProps: AnimationProps): Promise<unknown> { return null; }
21
+ abstract onRender(animationProps: AnimationProps): unknown;
22
+ abstract onFinalize(animationProps: AnimationProps): void;
23
+ }
@@ -1,4 +1,4 @@
1
- import {uid} from '@luma.gl/api';
1
+ import {uid} from '@luma.gl/core';
2
2
  import {TruncatedConeGeometry} from './truncated-cone-geometry';
3
3
 
4
4
  export type ConeGeometryProps = {
@@ -1,11 +1,11 @@
1
- import {uid} from '@luma.gl/api';
2
- import Geometry from '../geometry/geometry';
1
+ import {uid} from '@luma.gl/core';
2
+ import {Geometry} from '../geometry/geometry';
3
3
  // import type {GeometryType} from '../geometry/geometry-type';
4
4
 
5
5
  export type CubeGeometryProps = {
6
6
  id?: string;
7
7
  indices?: boolean;
8
- attributes?;
8
+ attributes?: any;
9
9
  };
10
10
 
11
11
  export class CubeGeometry extends Geometry {
@@ -14,11 +14,14 @@ export class CubeGeometry extends Geometry {
14
14
  super(indices ? {
15
15
  ...props,
16
16
  id,
17
+ topology: 'triangle-list',
17
18
  indices: {size: 1, value: CUBE_INDICES},
18
19
  attributes: {...ATTRIBUTES, ...props.attributes}
19
20
  } : {
20
21
  ...props,
21
22
  id,
23
+ topology: 'triangle-list',
24
+ indices: undefined,
22
25
  attributes: {...NON_INDEXED_ATTRIBUTES, ...props.attributes}
23
26
  });
24
27
  }
@@ -1,10 +1,10 @@
1
- import {uid} from '@luma.gl/api';
1
+ import {uid} from '@luma.gl/core';
2
2
  import {TruncatedConeGeometry} from './truncated-cone-geometry';
3
3
 
4
4
  export type CylinderGeometryProps = {
5
5
  id?: string;
6
6
  radius?: number;
7
- attributes?
7
+ attributes?: any;
8
8
  };
9
9
 
10
10
  export class CylinderGeometry extends TruncatedConeGeometry {