@luma.gl/engine 9.0.0-alpha.16 → 9.0.0-alpha.19

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 (188) hide show
  1. package/dist/animation/key-frames.d.ts +1 -1
  2. package/dist/animation/key-frames.d.ts.map +1 -1
  3. package/dist/animation/key-frames.js +55 -54
  4. package/dist/animation/key-frames.js.map +1 -0
  5. package/dist/animation/timeline.d.ts +4 -4
  6. package/dist/animation/timeline.d.ts.map +1 -1
  7. package/dist/animation/timeline.js +101 -94
  8. package/dist/animation/timeline.js.map +1 -0
  9. package/dist/animation-loop/animation-loop.d.ts +4 -2
  10. package/dist/animation-loop/animation-loop.d.ts.map +1 -1
  11. package/dist/animation-loop/animation-loop.js +358 -414
  12. package/dist/animation-loop/animation-loop.js.map +1 -0
  13. package/dist/animation-loop/animation-props.d.ts +3 -1
  14. package/dist/animation-loop/animation-props.d.ts.map +1 -1
  15. package/dist/animation-loop/animation-props.js +1 -0
  16. package/dist/animation-loop/animation-props.js.map +1 -0
  17. package/dist/animation-loop/make-animation-loop.d.ts +1 -1
  18. package/dist/animation-loop/make-animation-loop.d.ts.map +1 -1
  19. package/dist/animation-loop/make-animation-loop.js +25 -26
  20. package/dist/animation-loop/make-animation-loop.js.map +1 -0
  21. package/dist/animation-loop/render-loop.js +5 -17
  22. package/dist/animation-loop/render-loop.js.map +1 -0
  23. package/dist/dist.dev.js +12517 -0
  24. package/dist/geometries/cone-geometry.d.ts +1 -1
  25. package/dist/geometries/cone-geometry.d.ts.map +1 -1
  26. package/dist/geometries/cone-geometry.js +18 -12
  27. package/dist/geometries/cone-geometry.js.map +1 -0
  28. package/dist/geometries/cube-geometry.d.ts +1 -1
  29. package/dist/geometries/cube-geometry.d.ts.map +1 -1
  30. package/dist/geometries/cube-geometry.js +60 -187
  31. package/dist/geometries/cube-geometry.js.map +1 -0
  32. package/dist/geometries/cylinder-geometry.d.ts +1 -1
  33. package/dist/geometries/cylinder-geometry.d.ts.map +1 -1
  34. package/dist/geometries/cylinder-geometry.js +15 -10
  35. package/dist/geometries/cylinder-geometry.js.map +1 -0
  36. package/dist/geometries/ico-sphere-geometry.d.ts +1 -1
  37. package/dist/geometries/ico-sphere-geometry.d.ts.map +1 -1
  38. package/dist/geometries/ico-sphere-geometry.js +160 -141
  39. package/dist/geometries/ico-sphere-geometry.js.map +1 -0
  40. package/dist/geometries/plane-geometry.d.ts +1 -1
  41. package/dist/geometries/plane-geometry.d.ts.map +1 -1
  42. package/dist/geometries/plane-geometry.js +111 -93
  43. package/dist/geometries/plane-geometry.js.map +1 -0
  44. package/dist/geometries/sphere-geometry.d.ts +1 -1
  45. package/dist/geometries/sphere-geometry.d.ts.map +1 -1
  46. package/dist/geometries/sphere-geometry.js +95 -76
  47. package/dist/geometries/sphere-geometry.js.map +1 -0
  48. package/dist/geometries/truncated-cone-geometry.d.ts +1 -1
  49. package/dist/geometries/truncated-cone-geometry.d.ts.map +1 -1
  50. package/dist/geometries/truncated-cone-geometry.js +126 -105
  51. package/dist/geometries/truncated-cone-geometry.js.map +1 -0
  52. package/dist/geometry/geometry-table.d.ts +1 -1
  53. package/dist/geometry/geometry-table.d.ts.map +1 -1
  54. package/dist/geometry/geometry-table.js +1 -0
  55. package/dist/geometry/geometry-table.js.map +1 -0
  56. package/dist/geometry/geometry-utils.js +32 -22
  57. package/dist/geometry/geometry-utils.js.map +1 -0
  58. package/dist/geometry/geometry.d.ts +4 -4
  59. package/dist/geometry/geometry.d.ts.map +1 -1
  60. package/dist/geometry/geometry.js +109 -96
  61. package/dist/geometry/geometry.js.map +1 -0
  62. package/dist/geometry/primitive-utils.js +1 -30
  63. package/dist/geometry/primitive-utils.js.map +1 -0
  64. package/dist/index.cjs +2268 -0
  65. package/dist/index.d.ts +1 -0
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +17 -20
  68. package/dist/index.js.map +1 -0
  69. package/dist/lib/clip-space.d.ts +8 -0
  70. package/dist/lib/clip-space.d.ts.map +1 -1
  71. package/dist/lib/clip-space.js +32 -45
  72. package/dist/lib/clip-space.js.map +1 -0
  73. package/dist/lib/model-utils.js +28 -101
  74. package/dist/lib/model-utils.js.map +1 -0
  75. package/dist/lib/model.d.ts +1 -1
  76. package/dist/lib/model.d.ts.map +1 -1
  77. package/dist/lib/model.js +129 -121
  78. package/dist/lib/model.js.map +1 -0
  79. package/dist/lib/pipeline-factory.d.ts +3 -3
  80. package/dist/lib/pipeline-factory.d.ts.map +1 -1
  81. package/dist/lib/pipeline-factory.js +165 -136
  82. package/dist/lib/pipeline-factory.js.map +1 -0
  83. package/dist.min.js +295 -0
  84. package/package.json +22 -13
  85. package/src/animation/timeline.ts +1 -1
  86. package/src/animation-loop/animation-loop.ts +5 -5
  87. package/src/animation-loop/make-animation-loop.ts +2 -1
  88. package/src/geometry/geometry.ts +2 -2
  89. package/src/index.ts +1 -1
  90. package/src/lib/clip-space.ts +14 -11
  91. package/src/lib/pipeline-factory.ts +1 -1
  92. package/dist/bundle.d.ts +0 -2
  93. package/dist/bundle.d.ts.map +0 -1
  94. package/dist/bundle.js +0 -5
  95. package/dist/dist.min.js +0 -31
  96. package/dist/es5/animation/key-frames.js +0 -84
  97. package/dist/es5/animation/key-frames.js.map +0 -1
  98. package/dist/es5/animation/timeline.js +0 -183
  99. package/dist/es5/animation/timeline.js.map +0 -1
  100. package/dist/es5/animation-loop/animation-loop.js +0 -534
  101. package/dist/es5/animation-loop/animation-loop.js.map +0 -1
  102. package/dist/es5/animation-loop/animation-props.js +0 -2
  103. package/dist/es5/animation-loop/animation-props.js.map +0 -1
  104. package/dist/es5/animation-loop/make-animation-loop.js +0 -53
  105. package/dist/es5/animation-loop/make-animation-loop.js.map +0 -1
  106. package/dist/es5/animation-loop/render-loop.js +0 -39
  107. package/dist/es5/animation-loop/render-loop.js.map +0 -1
  108. package/dist/es5/bundle.js +0 -6
  109. package/dist/es5/bundle.js.map +0 -1
  110. package/dist/es5/geometries/cone-geometry.js +0 -43
  111. package/dist/es5/geometries/cone-geometry.js.map +0 -1
  112. package/dist/es5/geometries/cube-geometry.js +0 -84
  113. package/dist/es5/geometries/cube-geometry.js.map +0 -1
  114. package/dist/es5/geometries/cylinder-geometry.js +0 -39
  115. package/dist/es5/geometries/cylinder-geometry.js.map +0 -1
  116. package/dist/es5/geometries/ico-sphere-geometry.js +0 -185
  117. package/dist/es5/geometries/ico-sphere-geometry.js.map +0 -1
  118. package/dist/es5/geometries/plane-geometry.js +0 -137
  119. package/dist/es5/geometries/plane-geometry.js.map +0 -1
  120. package/dist/es5/geometries/sphere-geometry.js +0 -120
  121. package/dist/es5/geometries/sphere-geometry.js.map +0 -1
  122. package/dist/es5/geometries/truncated-cone-geometry.js +0 -160
  123. package/dist/es5/geometries/truncated-cone-geometry.js.map +0 -1
  124. package/dist/es5/geometry/geometry-table.js +0 -2
  125. package/dist/es5/geometry/geometry-table.js.map +0 -1
  126. package/dist/es5/geometry/geometry-utils.js +0 -39
  127. package/dist/es5/geometry/geometry-utils.js.map +0 -1
  128. package/dist/es5/geometry/geometry.js +0 -150
  129. package/dist/es5/geometry/geometry.js.map +0 -1
  130. package/dist/es5/geometry/primitive-utils.js +0 -2
  131. package/dist/es5/geometry/primitive-utils.js.map +0 -1
  132. package/dist/es5/index.js +0 -112
  133. package/dist/es5/index.js.map +0 -1
  134. package/dist/es5/lib/clip-space.js +0 -2
  135. package/dist/es5/lib/clip-space.js.map +0 -1
  136. package/dist/es5/lib/model-utils.js +0 -52
  137. package/dist/es5/lib/model-utils.js.map +0 -1
  138. package/dist/es5/lib/model.js +0 -173
  139. package/dist/es5/lib/model.js.map +0 -1
  140. package/dist/es5/lib/pipeline-factory.js +0 -244
  141. package/dist/es5/lib/pipeline-factory.js.map +0 -1
  142. package/dist/esm/animation/key-frames.js +0 -57
  143. package/dist/esm/animation/key-frames.js.map +0 -1
  144. package/dist/esm/animation/timeline.js +0 -113
  145. package/dist/esm/animation/timeline.js.map +0 -1
  146. package/dist/esm/animation-loop/animation-loop.js +0 -367
  147. package/dist/esm/animation-loop/animation-loop.js.map +0 -1
  148. package/dist/esm/animation-loop/animation-props.js +0 -2
  149. package/dist/esm/animation-loop/animation-props.js.map +0 -1
  150. package/dist/esm/animation-loop/make-animation-loop.js +0 -28
  151. package/dist/esm/animation-loop/make-animation-loop.js.map +0 -1
  152. package/dist/esm/animation-loop/render-loop.js +0 -7
  153. package/dist/esm/animation-loop/render-loop.js.map +0 -1
  154. package/dist/esm/bundle.js +0 -4
  155. package/dist/esm/bundle.js.map +0 -1
  156. package/dist/esm/geometries/cone-geometry.js +0 -21
  157. package/dist/esm/geometries/cone-geometry.js.map +0 -1
  158. package/dist/esm/geometries/cube-geometry.js +0 -67
  159. package/dist/esm/geometries/cube-geometry.js.map +0 -1
  160. package/dist/esm/geometries/cylinder-geometry.js +0 -18
  161. package/dist/esm/geometries/cylinder-geometry.js.map +0 -1
  162. package/dist/esm/geometries/ico-sphere-geometry.js +0 -170
  163. package/dist/esm/geometries/ico-sphere-geometry.js.map +0 -1
  164. package/dist/esm/geometries/plane-geometry.js +0 -119
  165. package/dist/esm/geometries/plane-geometry.js.map +0 -1
  166. package/dist/esm/geometries/sphere-geometry.js +0 -102
  167. package/dist/esm/geometries/sphere-geometry.js.map +0 -1
  168. package/dist/esm/geometries/truncated-cone-geometry.js +0 -136
  169. package/dist/esm/geometries/truncated-cone-geometry.js.map +0 -1
  170. package/dist/esm/geometry/geometry-table.js +0 -2
  171. package/dist/esm/geometry/geometry-table.js.map +0 -1
  172. package/dist/esm/geometry/geometry-utils.js +0 -37
  173. package/dist/esm/geometry/geometry-utils.js.map +0 -1
  174. package/dist/esm/geometry/geometry.js +0 -119
  175. package/dist/esm/geometry/geometry.js.map +0 -1
  176. package/dist/esm/geometry/primitive-utils.js +0 -2
  177. package/dist/esm/geometry/primitive-utils.js.map +0 -1
  178. package/dist/esm/index.js +0 -16
  179. package/dist/esm/index.js.map +0 -1
  180. package/dist/esm/lib/clip-space.js +0 -2
  181. package/dist/esm/lib/clip-space.js.map +0 -1
  182. package/dist/esm/lib/model-utils.js +0 -40
  183. package/dist/esm/lib/model-utils.js.map +0 -1
  184. package/dist/esm/lib/model.js +0 -146
  185. package/dist/esm/lib/model.js.map +0 -1
  186. package/dist/esm/lib/pipeline-factory.js +0 -180
  187. package/dist/esm/lib/pipeline-factory.js.map +0 -1
  188. package/src/bundle.ts +0 -4
