@luma.gl/engine 9.0.0-alpha.9 → 9.0.0-beta.2
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.
- package/LICENSE +3 -1
- package/dist/animation/key-frames.d.ts +1 -1
- package/dist/animation/key-frames.d.ts.map +1 -1
- package/dist/animation/key-frames.js +6 -27
- package/dist/animation/key-frames.js.map +1 -1
- package/dist/animation/timeline.d.ts +8 -8
- package/dist/animation/timeline.d.ts.map +1 -1
- package/dist/animation/timeline.js +18 -49
- package/dist/animation/timeline.js.map +1 -1
- package/dist/animation-loop/animation-loop-template.d.ts +23 -0
- package/dist/animation-loop/animation-loop-template.d.ts.map +1 -0
- package/dist/animation-loop/animation-loop-template.js +7 -0
- package/dist/animation-loop/animation-loop-template.js.map +1 -0
- package/dist/{lib → animation-loop}/animation-loop.d.ts +30 -22
- package/dist/animation-loop/animation-loop.d.ts.map +1 -0
- package/dist/{lib → animation-loop}/animation-loop.js +77 -192
- package/dist/animation-loop/animation-loop.js.map +1 -0
- package/dist/{lib → animation-loop}/animation-props.d.ts +2 -3
- package/dist/animation-loop/animation-props.d.ts.map +1 -0
- package/dist/animation-loop/animation-props.js.map +1 -0
- package/dist/animation-loop/make-animation-loop.d.ts +6 -0
- package/dist/animation-loop/make-animation-loop.d.ts.map +1 -0
- package/dist/animation-loop/make-animation-loop.js +28 -0
- package/dist/animation-loop/make-animation-loop.js.map +1 -0
- package/dist/debug/copy-texture-to-image.d.ts +26 -0
- package/dist/debug/copy-texture-to-image.d.ts.map +1 -0
- package/dist/debug/copy-texture-to-image.js +46 -0
- package/dist/debug/copy-texture-to-image.js.map +1 -0
- package/dist/debug/debug-framebuffer.d.ts +11 -0
- package/dist/debug/debug-framebuffer.d.ts.map +1 -0
- package/dist/debug/debug-framebuffer.js +43 -0
- package/dist/debug/debug-framebuffer.js.map +1 -0
- package/dist/debug/debug-shader-layout.d.ts +9 -0
- package/dist/debug/debug-shader-layout.d.ts.map +1 -0
- package/dist/debug/debug-shader-layout.js +28 -0
- package/dist/debug/debug-shader-layout.js.map +1 -0
- package/dist/debug/pixel-data-utils.d.ts +24 -0
- package/dist/debug/pixel-data-utils.d.ts.map +1 -0
- package/dist/debug/pixel-data-utils.js +41 -0
- package/dist/debug/pixel-data-utils.js.map +1 -0
- package/dist/dist.dev.js +10073 -0
- package/dist/geometries/cone-geometry.d.ts +1 -1
- package/dist/geometries/cone-geometry.d.ts.map +1 -1
- package/dist/geometries/cone-geometry.js +6 -5
- package/dist/geometries/cone-geometry.js.map +1 -1
- package/dist/geometries/cube-geometry.d.ts +2 -2
- package/dist/geometries/cube-geometry.d.ts.map +1 -1
- package/dist/geometries/cube-geometry.js +16 -10
- package/dist/geometries/cube-geometry.js.map +1 -1
- package/dist/geometries/cylinder-geometry.d.ts +1 -1
- package/dist/geometries/cylinder-geometry.d.ts.map +1 -1
- package/dist/geometries/cylinder-geometry.js +6 -5
- package/dist/geometries/cylinder-geometry.js.map +1 -1
- package/dist/geometries/ico-sphere-geometry.d.ts +2 -2
- package/dist/geometries/ico-sphere-geometry.d.ts.map +1 -1
- package/dist/geometries/ico-sphere-geometry.js +10 -19
- package/dist/geometries/ico-sphere-geometry.js.map +1 -1
- package/dist/geometries/plane-geometry.d.ts +2 -2
- package/dist/geometries/plane-geometry.d.ts.map +1 -1
- package/dist/geometries/plane-geometry.js +14 -23
- package/dist/geometries/plane-geometry.js.map +1 -1
- package/dist/geometries/sphere-geometry.d.ts +2 -2
- package/dist/geometries/sphere-geometry.d.ts.map +1 -1
- package/dist/geometries/sphere-geometry.js +9 -13
- package/dist/geometries/sphere-geometry.js.map +1 -1
- package/dist/geometries/truncated-cone-geometry.d.ts +2 -4
- package/dist/geometries/truncated-cone-geometry.d.ts.map +1 -1
- package/dist/geometries/truncated-cone-geometry.js +9 -25
- package/dist/geometries/truncated-cone-geometry.js.map +1 -1
- package/dist/geometry/geometry-table.d.ts +2 -2
- package/dist/geometry/geometry-table.d.ts.map +1 -1
- package/dist/geometry/geometry-table.js.map +1 -1
- package/dist/geometry/geometry-utils.d.ts.map +1 -1
- package/dist/geometry/geometry-utils.js +0 -9
- package/dist/geometry/geometry-utils.js.map +1 -1
- package/dist/geometry/geometry.d.ts +43 -43
- package/dist/geometry/geometry.d.ts.map +1 -1
- package/dist/geometry/geometry.js +20 -86
- package/dist/geometry/geometry.js.map +1 -1
- package/dist/geometry/gpu-geometry.d.ts +37 -0
- package/dist/geometry/gpu-geometry.d.ts.map +1 -0
- package/dist/geometry/gpu-geometry.js +110 -0
- package/dist/geometry/gpu-geometry.js.map +1 -0
- package/dist/geometry/gpu-table.d.ts +1 -0
- package/dist/geometry/gpu-table.d.ts.map +1 -0
- package/dist/geometry/gpu-table.js +2 -0
- package/dist/geometry/gpu-table.js.map +1 -0
- package/dist/index.cjs +3120 -0
- package/dist/index.d.ts +24 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -14
- package/dist/index.js.map +1 -1
- package/dist/lib/clip-space.d.ts +8 -0
- package/dist/lib/clip-space.d.ts.map +1 -1
- package/dist/lib/clip-space.js +47 -0
- package/dist/lib/clip-space.js.map +1 -1
- package/dist/lib/pipeline-factory.d.ts +12 -46
- package/dist/lib/pipeline-factory.d.ts.map +1 -1
- package/dist/lib/pipeline-factory.js +36 -179
- package/dist/lib/pipeline-factory.js.map +1 -1
- package/dist/model/model.d.ts +206 -0
- package/dist/model/model.d.ts.map +1 -0
- package/dist/model/model.js +440 -0
- package/dist/model/model.js.map +1 -0
- package/dist/scenegraph/group-node.d.ts +21 -0
- package/dist/scenegraph/group-node.d.ts.map +1 -0
- package/dist/scenegraph/group-node.js +94 -0
- package/dist/scenegraph/group-node.js.map +1 -0
- package/dist/scenegraph/model-node.d.ts +18 -0
- package/dist/scenegraph/model-node.d.ts.map +1 -0
- package/dist/scenegraph/model-node.js +28 -0
- package/dist/scenegraph/model-node.js.map +1 -0
- package/dist/scenegraph/scenegraph-node.d.ts +56 -0
- package/dist/scenegraph/scenegraph-node.d.ts.map +1 -0
- package/dist/scenegraph/scenegraph-node.js +141 -0
- package/dist/scenegraph/scenegraph-node.js.map +1 -0
- package/dist/shader-inputs.d.ts +63 -0
- package/dist/shader-inputs.d.ts.map +1 -0
- package/dist/shader-inputs.js +66 -0
- package/dist/shader-inputs.js.map +1 -0
- package/dist/transform/buffer-transform.d.ts +35 -0
- package/dist/transform/buffer-transform.d.ts.map +1 -0
- package/dist/transform/buffer-transform.js +62 -0
- package/dist/transform/buffer-transform.js.map +1 -0
- package/dist/transform/texture-transform.d.ts +57 -0
- package/dist/transform/texture-transform.d.ts.map +1 -0
- package/dist/transform/texture-transform.js +122 -0
- package/dist/transform/texture-transform.js.map +1 -0
- package/dist.min.js +293 -0
- package/package.json +21 -12
- package/src/animation/timeline.ts +15 -14
- package/src/animation-loop/animation-loop-template.ts +23 -0
- package/src/{lib → animation-loop}/animation-loop.ts +99 -88
- package/src/{lib → animation-loop}/animation-props.ts +1 -1
- package/src/animation-loop/make-animation-loop.ts +44 -0
- package/src/debug/copy-texture-to-image.ts +72 -0
- package/src/debug/debug-framebuffer.ts +57 -0
- package/src/debug/debug-shader-layout.ts +38 -0
- package/src/debug/pixel-data-utils.ts +57 -0
- package/src/geometries/cone-geometry.ts +1 -1
- package/src/geometries/cube-geometry.ts +47 -45
- package/src/geometries/cylinder-geometry.ts +2 -2
- package/src/geometries/ico-sphere-geometry.ts +6 -5
- package/src/geometries/plane-geometry.ts +5 -4
- package/src/geometries/sphere-geometry.ts +4 -3
- package/src/geometries/truncated-cone-geometry.ts +4 -13
- package/src/geometry/geometry-table.ts +1 -1
- package/src/geometry/geometry-utils.ts +19 -3
- package/src/geometry/geometry.ts +65 -110
- package/src/geometry/gpu-geometry.ts +125 -0
- package/src/geometry/gpu-table.ts +41 -0
- package/src/index.ts +34 -10
- package/src/lib/clip-space.ts +22 -21
- package/src/lib/pipeline-factory.ts +48 -179
- package/src/model/model.ts +733 -0
- package/src/scenegraph/group-node.ts +103 -0
- package/src/scenegraph/model-node.ts +50 -0
- package/src/scenegraph/scenegraph-node.ts +204 -0
- package/src/shader-inputs.ts +150 -0
- package/src/transform/buffer-transform.ts +94 -0
- package/src/transform/texture-transform.ts +169 -0
- package/dist/bundle.d.ts +0 -2
- package/dist/bundle.d.ts.map +0 -1
- package/dist/bundle.js +0 -5
- package/dist/bundle.js.map +0 -1
- package/dist/geometry/primitive-utils.d.ts +0 -1
- package/dist/geometry/primitive-utils.d.ts.map +0 -1
- package/dist/geometry/primitive-utils.js +0 -2
- package/dist/geometry/primitive-utils.js.map +0 -1
- package/dist/lib/animation-loop.d.ts.map +0 -1
- package/dist/lib/animation-loop.js.map +0 -1
- package/dist/lib/animation-props.d.ts.map +0 -1
- package/dist/lib/animation-props.js.map +0 -1
- package/dist/lib/model-utils.d.ts +0 -5
- package/dist/lib/model-utils.d.ts.map +0 -1
- package/dist/lib/model-utils.js +0 -45
- package/dist/lib/model-utils.js.map +0 -1
- package/dist/lib/model.d.ts +0 -41
- package/dist/lib/model.d.ts.map +0 -1
- package/dist/lib/model.js +0 -182
- package/dist/lib/model.js.map +0 -1
- package/dist/lib/render-loop.d.ts +0 -14
- package/dist/lib/render-loop.d.ts.map +0 -1
- package/dist/lib/render-loop.js +0 -49
- package/dist/lib/render-loop.js.map +0 -1
- package/src/bundle.ts +0 -4
- package/src/geometry/primitive-utils.ts +0 -30
- package/src/lib/model-utils.ts +0 -124
- package/src/lib/model.ts +0 -183
- package/src/lib/render-loop.ts +0 -58
- /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-
|
|
3
|
+
"version": "9.0.0-beta.2",
|
|
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,35 @@
|
|
|
16
17
|
"animation",
|
|
17
18
|
"3d"
|
|
18
19
|
],
|
|
19
|
-
"types": "
|
|
20
|
-
"main": "dist/index.
|
|
20
|
+
"types": "dist/index.d.ts",
|
|
21
|
+
"main": "dist/index.cjs",
|
|
21
22
|
"module": "dist/index.js",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"import": "./dist/index.js",
|
|
27
|
+
"require": "./dist/index.cjs"
|
|
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
|
-
"
|
|
30
|
-
"build
|
|
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-
|
|
35
|
-
"@luma.gl/
|
|
36
|
-
"@luma.gl/
|
|
37
|
-
"@math.gl/core": "^
|
|
38
|
-
"@probe.gl/log": "^
|
|
39
|
-
"@probe.gl/stats": "^
|
|
43
|
+
"@luma.gl/constants": "9.0.0-beta.2",
|
|
44
|
+
"@luma.gl/core": "9.0.0-beta.2",
|
|
45
|
+
"@luma.gl/shadertools": "9.0.0-beta.2",
|
|
46
|
+
"@math.gl/core": "^4.0.0",
|
|
47
|
+
"@probe.gl/log": "^4.0.2",
|
|
48
|
+
"@probe.gl/stats": "^4.0.2"
|
|
40
49
|
},
|
|
41
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "d90ddd6231c3d405d88dfb9e8c232c4dfefcc056"
|
|
42
51
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// luma.gl, MIT license
|
|
2
|
+
// Copyright (c) vis.gl contributors
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Timeline channel properties
|
|
@@ -7,7 +8,7 @@
|
|
|
7
8
|
* @param rate = 1
|
|
8
9
|
* @param repeat = 1
|
|
9
10
|
*/
|
|
10
|
-
|
|
11
|
+
export type ChannelOptions = {
|
|
11
12
|
delay?: number
|
|
12
13
|
duration?: number
|
|
13
14
|
rate?: number
|
|
@@ -49,7 +50,7 @@ export class Timeline {
|
|
|
49
50
|
addChannel(props: ChannelOptions): number {
|
|
50
51
|
const {delay = 0, duration = Number.POSITIVE_INFINITY, rate = 1, repeat = 1} = props;
|
|
51
52
|
|
|
52
|
-
const
|
|
53
|
+
const channelId = channelHandles++;
|
|
53
54
|
const channel: Channel = {
|
|
54
55
|
time: 0,
|
|
55
56
|
delay,
|
|
@@ -58,23 +59,23 @@ export class Timeline {
|
|
|
58
59
|
repeat
|
|
59
60
|
};
|
|
60
61
|
this._setChannelTime(channel, this.time);
|
|
61
|
-
this.channels.set(
|
|
62
|
+
this.channels.set(channelId, channel);
|
|
62
63
|
|
|
63
|
-
return
|
|
64
|
+
return channelId;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
removeChannel(
|
|
67
|
-
this.channels.delete(
|
|
67
|
+
removeChannel(channelId: number): void {
|
|
68
|
+
this.channels.delete(channelId);
|
|
68
69
|
|
|
69
70
|
for (const [animationHandle, animation] of this.animations) {
|
|
70
|
-
if (animation.channel ===
|
|
71
|
+
if (animation.channel === channelId) {
|
|
71
72
|
this.detachAnimation(animationHandle);
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
isFinished(
|
|
77
|
-
const channel = this.channels.get(
|
|
77
|
+
isFinished(channelId: number): boolean {
|
|
78
|
+
const channel = this.channels.get(channelId);
|
|
78
79
|
if (channel === undefined) {
|
|
79
80
|
return false;
|
|
80
81
|
}
|
|
@@ -82,12 +83,12 @@ export class Timeline {
|
|
|
82
83
|
return this.time >= channel.delay + channel.duration * channel.repeat;
|
|
83
84
|
}
|
|
84
85
|
|
|
85
|
-
getTime(
|
|
86
|
-
if (
|
|
86
|
+
getTime(channelId?: number): number {
|
|
87
|
+
if (channelId === undefined) {
|
|
87
88
|
return this.time;
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
const channel = this.channels.get(
|
|
91
|
+
const channel = this.channels.get(channelId);
|
|
91
92
|
|
|
92
93
|
if (channel === undefined) {
|
|
93
94
|
return -1;
|
|
@@ -137,8 +138,8 @@ export class Timeline {
|
|
|
137
138
|
return animationHandle;
|
|
138
139
|
}
|
|
139
140
|
|
|
140
|
-
detachAnimation(
|
|
141
|
-
this.animations.delete(
|
|
141
|
+
detachAnimation(channelId: number): void {
|
|
142
|
+
this.animations.delete(channelId);
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
update(engineTime: number): void {
|
|
@@ -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,53 +1,54 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// luma.gl, MIT license
|
|
2
|
+
// Copyright (c) vis.gl contributors
|
|
3
|
+
|
|
4
|
+
import {luma, Device} from '@luma.gl/core';
|
|
5
|
+
import {requestAnimationFrame, cancelAnimationFrame} from '@luma.gl/core';
|
|
3
6
|
import {Timeline} from '../animation/timeline';
|
|
4
|
-
import {AnimationProps} from '
|
|
7
|
+
import {AnimationProps} from './animation-props';
|
|
5
8
|
import {Stats, Stat} from '@probe.gl/stats';
|
|
6
|
-
import {isBrowser} from '@probe.gl/env';
|
|
7
|
-
|
|
8
|
-
const isPage = isBrowser() && typeof document !== 'undefined';
|
|
9
9
|
|
|
10
10
|
let statIdCounter = 0;
|
|
11
11
|
|
|
12
|
-
type ContextProps = DeviceProps;
|
|
13
|
-
|
|
14
12
|
/** AnimationLoop properties */
|
|
15
13
|
export type AnimationLoopProps = {
|
|
16
|
-
|
|
14
|
+
device: Device | Promise<Device>;
|
|
15
|
+
|
|
17
16
|
onAddHTML?: (div: HTMLDivElement) => string; // innerHTML
|
|
18
|
-
onInitialize?: (animationProps: AnimationProps) =>
|
|
19
|
-
onRender?: (animationProps: AnimationProps) =>
|
|
17
|
+
onInitialize?: (animationProps: AnimationProps) => Promise<unknown>;
|
|
18
|
+
onRender?: (animationProps: AnimationProps) => unknown;
|
|
20
19
|
onFinalize?: (animationProps: AnimationProps) => void;
|
|
21
20
|
onError?: (reason: Error) => void;
|
|
22
21
|
|
|
23
|
-
device?: Device | null;
|
|
24
|
-
deviceProps?: DeviceProps;
|
|
25
22
|
stats?: Stats;
|
|
26
23
|
|
|
27
|
-
// view parameters
|
|
28
|
-
debug?: boolean;
|
|
24
|
+
// view parameters - TODO move to CanvasContext?
|
|
29
25
|
autoResizeViewport?: boolean;
|
|
30
26
|
autoResizeDrawingBuffer?: boolean;
|
|
31
27
|
useDevicePixels?: number | boolean;
|
|
32
28
|
};
|
|
33
29
|
|
|
30
|
+
export type MutableAnimationLoopProps = {
|
|
31
|
+
// view parameters
|
|
32
|
+
autoResizeViewport?: boolean;
|
|
33
|
+
autoResizeDrawingBuffer?: boolean;
|
|
34
|
+
useDevicePixels?: number | boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
34
37
|
const DEFAULT_ANIMATION_LOOP_PROPS: Required<AnimationLoopProps> = {
|
|
35
|
-
|
|
38
|
+
device: null!,
|
|
39
|
+
|
|
36
40
|
onAddHTML: () => '',
|
|
37
|
-
onInitialize: () =>
|
|
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: null,
|
|
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:
|
|
50
|
-
autoResizeDrawingBuffer:
|
|
50
|
+
autoResizeViewport: false,
|
|
51
|
+
autoResizeDrawingBuffer: false,
|
|
51
52
|
};
|
|
52
53
|
|
|
53
54
|
/** Convenient animation loop */
|
|
@@ -71,7 +72,7 @@ export class AnimationLoop {
|
|
|
71
72
|
_running: boolean = false;
|
|
72
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,17 +80,17 @@ export 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
|
-
|
|
87
|
+
if (!props.device) {
|
|
88
|
+
throw new Error('No device provided');
|
|
89
|
+
}
|
|
87
90
|
|
|
88
|
-
|
|
89
|
-
this.device = props.device || null;
|
|
90
|
-
// @ts-expect-error
|
|
91
|
-
this.gl = (this.device && this.device.gl) || props.gl;
|
|
91
|
+
const {useDevicePixels = true} = this.props;
|
|
92
92
|
|
|
93
|
+
// state
|
|
93
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');
|
|
@@ -119,13 +120,14 @@ export class AnimationLoop {
|
|
|
119
120
|
this.destroy();
|
|
120
121
|
}
|
|
121
122
|
|
|
123
|
+
/** Flags this animation loop as needing redraw */
|
|
122
124
|
setNeedsRedraw(reason: string): this {
|
|
123
125
|
this.needsRedraw = this.needsRedraw || reason;
|
|
124
126
|
return this;
|
|
125
127
|
}
|
|
126
128
|
|
|
127
|
-
|
|
128
|
-
setProps(props:
|
|
129
|
+
/** TODO - move these props to CanvasContext? */
|
|
130
|
+
setProps(props: MutableAnimationLoopProps): this {
|
|
129
131
|
if ('autoResizeViewport' in props) {
|
|
130
132
|
this.props.autoResizeViewport = props.autoResizeViewport || false;
|
|
131
133
|
}
|
|
@@ -146,16 +148,12 @@ export class AnimationLoop {
|
|
|
146
148
|
this._running = true;
|
|
147
149
|
|
|
148
150
|
try {
|
|
149
|
-
// check that we haven't been stopped
|
|
150
|
-
if (!this._running) {
|
|
151
|
-
return null;
|
|
152
|
-
}
|
|
153
151
|
|
|
154
152
|
let appContext;
|
|
155
153
|
if (!this._initialized) {
|
|
156
154
|
this._initialized = true;
|
|
157
155
|
// Create the WebGL context
|
|
158
|
-
await this.
|
|
156
|
+
await this._initDevice();
|
|
159
157
|
this._initialize();
|
|
160
158
|
|
|
161
159
|
// Note: onIntialize can return a promise (e.g. in case app needs to load resources)
|
|
@@ -183,13 +181,31 @@ export class AnimationLoop {
|
|
|
183
181
|
}
|
|
184
182
|
}
|
|
185
183
|
|
|
184
|
+
/** Stops a render loop if already running, finalizing */
|
|
185
|
+
stop() {
|
|
186
|
+
// console.debug(`Stopping ${this.constructor.name}`);
|
|
187
|
+
if (this._running) {
|
|
188
|
+
// call callback
|
|
189
|
+
// If stop is called immediately, we can end up in a state where props haven't been initialized...
|
|
190
|
+
if (this.animationProps) {
|
|
191
|
+
this.props.onFinalize(this.animationProps);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
this._cancelAnimationFrame();
|
|
195
|
+
this._nextFramePromise = null;
|
|
196
|
+
this._resolveNextFrame = null;
|
|
197
|
+
this._running = false;
|
|
198
|
+
}
|
|
199
|
+
return this;
|
|
200
|
+
}
|
|
201
|
+
|
|
186
202
|
/** Explicitly draw a frame */
|
|
187
203
|
redraw(): this {
|
|
188
204
|
if (this.device?.isLost) {
|
|
189
205
|
return this;
|
|
190
206
|
}
|
|
191
207
|
|
|
192
|
-
this.
|
|
208
|
+
this._beginFrameTimers();
|
|
193
209
|
|
|
194
210
|
this._setupFrame();
|
|
195
211
|
this._updateAnimationProps();
|
|
@@ -205,38 +221,23 @@ export class AnimationLoop {
|
|
|
205
221
|
this._resolveNextFrame = null;
|
|
206
222
|
}
|
|
207
223
|
|
|
208
|
-
this.
|
|
224
|
+
this._endFrameTimers();
|
|
209
225
|
|
|
210
226
|
return this;
|
|
211
227
|
}
|
|
212
228
|
|
|
213
|
-
|
|
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
|
-
|
|
229
|
+
/** Add a timeline, it will be automatically updated by the animation loop. */
|
|
231
230
|
attachTimeline(timeline: Timeline): Timeline {
|
|
232
231
|
this.timeline = timeline;
|
|
233
232
|
return this.timeline;
|
|
234
233
|
}
|
|
235
234
|
|
|
235
|
+
/** Remove a timeline */
|
|
236
236
|
detachTimeline(): void {
|
|
237
237
|
this.timeline = null;
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
/** Wait until a render completes */
|
|
240
241
|
waitForRender(): Promise<AnimationLoop> {
|
|
241
242
|
this.setNeedsRedraw('waitForRender');
|
|
242
243
|
|
|
@@ -248,6 +249,7 @@ export class AnimationLoop {
|
|
|
248
249
|
return this._nextFramePromise;
|
|
249
250
|
}
|
|
250
251
|
|
|
252
|
+
/** TODO - should use device.deviceContext */
|
|
251
253
|
async toDataURL(): Promise<string> {
|
|
252
254
|
this.setNeedsRedraw('toDataURL');
|
|
253
255
|
await this.waitForRender();
|
|
@@ -259,7 +261,7 @@ export class AnimationLoop {
|
|
|
259
261
|
|
|
260
262
|
// PRIVATE METHODS
|
|
261
263
|
|
|
262
|
-
_initialize() {
|
|
264
|
+
_initialize(): void {
|
|
263
265
|
this._startEventHandling();
|
|
264
266
|
|
|
265
267
|
// Initialize the callback data
|
|
@@ -273,9 +275,9 @@ export class AnimationLoop {
|
|
|
273
275
|
// this._gpuTimeQuery = Query.isSupported(this.gl, ['timers']) ? new Query(this.gl) : null;
|
|
274
276
|
}
|
|
275
277
|
|
|
276
|
-
_setDisplay(display) {
|
|
278
|
+
_setDisplay(display: any): void {
|
|
277
279
|
if (this.display) {
|
|
278
|
-
this.display.
|
|
280
|
+
this.display.destroy();
|
|
279
281
|
this.display.animationLoop = null;
|
|
280
282
|
}
|
|
281
283
|
|
|
@@ -287,7 +289,7 @@ export class AnimationLoop {
|
|
|
287
289
|
this.display = display;
|
|
288
290
|
}
|
|
289
291
|
|
|
290
|
-
_requestAnimationFrame() {
|
|
292
|
+
_requestAnimationFrame(): void {
|
|
291
293
|
if (!this._running) {
|
|
292
294
|
return;
|
|
293
295
|
}
|
|
@@ -301,8 +303,8 @@ export class AnimationLoop {
|
|
|
301
303
|
this._animationFrameId = requestAnimationFrame(this._animationFrame.bind(this));
|
|
302
304
|
}
|
|
303
305
|
|
|
304
|
-
_cancelAnimationFrame() {
|
|
305
|
-
if (this._animationFrameId
|
|
306
|
+
_cancelAnimationFrame(): void {
|
|
307
|
+
if (this._animationFrameId === null) {
|
|
306
308
|
return;
|
|
307
309
|
}
|
|
308
310
|
|
|
@@ -312,11 +314,11 @@ export class AnimationLoop {
|
|
|
312
314
|
// if (this.display && this.display.cancelAnimationFrame) {
|
|
313
315
|
// this.display.cancelAnimationFrame(this._animationFrameId);
|
|
314
316
|
// }
|
|
315
|
-
|
|
317
|
+
cancelAnimationFrame(this._animationFrameId);
|
|
316
318
|
this._animationFrameId = null;
|
|
317
319
|
}
|
|
318
320
|
|
|
319
|
-
_animationFrame() {
|
|
321
|
+
_animationFrame(): void {
|
|
320
322
|
if (!this._running) {
|
|
321
323
|
return;
|
|
322
324
|
}
|
|
@@ -326,36 +328,40 @@ export class AnimationLoop {
|
|
|
326
328
|
|
|
327
329
|
// Called on each frame, can be overridden to call onRender multiple times
|
|
328
330
|
// to support e.g. stereoscopic rendering
|
|
329
|
-
_renderFrame(
|
|
331
|
+
_renderFrame(animationProps: AnimationProps): void {
|
|
330
332
|
// Allow e.g. VR display to render multiple frames.
|
|
331
333
|
if (this.display) {
|
|
332
|
-
this.display._renderFrame(
|
|
334
|
+
this.display._renderFrame(animationProps);
|
|
333
335
|
return;
|
|
334
336
|
}
|
|
335
337
|
|
|
336
338
|
// call callback
|
|
337
|
-
this.props.onRender(
|
|
339
|
+
this.props.onRender(this._getAnimationProps());
|
|
338
340
|
// end callback
|
|
341
|
+
|
|
342
|
+
// Submit commands (necessary on WebGPU)
|
|
343
|
+
this.device.submit();
|
|
339
344
|
}
|
|
340
345
|
|
|
341
|
-
_clearNeedsRedraw() {
|
|
346
|
+
_clearNeedsRedraw(): void {
|
|
342
347
|
this.needsRedraw = false;
|
|
343
348
|
}
|
|
344
349
|
|
|
345
|
-
_setupFrame() {
|
|
350
|
+
_setupFrame(): void {
|
|
346
351
|
this._resizeCanvasDrawingBuffer();
|
|
347
352
|
this._resizeViewport();
|
|
348
353
|
}
|
|
349
354
|
|
|
350
355
|
// Initialize the object that will be passed to app callbacks
|
|
351
|
-
_initializeAnimationProps() {
|
|
356
|
+
_initializeAnimationProps(): void {
|
|
352
357
|
if (!this.device) {
|
|
353
358
|
throw new Error('loop');
|
|
354
359
|
}
|
|
355
360
|
this.animationProps = {
|
|
356
361
|
animationLoop: this,
|
|
362
|
+
|
|
357
363
|
device: this.device,
|
|
358
|
-
canvas: this.device?.canvasContext?.canvas
|
|
364
|
+
canvas: this.device?.canvasContext?.canvas,
|
|
359
365
|
timeline: this.timeline,
|
|
360
366
|
|
|
361
367
|
// Initial values
|
|
@@ -392,6 +398,7 @@ export class AnimationLoop {
|
|
|
392
398
|
return;
|
|
393
399
|
}
|
|
394
400
|
|
|
401
|
+
// Can this be replaced with canvas context?
|
|
395
402
|
const {width, height, aspect} = this._getSizeAndAspect();
|
|
396
403
|
if (width !== this.animationProps.width || height !== this.animationProps.height) {
|
|
397
404
|
this.setNeedsRedraw('drawing buffer resized');
|
|
@@ -422,15 +429,17 @@ export class AnimationLoop {
|
|
|
422
429
|
: this.animationProps.engineTime;
|
|
423
430
|
}
|
|
424
431
|
|
|
425
|
-
/**
|
|
426
|
-
async
|
|
427
|
-
|
|
428
|
-
this.device
|
|
429
|
-
|
|
430
|
-
|
|
432
|
+
/** Wait for supplied device */
|
|
433
|
+
async _initDevice() {
|
|
434
|
+
this.device = await this.props.device;
|
|
435
|
+
if (!this.device) {
|
|
436
|
+
throw new Error('No device provided');
|
|
437
|
+
}
|
|
438
|
+
this.canvas = this.device.canvasContext?.canvas || null;
|
|
439
|
+
// this._createInfoDiv();
|
|
431
440
|
}
|
|
432
441
|
|
|
433
|
-
_createInfoDiv() {
|
|
442
|
+
_createInfoDiv(): void {
|
|
434
443
|
if (this.canvas && this.props.onAddHTML) {
|
|
435
444
|
const wrapperDiv = document.createElement('div');
|
|
436
445
|
document.body.appendChild(wrapperDiv);
|
|
@@ -475,7 +484,7 @@ export class AnimationLoop {
|
|
|
475
484
|
}
|
|
476
485
|
|
|
477
486
|
/** Default viewport setup */
|
|
478
|
-
_resizeViewport() {
|
|
487
|
+
_resizeViewport(): void {
|
|
479
488
|
// @ts-expect-error Expose on canvasContext
|
|
480
489
|
if (this.props.autoResizeViewport && this.device.gl) {
|
|
481
490
|
// @ts-expect-error Expose canvasContext
|
|
@@ -487,13 +496,13 @@ export class AnimationLoop {
|
|
|
487
496
|
* Resize the render buffer of the canvas to match canvas client size
|
|
488
497
|
* Optionally multiplying with devicePixel ratio
|
|
489
498
|
*/
|
|
490
|
-
_resizeCanvasDrawingBuffer() {
|
|
499
|
+
_resizeCanvasDrawingBuffer(): void {
|
|
491
500
|
if (this.props.autoResizeDrawingBuffer) {
|
|
492
501
|
this.device?.canvasContext?.resize({useDevicePixels: this.props.useDevicePixels});
|
|
493
502
|
}
|
|
494
503
|
}
|
|
495
504
|
|
|
496
|
-
|
|
505
|
+
_beginFrameTimers() {
|
|
497
506
|
this.frameRate.timeEnd();
|
|
498
507
|
this.frameRate.timeStart();
|
|
499
508
|
|
|
@@ -513,10 +522,10 @@ export class AnimationLoop {
|
|
|
513
522
|
// this._gpuTimeQuery.beginTimeElapsedQuery();
|
|
514
523
|
// }
|
|
515
524
|
|
|
516
|
-
|
|
525
|
+
this.cpuTime.timeStart();
|
|
517
526
|
}
|
|
518
527
|
|
|
519
|
-
|
|
528
|
+
_endFrameTimers() {
|
|
520
529
|
this.cpuTime.timeEnd();
|
|
521
530
|
|
|
522
531
|
// if (this._gpuTimeQuery) {
|
|
@@ -529,16 +538,18 @@ export class AnimationLoop {
|
|
|
529
538
|
|
|
530
539
|
_startEventHandling() {
|
|
531
540
|
if (this.canvas) {
|
|
532
|
-
this.canvas.addEventListener('mousemove', this._onMousemove);
|
|
533
|
-
this.canvas.addEventListener('mouseleave', this._onMouseleave);
|
|
541
|
+
this.canvas.addEventListener('mousemove', this._onMousemove.bind(this));
|
|
542
|
+
this.canvas.addEventListener('mouseleave', this._onMouseleave.bind(this));
|
|
534
543
|
}
|
|
535
544
|
}
|
|
536
545
|
|
|
537
|
-
_onMousemove(
|
|
538
|
-
|
|
546
|
+
_onMousemove(event: Event) {
|
|
547
|
+
if (event instanceof MouseEvent) {
|
|
548
|
+
this._getAnimationProps()._mousePosition = [event.offsetX, event.offsetY];
|
|
549
|
+
}
|
|
539
550
|
}
|
|
540
551
|
|
|
541
|
-
_onMouseleave(
|
|
552
|
+
_onMouseleave(event: Event) {
|
|
542
553
|
this._getAnimationProps()._mousePosition = null;
|
|
543
554
|
}
|
|
544
555
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// luma.gl, MIT license
|
|
2
|
+
import {luma} from '@luma.gl/core';
|
|
3
|
+
import {AnimationLoopTemplate} from './animation-loop-template'
|
|
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
|
+
}
|