@@ -1,423 +1,367 @@
1
- // luma.gl, MIT license
1
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
2
  import { luma } from '@luma.gl/api';
3
3
  import { requestAnimationFrame, cancelAnimationFrame } from '@luma.gl/api';
4
4
  import { Stats } from '@probe.gl/stats';
5
5
  let statIdCounter = 0;
6
6
  const DEFAULT_ANIMATION_LOOP_PROPS = {
7
- device: null,
8
- onAddHTML: () => '',
9
- onInitialize: async () => { return null; },
10
- onRender: () => { },
11
- onFinalize: () => { },
12
- onError: (error) => console.error(error),
13
- stats: luma.stats.get(`animation-loop-${statIdCounter++}`),
14
- // view parameters
15
- useDevicePixels: true,
16
- autoResizeViewport: false,
17
- autoResizeDrawingBuffer: false,
7
+ device: null,
8
+ onAddHTML: () => '',
9
+ onInitialize: async () => {
10
+ return null;
11
+ },
12
+ onRender: () => {},
13
+ onFinalize: () => {},
14
+ onError: error => console.error(error),
15
+ stats: luma.stats.get("animation-loop-".concat(statIdCounter++)),
16
+ useDevicePixels: true,
17
+ autoResizeViewport: false,
18
+ autoResizeDrawingBuffer: false
18
19
  };
19
- /** Convenient animation loop */
20
20
  export class AnimationLoop {
21
- // _gpuTimeQuery: Query | null = null;
22
- /*
23
- * @param {HTMLCanvasElement} canvas - if provided, width and height will be passed to context
24
- */
25
- constructor(props) {
26
- this.device = null;
27
- this.canvas = null;
28
- this.animationProps = null;
29
- this.timeline = null;
30
- this.needsRedraw = 'initialized';
31
- this._initialized = false;
32
- this._running = false;
33
- this._animationFrameId = null;
34
- this._nextFramePromise = null;
35
- this._resolveNextFrame = null;
36
- this._cpuStartTime = 0;
37
- this.props = { ...DEFAULT_ANIMATION_LOOP_PROPS, ...props };
38
- props = this.props;
39
- if (!props.device) {
40
- throw new Error('No device provided');
41
- }
42
- let { useDevicePixels = true } = this.props;
43
- // state
44
- this.stats = props.stats || new Stats({ id: 'animation-loop-stats' });
45
- this.cpuTime = this.stats.get('CPU Time');
46
- this.gpuTime = this.stats.get('GPU Time');
47
- this.frameRate = this.stats.get('Frame Rate');
48
- this.setProps({
49
- autoResizeViewport: props.autoResizeViewport,
50
- autoResizeDrawingBuffer: props.autoResizeDrawingBuffer,
51
- useDevicePixels
52
- });
53
- // Bind methods
54
- this.start = this.start.bind(this);
55
- this.stop = this.stop.bind(this);
56
- this._onMousemove = this._onMousemove.bind(this);
57
- this._onMouseleave = this._onMouseleave.bind(this);
58
- }
59
- destroy() {
60
- this.stop();
61
- this._setDisplay(null);
62
- }
63
- /** @deprecated Use .destroy() */
64
- delete() {
65
- this.destroy();
66
- }
67
- setNeedsRedraw(reason) {
68
- this.needsRedraw = this.needsRedraw || reason;
69
- return this;
70
- }
71
- // TODO - move to CanvasContext
72
- setProps(props) {
73
- if ('autoResizeViewport' in props) {
74
- this.props.autoResizeViewport = props.autoResizeViewport || false;
75
- }
76
- if ('autoResizeDrawingBuffer' in props) {
77
- this.props.autoResizeDrawingBuffer = props.autoResizeDrawingBuffer || false;
78
- }
79
- if ('useDevicePixels' in props) {
80
- this.props.useDevicePixels = props.useDevicePixels || false;
81
- }
82
- return this;
83
- }
84
- /** Starts a render loop if not already running */
85
- async start() {
86
- if (this._running) {
87
- return this;
88
- }
89
- this._running = true;
90
- try {
91
- // check that we haven't been stopped
92
- if (!this._running) {
93
- return null;
94
- }
95
- let appContext;
96
- if (!this._initialized) {
97
- this._initialized = true;
98
- // Create the WebGL context
99
- await this._initDevice();
100
- this._initialize();
101
- // Note: onIntialize can return a promise (e.g. in case app needs to load resources)
102
- await this.props.onInitialize(this._getAnimationProps());
103
- }
104
- // check that we haven't been stopped
105
- if (!this._running) {
106
- return null;
107
- }
108
- // Start the loop
109
- if (appContext !== false) {
110
- // cancel any pending renders to ensure only one loop can ever run
111
- this._cancelAnimationFrame();
112
- this._requestAnimationFrame();
113
- }
114
- return this;
115
- }
116
- catch (err) {
117
- const error = err instanceof Error ? err : new Error('Unknown error');
118
- this.props.onError(error);
119
- // this._running = false; // TODO
120
- throw error;
121
- }
122
- }
123
- /** Explicitly draw a frame */
124
- redraw() {
125
- if (this.device?.isLost) {
126
- return this;
127
- }
128
- this._beginTimers();
129
- this._setupFrame();
130
- this._updateAnimationProps();
131
- this._renderFrame(this._getAnimationProps());
132
- // clear needsRedraw flag
133
- this._clearNeedsRedraw();
134
- if (this._resolveNextFrame) {
135
- this._resolveNextFrame(this);
136
- this._nextFramePromise = null;
137
- this._resolveNextFrame = null;
138
- }
139
- this._endTimers();
140
- return this;
141
- }
142
- // Stops a render loop if already running, finalizing
143
- stop() {
144
- // console.debug(`Stopping ${this.constructor.name}`);
145
- if (this._running) {
146
- // call callback
147
- // If stop is called immediately, we can end up in a state where props haven't been initialized...
148
- if (this.animationProps) {
149
- this.props.onFinalize(this.animationProps);
150
- }
151
- this._cancelAnimationFrame();
152
- this._nextFramePromise = null;
153
- this._resolveNextFrame = null;
154
- this._running = false;
155
- }
156
- return this;
157
- }
158
- attachTimeline(timeline) {
159
- this.timeline = timeline;
160
- return this.timeline;
161
- }
162
- detachTimeline() {
163
- this.timeline = null;
164
- }
165
- waitForRender() {
166
- this.setNeedsRedraw('waitForRender');
167
- if (!this._nextFramePromise) {
168
- this._nextFramePromise = new Promise((resolve) => {
169
- this._resolveNextFrame = resolve;
170
- });
171
- }
172
- return this._nextFramePromise;
173
- }
174
- async toDataURL() {
175
- this.setNeedsRedraw('toDataURL');
176
- await this.waitForRender();
177
- if (this.canvas instanceof HTMLCanvasElement) {
178
- return this.canvas.toDataURL();
179
- }
180
- throw new Error('OffscreenCanvas');
181
- }
182
- // PRIVATE METHODS
183
- _initialize() {
184
- this._startEventHandling();
185
- // Initialize the callback data
186
- this._initializeAnimationProps();
187
- this._updateAnimationProps();
188
- // Default viewport setup, in case onInitialize wants to render
189
- this._resizeCanvasDrawingBuffer();
190
- this._resizeViewport();
191
- // this._gpuTimeQuery = Query.isSupported(this.gl, ['timers']) ? new Query(this.gl) : null;
192
- }
193
- _setDisplay(display) {
194
- if (this.display) {
195
- this.display.delete();
196
- this.display.animationLoop = null;
197
- }
198
- // store animation loop on the display
199
- if (display) {
200
- display.animationLoop = this;
201
- }
202
- this.display = display;
203
- }
204
- _requestAnimationFrame() {
205
- if (!this._running) {
206
- return;
207
- }
208
- // VR display has a separate animation frame to sync with headset
209
- // TODO WebVR API discontinued, replaced by WebXR: https://immersive-web.github.io/webxr/
210
- // See https://developer.mozilla.org/en-US/docs/Web/API/VRDisplay/requestAnimationFrame
211
- // if (this.display && this.display.requestAnimationFrame) {
212
- // this._animationFrameId = this.display.requestAnimationFrame(this._animationFrame.bind(this));
213
- // }
214
- this._animationFrameId = requestAnimationFrame(this._animationFrame.bind(this));
215
- }
216
- _cancelAnimationFrame() {
217
- if (this._animationFrameId !== null) {
218
- return;
219
- }
220
- // VR display has a separate animation frame to sync with headset
221
- // TODO WebVR API discontinued, replaced by WebXR: https://immersive-web.github.io/webxr/
222
- // See https://developer.mozilla.org/en-US/docs/Web/API/VRDisplay/requestAnimationFrame
223
- // if (this.display && this.display.cancelAnimationFrame) {
224
- // this.display.cancelAnimationFrame(this._animationFrameId);
225
- // }
226
- cancelAnimationFrame(this._animationFrameId);
227
- this._animationFrameId = null;
228
- }
229
- _animationFrame() {
230
- if (!this._running) {
231
- return;
232
- }
233
- this.redraw();
21
+ constructor(props) {
22
+ _defineProperty(this, "device", null);
23
+ _defineProperty(this, "canvas", null);
24
+ _defineProperty(this, "props", void 0);
25
+ _defineProperty(this, "animationProps", null);
26
+ _defineProperty(this, "timeline", null);
27
+ _defineProperty(this, "stats", void 0);
28
+ _defineProperty(this, "cpuTime", void 0);
29
+ _defineProperty(this, "gpuTime", void 0);
30
+ _defineProperty(this, "frameRate", void 0);
31
+ _defineProperty(this, "display", void 0);
32
+ _defineProperty(this, "needsRedraw", 'initialized');
33
+ _defineProperty(this, "_initialized", false);
34
+ _defineProperty(this, "_running", false);
35
+ _defineProperty(this, "_animationFrameId", null);
36
+ _defineProperty(this, "_nextFramePromise", null);
37
+ _defineProperty(this, "_resolveNextFrame", null);
38
+ _defineProperty(this, "_cpuStartTime", 0);
39
+ this.props = {
40
+ ...DEFAULT_ANIMATION_LOOP_PROPS,
41
+ ...props
42
+ };
43
+ props = this.props;
44
+ if (!props.device) {
45
+ throw new Error('No device provided');
46
+ }
47
+ const {
48
+ useDevicePixels = true
49
+ } = this.props;
50
+ this.stats = props.stats || new Stats({
51
+ id: 'animation-loop-stats'
52
+ });
53
+ this.cpuTime = this.stats.get('CPU Time');
54
+ this.gpuTime = this.stats.get('GPU Time');
55
+ this.frameRate = this.stats.get('Frame Rate');
56
+ this.setProps({
57
+ autoResizeViewport: props.autoResizeViewport,
58
+ autoResizeDrawingBuffer: props.autoResizeDrawingBuffer,
59
+ useDevicePixels
60
+ });
61
+ this.start = this.start.bind(this);
62
+ this.stop = this.stop.bind(this);
63
+ this._onMousemove = this._onMousemove.bind(this);
64
+ this._onMouseleave = this._onMouseleave.bind(this);
65
+ }
66
+ destroy() {
67
+ this.stop();
68
+ this._setDisplay(null);
69
+ }
70
+ delete() {
71
+ this.destroy();
72
+ }
73
+ setNeedsRedraw(reason) {
74
+ this.needsRedraw = this.needsRedraw || reason;
75
+ return this;
76
+ }
77
+ setProps(props) {
78
+ if ('autoResizeViewport' in props) {
79
+ this.props.autoResizeViewport = props.autoResizeViewport || false;
80
+ }
81
+ if ('autoResizeDrawingBuffer' in props) {
82
+ this.props.autoResizeDrawingBuffer = props.autoResizeDrawingBuffer || false;
83
+ }
84
+ if ('useDevicePixels' in props) {
85
+ this.props.useDevicePixels = props.useDevicePixels || false;
86
+ }
87
+ return this;
88
+ }
89
+ async start() {
90
+ if (this._running) {
91
+ return this;
92
+ }
93
+ this._running = true;
94
+ try {
95
+ if (!this._running) {
96
+ return null;
97
+ }
98
+ let appContext;
99
+ if (!this._initialized) {
100
+ this._initialized = true;
101
+ await this._initDevice();
102
+ this._initialize();
103
+ await this.props.onInitialize(this._getAnimationProps());
104
+ }
105
+ if (!this._running) {
106
+ return null;
107
+ }
108
+ if (appContext !== false) {
109
+ this._cancelAnimationFrame();
234
110
  this._requestAnimationFrame();
235
- }
236
- // Called on each frame, can be overridden to call onRender multiple times
237
- // to support e.g. stereoscopic rendering
238
- _renderFrame(animationProps) {
239
- // Allow e.g. VR display to render multiple frames.
240
- if (this.display) {
241
- this.display._renderFrame(animationProps);
242
- return;
243
- }
244
- // call callback
245
- this.props.onRender(this._getAnimationProps());
246
- // end callback
247
- }
248
- _clearNeedsRedraw() {
249
- this.needsRedraw = false;
250
- }
251
- _setupFrame() {
252
- this._resizeCanvasDrawingBuffer();
253
- this._resizeViewport();
254
- }
255
- // Initialize the object that will be passed to app callbacks
256
- _initializeAnimationProps() {
257
- if (!this.device) {
258
- throw new Error('loop');
259
- }
260
- this.animationProps = {
261
- animationLoop: this,
262
- device: this.device,
263
- canvas: this.device?.canvasContext?.canvas,
264
- timeline: this.timeline,
265
- // Initial values
266
- useDevicePixels: this.props.useDevicePixels,
267
- needsRedraw: false,
268
- // Placeholders
269
- width: 1,
270
- height: 1,
271
- aspect: 1,
272
- // Animation props
273
- time: 0,
274
- startTime: Date.now(),
275
- engineTime: 0,
276
- tick: 0,
277
- tock: 0,
278
- // Experimental
279
- _mousePosition: null // Event props
280
- };
281
- }
282
- _getAnimationProps() {
283
- if (!this.animationProps) {
284
- throw new Error('animationProps');
285
- }
286
- return this.animationProps;
287
- }
288
- // Update the context object that will be passed to app callbacks
289
- _updateAnimationProps() {
290
- if (!this.animationProps) {
291
- return;
292
- }
293
- const { width, height, aspect } = this._getSizeAndAspect();
294
- if (width !== this.animationProps.width || height !== this.animationProps.height) {
295
- this.setNeedsRedraw('drawing buffer resized');
296
- }
297
- if (aspect !== this.animationProps.aspect) {
298
- this.setNeedsRedraw('drawing buffer aspect changed');
299
- }
300
- this.animationProps.width = width;
301
- this.animationProps.height = height;
302
- this.animationProps.aspect = aspect;
303
- this.animationProps.needsRedraw = this.needsRedraw;
304
- // Update time properties
305
- this.animationProps.engineTime = Date.now() - this.animationProps.startTime;
306
- if (this.timeline) {
307
- this.timeline.update(this.animationProps.engineTime);
308
- }
309
- this.animationProps.tick = Math.floor((this.animationProps.time / 1000) * 60);
310
- this.animationProps.tock++;
311
- // For back compatibility
312
- this.animationProps.time = this.timeline
313
- ? this.timeline.getTime()
314
- : this.animationProps.engineTime;
315
- }
316
- /** Wait for supplied device */
317
- async _initDevice() {
318
- this.device = await this.props.device;
319
- if (!this.device) {
320
- throw new Error('No device provided');
321
- }
322
- this.canvas = this.device.canvasContext?.canvas || null;
323
- // this._createInfoDiv();
324
- }
325
- _createInfoDiv() {
326
- if (this.canvas && this.props.onAddHTML) {
327
- const wrapperDiv = document.createElement('div');
328
- document.body.appendChild(wrapperDiv);
329
- wrapperDiv.style.position = 'relative';
330
- const div = document.createElement('div');
331
- div.style.position = 'absolute';
332
- div.style.left = '10px';
333
- div.style.bottom = '10px';
334
- div.style.width = '300px';
335
- div.style.background = 'white';
336
- if (this.canvas instanceof HTMLCanvasElement) {
337
- wrapperDiv.appendChild(this.canvas);
338
- }
339
- wrapperDiv.appendChild(div);
340
- const html = this.props.onAddHTML(div);
341
- if (html) {
342
- div.innerHTML = html;
343
- }
344
- }
345
- }
346
- _getSizeAndAspect() {
347
- if (!this.device) {
348
- return { width: 1, height: 1, aspect: 1 };
349
- }
350
- // https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
351
- const [width, height] = this.device?.canvasContext?.getPixelSize() || [1, 1];
352
- // https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
353
- let aspect = 1;
354
- const canvas = this.device?.canvasContext?.canvas;
355
- // @ts-expect-error
356
- if (canvas && canvas.clientHeight) {
357
- // @ts-expect-error
358
- aspect = canvas.clientWidth / canvas.clientHeight;
359
- }
360
- else if (width > 0 && height > 0) {
361
- aspect = width / height;
362
- }
363
- return { width, height, aspect };
364
- }
365
- /** Default viewport setup */
366
- _resizeViewport() {
367
- // @ts-expect-error Expose on canvasContext
368
- if (this.props.autoResizeViewport && this.device.gl) {
369
- // @ts-expect-error Expose canvasContext
370
- this.device.gl.viewport(0, 0, this.device.gl.drawingBufferWidth, this.device.gl.drawingBufferHeight);
371
- }
372
- }
373
- /**
374
- * Resize the render buffer of the canvas to match canvas client size
375
- * Optionally multiplying with devicePixel ratio
376
- */
377
- _resizeCanvasDrawingBuffer() {
378
- if (this.props.autoResizeDrawingBuffer) {
379
- this.device?.canvasContext?.resize({ useDevicePixels: this.props.useDevicePixels });
380
- }
381
- }
382
- _beginTimers() {
383
- this.frameRate.timeEnd();
384
- this.frameRate.timeStart();
385
- // Check if timer for last frame has completed.
386
- // GPU timer results are never available in the same
387
- // frame they are captured.
388
- // if (
389
- // this._gpuTimeQuery &&
390
- // this._gpuTimeQuery.isResultAvailable() &&
391
- // !this._gpuTimeQuery.isTimerDisjoint()
392
- // ) {
393
- // this.stats.get('GPU Time').addTime(this._gpuTimeQuery.getTimerMilliseconds());
394
- // }
395
- // if (this._gpuTimeQuery) {
396
- // // GPU time query start
397
- // this._gpuTimeQuery.beginTimeElapsedQuery();
398
- // }
399
- // this.cpuTime.timeStart();
400
- }
401
- _endTimers() {
402
- this.cpuTime.timeEnd();
403
- // if (this._gpuTimeQuery) {
404
- // // GPU time query end. Results will be available on next frame.
405
- // this._gpuTimeQuery.end();
406
- // }
407
- }
408
- // Event handling
409
- _startEventHandling() {
410
- if (this.canvas) {
411
- this.canvas.addEventListener('mousemove', this._onMousemove);
412
- this.canvas.addEventListener('mouseleave', this._onMouseleave);
413
- }
414
- }
415
- _onMousemove(event) {
416
- if (event instanceof MouseEvent) {
417
- this._getAnimationProps()._mousePosition = [event.offsetX, event.offsetY];
418
- }
419
- }
420
- _onMouseleave(event) {
421
- this._getAnimationProps()._mousePosition = null;
422
- }
111
+ }
112
+ return this;
113
+ } catch (err) {
114
+ const error = err instanceof Error ? err : new Error('Unknown error');
115
+ this.props.onError(error);
116
+ throw error;
117
+ }
118
+ }
119
+ redraw() {
120
+ var _this$device;
121
+ if ((_this$device = this.device) !== null && _this$device !== void 0 && _this$device.isLost) {
122
+ return this;
123
+ }
124
+ this._beginTimers();
125
+ this._setupFrame();
126
+ this._updateAnimationProps();
127
+ this._renderFrame(this._getAnimationProps());
128
+ this._clearNeedsRedraw();
129
+ if (this._resolveNextFrame) {
130
+ this._resolveNextFrame(this);
131
+ this._nextFramePromise = null;
132
+ this._resolveNextFrame = null;
133
+ }
134
+ this._endTimers();
135
+ return this;
136
+ }
137
+ stop() {
138
+ if (this._running) {
139
+ if (this.animationProps) {
140
+ this.props.onFinalize(this.animationProps);
141
+ }
142
+ this._cancelAnimationFrame();
143
+ this._nextFramePromise = null;
144
+ this._resolveNextFrame = null;
145
+ this._running = false;
146
+ }
147
+ return this;
148
+ }
149
+ attachTimeline(timeline) {
150
+ this.timeline = timeline;
151
+ return this.timeline;
152
+ }
153
+ detachTimeline() {
154
+ this.timeline = null;
155
+ }
156
+ waitForRender() {
157
+ this.setNeedsRedraw('waitForRender');
158
+ if (!this._nextFramePromise) {
159
+ this._nextFramePromise = new Promise(resolve => {
160
+ this._resolveNextFrame = resolve;
161
+ });
162
+ }
163
+ return this._nextFramePromise;
164
+ }
165
+ async toDataURL() {
166
+ this.setNeedsRedraw('toDataURL');
167
+ await this.waitForRender();
168
+ if (this.canvas instanceof HTMLCanvasElement) {
169
+ return this.canvas.toDataURL();
170
+ }
171
+ throw new Error('OffscreenCanvas');
172
+ }
173
+ _initialize() {
174
+ this._startEventHandling();
175
+ this._initializeAnimationProps();
176
+ this._updateAnimationProps();
177
+ this._resizeCanvasDrawingBuffer();
178
+ this._resizeViewport();
179
+ }
180
+ _setDisplay(display) {
181
+ if (this.display) {
182
+ this.display.delete();
183
+ this.display.animationLoop = null;
184
+ }
185
+ if (display) {
186
+ display.animationLoop = this;
187
+ }
188
+ this.display = display;
189
+ }
190
+ _requestAnimationFrame() {
191
+ if (!this._running) {
192
+ return;
193
+ }
194
+ this._animationFrameId = requestAnimationFrame(this._animationFrame.bind(this));
195
+ }
196
+ _cancelAnimationFrame() {
197
+ if (this._animationFrameId !== null) {
198
+ return;
199
+ }
200
+ cancelAnimationFrame(this._animationFrameId);
201
+ this._animationFrameId = null;
202
+ }
203
+ _animationFrame() {
204
+ if (!this._running) {
205
+ return;
206
+ }
207
+ this.redraw();
208
+ this._requestAnimationFrame();
209
+ }
210
+ _renderFrame(animationProps) {
211
+ if (this.display) {
212
+ this.display._renderFrame(animationProps);
213
+ return;
214
+ }
215
+ this.props.onRender(this._getAnimationProps());
216
+ }
217
+ _clearNeedsRedraw() {
218
+ this.needsRedraw = false;
219
+ }
220
+ _setupFrame() {
221
+ this._resizeCanvasDrawingBuffer();
222
+ this._resizeViewport();
223
+ }
224
+ _initializeAnimationProps() {
225
+ var _this$device2, _this$device2$canvasC;
226
+ if (!this.device) {
227
+ throw new Error('loop');
228
+ }
229
+ this.animationProps = {
230
+ animationLoop: this,
231
+ device: this.device,
232
+ canvas: (_this$device2 = this.device) === null || _this$device2 === void 0 ? void 0 : (_this$device2$canvasC = _this$device2.canvasContext) === null || _this$device2$canvasC === void 0 ? void 0 : _this$device2$canvasC.canvas,
233
+ timeline: this.timeline,
234
+ useDevicePixels: this.props.useDevicePixels,
235
+ needsRedraw: false,
236
+ width: 1,
237
+ height: 1,
238
+ aspect: 1,
239
+ time: 0,
240
+ startTime: Date.now(),
241
+ engineTime: 0,
242
+ tick: 0,
243
+ tock: 0,
244
+ _mousePosition: null
245
+ };
246
+ }
247
+ _getAnimationProps() {
248
+ if (!this.animationProps) {
249
+ throw new Error('animationProps');
250
+ }
251
+ return this.animationProps;
252
+ }
253
+ _updateAnimationProps() {
254
+ if (!this.animationProps) {
255
+ return;
256
+ }
257
+ const {
258
+ width,
259
+ height,
260
+ aspect
261
+ } = this._getSizeAndAspect();
262
+ if (width !== this.animationProps.width || height !== this.animationProps.height) {
263
+ this.setNeedsRedraw('drawing buffer resized');
264
+ }
265
+ if (aspect !== this.animationProps.aspect) {
266
+ this.setNeedsRedraw('drawing buffer aspect changed');
267
+ }
268
+ this.animationProps.width = width;
269
+ this.animationProps.height = height;
270
+ this.animationProps.aspect = aspect;
271
+ this.animationProps.needsRedraw = this.needsRedraw;
272
+ this.animationProps.engineTime = Date.now() - this.animationProps.startTime;
273
+ if (this.timeline) {
274
+ this.timeline.update(this.animationProps.engineTime);
275
+ }
276
+ this.animationProps.tick = Math.floor(this.animationProps.time / 1000 * 60);
277
+ this.animationProps.tock++;
278
+ this.animationProps.time = this.timeline ? this.timeline.getTime() : this.animationProps.engineTime;
279
+ }
280
+ async _initDevice() {
281
+ var _this$device$canvasCo;
282
+ this.device = await this.props.device;
283
+ if (!this.device) {
284
+ throw new Error('No device provided');
285
+ }
286
+ this.canvas = ((_this$device$canvasCo = this.device.canvasContext) === null || _this$device$canvasCo === void 0 ? void 0 : _this$device$canvasCo.canvas) || null;
287
+ }
288
+ _createInfoDiv() {
289
+ if (this.canvas && this.props.onAddHTML) {
290
+ const wrapperDiv = document.createElement('div');
291
+ document.body.appendChild(wrapperDiv);
292
+ wrapperDiv.style.position = 'relative';
293
+ const div = document.createElement('div');
294
+ div.style.position = 'absolute';
295
+ div.style.left = '10px';
296
+ div.style.bottom = '10px';
297
+ div.style.width = '300px';
298
+ div.style.background = 'white';
299
+ if (this.canvas instanceof HTMLCanvasElement) {
300
+ wrapperDiv.appendChild(this.canvas);
301
+ }
302
+ wrapperDiv.appendChild(div);
303
+ const html = this.props.onAddHTML(div);
304
+ if (html) {
305
+ div.innerHTML = html;
306
+ }
307
+ }
308
+ }
309
+ _getSizeAndAspect() {
310
+ var _this$device3, _this$device3$canvasC, _this$device4, _this$device4$canvasC;
311
+ if (!this.device) {
312
+ return {
313
+ width: 1,
314
+ height: 1,
315
+ aspect: 1
316
+ };
317
+ }
318
+ const [width, height] = ((_this$device3 = this.device) === null || _this$device3 === void 0 ? void 0 : (_this$device3$canvasC = _this$device3.canvasContext) === null || _this$device3$canvasC === void 0 ? void 0 : _this$device3$canvasC.getPixelSize()) || [1, 1];
319
+ let aspect = 1;
320
+ const canvas = (_this$device4 = this.device) === null || _this$device4 === void 0 ? void 0 : (_this$device4$canvasC = _this$device4.canvasContext) === null || _this$device4$canvasC === void 0 ? void 0 : _this$device4$canvasC.canvas;
321
+ if (canvas && canvas.clientHeight) {
322
+ aspect = canvas.clientWidth / canvas.clientHeight;
323
+ } else if (width > 0 && height > 0) {
324
+ aspect = width / height;
325
+ }
326
+ return {
327
+ width,
328
+ height,
329
+ aspect
330
+ };
331
+ }
332
+ _resizeViewport() {
333
+ if (this.props.autoResizeViewport && this.device.gl) {
334
+ this.device.gl.viewport(0, 0, this.device.gl.drawingBufferWidth, this.device.gl.drawingBufferHeight);
335
+ }
336
+ }
337
+ _resizeCanvasDrawingBuffer() {
338
+ if (this.props.autoResizeDrawingBuffer) {
339
+ var _this$device5, _this$device5$canvasC;
340
+ (_this$device5 = this.device) === null || _this$device5 === void 0 ? void 0 : (_this$device5$canvasC = _this$device5.canvasContext) === null || _this$device5$canvasC === void 0 ? void 0 : _this$device5$canvasC.resize({
341
+ useDevicePixels: this.props.useDevicePixels
342
+ });
343
+ }
344
+ }
345
+ _beginTimers() {
346
+ this.frameRate.timeEnd();
347
+ this.frameRate.timeStart();
348
+ }
349
+ _endTimers() {
350
+ this.cpuTime.timeEnd();
351
+ }
352
+ _startEventHandling() {
353
+ if (this.canvas) {
354
+ this.canvas.addEventListener('mousemove', this._onMousemove.bind(this));
355
+ this.canvas.addEventListener('mouseleave', this._onMouseleave.bind(this));
356
+ }
357
+ }
358
+ _onMousemove(event) {
359
+ if (event instanceof MouseEvent) {
360
+ this._getAnimationProps()._mousePosition = [event.offsetX, event.offsetY];
361
+ }
362
+ }
363
+ _onMouseleave(event) {
364
+ this._getAnimationProps()._mousePosition = null;
365
+ }
423
366
  }
367
+ //# sourceMappingURL=animation-loop.js.map