@luma.gl/engine 9.0.0-alpha.5 → 9.0.0-alpha.50
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 +9 -9
- 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/{lib → animation-loop}/animation-loop.d.ts +30 -31
- package/dist/animation-loop/animation-loop.d.ts.map +1 -0
- package/dist/{lib → animation-loop}/animation-loop.js +115 -199
- package/dist/animation-loop/animation-loop.js.map +1 -0
- package/dist/{lib → animation-loop}/animation-props.d.ts +6 -7
- 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/animation-loop/render-loop.d.ts +23 -0
- package/dist/animation-loop/render-loop.d.ts.map +1 -0
- package/dist/animation-loop/render-loop.js +7 -0
- package/dist/animation-loop/render-loop.js.map +1 -0
- package/dist/dist.dev.js +7064 -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 +15 -8
- 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 +50 -59
- package/dist/geometry/geometry.d.ts.map +1 -1
- package/dist/geometry/geometry.js +32 -97
- 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 +107 -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 +2959 -0
- package/dist/index.d.ts +26 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -13
- 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 -40
- package/dist/lib/pipeline-factory.d.ts.map +1 -1
- package/dist/lib/pipeline-factory.js +50 -148
- package/dist/lib/pipeline-factory.js.map +1 -1
- package/dist/model/model.d.ts +192 -0
- package/dist/model/model.d.ts.map +1 -0
- package/dist/model/model.js +312 -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 +62 -0
- package/dist/shader-inputs.d.ts.map +1 -0
- package/dist/shader-inputs.js +49 -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 +286 -0
- package/package.json +21 -12
- package/src/animation/timeline.ts +16 -15
- package/src/{lib → animation-loop}/animation-loop.ts +120 -107
- package/src/{lib → animation-loop}/animation-props.ts +5 -5
- package/src/animation-loop/make-animation-loop.ts +44 -0
- package/src/animation-loop/render-loop.ts +23 -0
- package/src/geometries/cone-geometry.ts +1 -1
- package/src/geometries/cube-geometry.ts +6 -3
- package/src/geometries/cylinder-geometry.ts +2 -2
- package/src/geometries/ico-sphere-geometry.ts +7 -6
- 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 +3 -3
- package/src/geometry/geometry.ts +79 -119
- package/src/geometry/gpu-geometry.ts +124 -0
- package/src/geometry/gpu-table.ts +41 -0
- package/src/index.ts +38 -12
- package/src/lib/clip-space.ts +22 -21
- package/src/lib/pipeline-factory.ts +60 -168
- package/src/model/model.ts +549 -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 +132 -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 -176
- 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 -179
- 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-alpha.
|
|
3
|
+
"version": "9.0.0-alpha.50",
|
|
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
|
+
"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
|
-
"
|
|
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-alpha.
|
|
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-alpha.50",
|
|
44
|
+
"@luma.gl/core": "9.0.0-alpha.50",
|
|
45
|
+
"@luma.gl/shadertools": "9.0.0-alpha.50",
|
|
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": "83899806fcfab67f97cc8b308f81e4844a05ca05"
|
|
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
|
|
@@ -27,7 +28,7 @@ export type AnimationOptions = {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
type Animation = {
|
|
30
|
-
channel
|
|
31
|
+
channel?: number;
|
|
31
32
|
animation: {
|
|
32
33
|
setTime: (time: number) => void
|
|
33
34
|
}
|
|
@@ -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 {
|
|
@@ -1,63 +1,65 @@
|
|
|
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;
|
|
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
|
+
|
|
37
|
+
|
|
34
38
|
const DEFAULT_ANIMATION_LOOP_PROPS: Required<AnimationLoopProps> = {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
device: null!,
|
|
40
|
+
|
|
41
|
+
onAddHTML: () => '',
|
|
42
|
+
onInitialize: async () => { return null; },
|
|
38
43
|
onRender: () => {},
|
|
39
44
|
onFinalize: () => {},
|
|
40
45
|
onError: (error) => console.error(error), // eslint-disable-line no-console
|
|
41
46
|
|
|
42
|
-
device: undefined,
|
|
43
|
-
deviceProps: {},
|
|
44
|
-
debug: false,
|
|
45
47
|
stats: luma.stats.get(`animation-loop-${statIdCounter++}`),
|
|
46
48
|
|
|
47
49
|
// view parameters
|
|
48
50
|
useDevicePixels: true,
|
|
49
|
-
autoResizeViewport:
|
|
50
|
-
autoResizeDrawingBuffer:
|
|
51
|
+
autoResizeViewport: false,
|
|
52
|
+
autoResizeDrawingBuffer: false,
|
|
51
53
|
};
|
|
52
54
|
|
|
53
55
|
/** Convenient animation loop */
|
|
54
|
-
export
|
|
55
|
-
device: Device;
|
|
56
|
-
canvas: HTMLCanvasElement
|
|
56
|
+
export class AnimationLoop {
|
|
57
|
+
device: Device | null = null;
|
|
58
|
+
canvas: HTMLCanvasElement | OffscreenCanvas | null = null;
|
|
57
59
|
|
|
58
60
|
props: Required<AnimationLoopProps>;
|
|
59
|
-
animationProps: AnimationProps;
|
|
60
|
-
timeline: Timeline = null;
|
|
61
|
+
animationProps: AnimationProps | null = null;
|
|
62
|
+
timeline: Timeline | null = null;
|
|
61
63
|
stats: Stats;
|
|
62
64
|
cpuTime: Stat;
|
|
63
65
|
gpuTime: Stat;
|
|
@@ -65,13 +67,13 @@ export default class AnimationLoop {
|
|
|
65
67
|
|
|
66
68
|
display: any;
|
|
67
69
|
|
|
68
|
-
needsRedraw: string |
|
|
70
|
+
needsRedraw: string | false = 'initialized';
|
|
69
71
|
|
|
70
72
|
_initialized: boolean = false;
|
|
71
73
|
_running: boolean = false;
|
|
72
|
-
_animationFrameId = null;
|
|
74
|
+
_animationFrameId: any = null;
|
|
73
75
|
_nextFramePromise: Promise<AnimationLoop> | null = null;
|
|
74
|
-
_resolveNextFrame: ((AnimationLoop) => void) | null = null;
|
|
76
|
+
_resolveNextFrame: ((animationLoop: AnimationLoop) => void) | null = null;
|
|
75
77
|
_cpuStartTime: number = 0;
|
|
76
78
|
|
|
77
79
|
// _gpuTimeQuery: Query | null = null;
|
|
@@ -79,18 +81,18 @@ export default class AnimationLoop {
|
|
|
79
81
|
/*
|
|
80
82
|
* @param {HTMLCanvasElement} canvas - if provided, width and height will be passed to context
|
|
81
83
|
*/
|
|
82
|
-
constructor(props: AnimationLoopProps
|
|
84
|
+
constructor(props: AnimationLoopProps) {
|
|
83
85
|
this.props = {...DEFAULT_ANIMATION_LOOP_PROPS, ...props};
|
|
84
86
|
props = this.props;
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
if (!props.device) {
|
|
89
|
+
throw new Error('No device provided');
|
|
90
|
+
}
|
|
87
91
|
|
|
88
|
-
|
|
89
|
-
this.device = props.device;
|
|
90
|
-
// @ts-expect-error
|
|
91
|
-
this.gl = (this.device && this.device.gl) || props.gl;
|
|
92
|
+
const {useDevicePixels = true} = this.props;
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
// state
|
|
95
|
+
this.stats = props.stats || new Stats({id: 'animation-loop-stats'});
|
|
94
96
|
this.cpuTime = this.stats.get('CPU Time');
|
|
95
97
|
this.gpuTime = this.stats.get('GPU Time');
|
|
96
98
|
this.frameRate = this.stats.get('Frame Rate');
|
|
@@ -125,15 +127,15 @@ export default class AnimationLoop {
|
|
|
125
127
|
}
|
|
126
128
|
|
|
127
129
|
// TODO - move to CanvasContext
|
|
128
|
-
setProps(props:
|
|
130
|
+
setProps(props: MutableAnimationLoopProps): this {
|
|
129
131
|
if ('autoResizeViewport' in props) {
|
|
130
|
-
this.props.autoResizeViewport = props.autoResizeViewport;
|
|
132
|
+
this.props.autoResizeViewport = props.autoResizeViewport || false;
|
|
131
133
|
}
|
|
132
134
|
if ('autoResizeDrawingBuffer' in props) {
|
|
133
|
-
this.props.autoResizeDrawingBuffer = props.autoResizeDrawingBuffer;
|
|
135
|
+
this.props.autoResizeDrawingBuffer = props.autoResizeDrawingBuffer || false;
|
|
134
136
|
}
|
|
135
137
|
if ('useDevicePixels' in props) {
|
|
136
|
-
this.props.useDevicePixels = props.useDevicePixels;
|
|
138
|
+
this.props.useDevicePixels = props.useDevicePixels || false;
|
|
137
139
|
}
|
|
138
140
|
return this;
|
|
139
141
|
}
|
|
@@ -146,20 +148,16 @@ export default 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)
|
|
162
|
-
await this.onInitialize(this.
|
|
160
|
+
await this.props.onInitialize(this._getAnimationProps());
|
|
163
161
|
}
|
|
164
162
|
|
|
165
163
|
// check that we haven't been stopped
|
|
@@ -185,16 +183,16 @@ export default class AnimationLoop {
|
|
|
185
183
|
|
|
186
184
|
/** Explicitly draw a frame */
|
|
187
185
|
redraw(): this {
|
|
188
|
-
if (this.device
|
|
186
|
+
if (this.device?.isLost) {
|
|
189
187
|
return this;
|
|
190
188
|
}
|
|
191
189
|
|
|
192
|
-
this.
|
|
190
|
+
this._beginFrameTimers();
|
|
193
191
|
|
|
194
192
|
this._setupFrame();
|
|
195
|
-
this.
|
|
193
|
+
this._updateAnimationProps();
|
|
196
194
|
|
|
197
|
-
this._renderFrame(this.
|
|
195
|
+
this._renderFrame(this._getAnimationProps());
|
|
198
196
|
|
|
199
197
|
// clear needsRedraw flag
|
|
200
198
|
this._clearNeedsRedraw();
|
|
@@ -205,7 +203,7 @@ export default class AnimationLoop {
|
|
|
205
203
|
this._resolveNextFrame = null;
|
|
206
204
|
}
|
|
207
205
|
|
|
208
|
-
this.
|
|
206
|
+
this._endFrameTimers();
|
|
209
207
|
|
|
210
208
|
return this;
|
|
211
209
|
}
|
|
@@ -215,7 +213,10 @@ export default class AnimationLoop {
|
|
|
215
213
|
// console.debug(`Stopping ${this.constructor.name}`);
|
|
216
214
|
if (this._running) {
|
|
217
215
|
// call callback
|
|
218
|
-
|
|
216
|
+
// If stop is called immediately, we can end up in a state where props haven't been initialized...
|
|
217
|
+
if (this.animationProps) {
|
|
218
|
+
this.props.onFinalize(this.animationProps);
|
|
219
|
+
}
|
|
219
220
|
|
|
220
221
|
this._cancelAnimationFrame();
|
|
221
222
|
this._nextFramePromise = null;
|
|
@@ -245,26 +246,13 @@ export default class AnimationLoop {
|
|
|
245
246
|
return this._nextFramePromise;
|
|
246
247
|
}
|
|
247
248
|
|
|
248
|
-
async toDataURL() {
|
|
249
|
+
async toDataURL(): Promise<string> {
|
|
249
250
|
this.setNeedsRedraw('toDataURL');
|
|
250
251
|
await this.waitForRender();
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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);
|
|
252
|
+
if (this.canvas instanceof HTMLCanvasElement) {
|
|
253
|
+
return this.canvas.toDataURL();
|
|
254
|
+
}
|
|
255
|
+
throw new Error('OffscreenCanvas');
|
|
268
256
|
}
|
|
269
257
|
|
|
270
258
|
// PRIVATE METHODS
|
|
@@ -273,8 +261,8 @@ export default class AnimationLoop {
|
|
|
273
261
|
this._startEventHandling();
|
|
274
262
|
|
|
275
263
|
// Initialize the callback data
|
|
276
|
-
this.
|
|
277
|
-
this.
|
|
264
|
+
this._initializeAnimationProps();
|
|
265
|
+
this._updateAnimationProps();
|
|
278
266
|
|
|
279
267
|
// Default viewport setup, in case onInitialize wants to render
|
|
280
268
|
this._resizeCanvasDrawingBuffer();
|
|
@@ -283,9 +271,9 @@ export default class AnimationLoop {
|
|
|
283
271
|
// this._gpuTimeQuery = Query.isSupported(this.gl, ['timers']) ? new Query(this.gl) : null;
|
|
284
272
|
}
|
|
285
273
|
|
|
286
|
-
_setDisplay(display) {
|
|
274
|
+
_setDisplay(display: any) {
|
|
287
275
|
if (this.display) {
|
|
288
|
-
this.display.
|
|
276
|
+
this.display.destroy();
|
|
289
277
|
this.display.animationLoop = null;
|
|
290
278
|
}
|
|
291
279
|
|
|
@@ -312,7 +300,7 @@ export default class AnimationLoop {
|
|
|
312
300
|
}
|
|
313
301
|
|
|
314
302
|
_cancelAnimationFrame() {
|
|
315
|
-
if (this._animationFrameId
|
|
303
|
+
if (this._animationFrameId === null) {
|
|
316
304
|
return;
|
|
317
305
|
}
|
|
318
306
|
|
|
@@ -322,7 +310,7 @@ export default class AnimationLoop {
|
|
|
322
310
|
// if (this.display && this.display.cancelAnimationFrame) {
|
|
323
311
|
// this.display.cancelAnimationFrame(this._animationFrameId);
|
|
324
312
|
// }
|
|
325
|
-
|
|
313
|
+
cancelAnimationFrame(this._animationFrameId);
|
|
326
314
|
this._animationFrameId = null;
|
|
327
315
|
}
|
|
328
316
|
|
|
@@ -336,20 +324,20 @@ export default class AnimationLoop {
|
|
|
336
324
|
|
|
337
325
|
// Called on each frame, can be overridden to call onRender multiple times
|
|
338
326
|
// to support e.g. stereoscopic rendering
|
|
339
|
-
_renderFrame(
|
|
327
|
+
_renderFrame(animationProps: AnimationProps) {
|
|
340
328
|
// Allow e.g. VR display to render multiple frames.
|
|
341
329
|
if (this.display) {
|
|
342
|
-
this.display._renderFrame(
|
|
330
|
+
this.display._renderFrame(animationProps);
|
|
343
331
|
return;
|
|
344
332
|
}
|
|
345
333
|
|
|
346
334
|
// call callback
|
|
347
|
-
this.onRender(
|
|
335
|
+
this.props.onRender(this._getAnimationProps());
|
|
348
336
|
// end callback
|
|
349
337
|
}
|
|
350
338
|
|
|
351
339
|
_clearNeedsRedraw() {
|
|
352
|
-
this.needsRedraw =
|
|
340
|
+
this.needsRedraw = false;
|
|
353
341
|
}
|
|
354
342
|
|
|
355
343
|
_setupFrame() {
|
|
@@ -358,16 +346,20 @@ export default class AnimationLoop {
|
|
|
358
346
|
}
|
|
359
347
|
|
|
360
348
|
// Initialize the object that will be passed to app callbacks
|
|
361
|
-
|
|
349
|
+
_initializeAnimationProps() {
|
|
350
|
+
if (!this.device) {
|
|
351
|
+
throw new Error('loop');
|
|
352
|
+
}
|
|
362
353
|
this.animationProps = {
|
|
363
354
|
animationLoop: this,
|
|
355
|
+
|
|
364
356
|
device: this.device,
|
|
365
|
-
canvas: this.device
|
|
357
|
+
canvas: this.device?.canvasContext?.canvas,
|
|
366
358
|
timeline: this.timeline,
|
|
367
359
|
|
|
368
360
|
// Initial values
|
|
369
361
|
useDevicePixels: this.props.useDevicePixels,
|
|
370
|
-
needsRedraw:
|
|
362
|
+
needsRedraw: false,
|
|
371
363
|
|
|
372
364
|
// Placeholders
|
|
373
365
|
width: 1,
|
|
@@ -386,8 +378,20 @@ export default class AnimationLoop {
|
|
|
386
378
|
};
|
|
387
379
|
}
|
|
388
380
|
|
|
381
|
+
_getAnimationProps(): AnimationProps {
|
|
382
|
+
if (!this.animationProps) {
|
|
383
|
+
throw new Error('animationProps');
|
|
384
|
+
}
|
|
385
|
+
return this.animationProps;
|
|
386
|
+
}
|
|
387
|
+
|
|
389
388
|
// Update the context object that will be passed to app callbacks
|
|
390
|
-
|
|
389
|
+
_updateAnimationProps(): void {
|
|
390
|
+
if (!this.animationProps) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Can this be replaced with canvas context?
|
|
391
395
|
const {width, height, aspect} = this._getSizeAndAspect();
|
|
392
396
|
if (width !== this.animationProps.width || height !== this.animationProps.height) {
|
|
393
397
|
this.setNeedsRedraw('drawing buffer resized');
|
|
@@ -418,13 +422,14 @@ export default class AnimationLoop {
|
|
|
418
422
|
: this.animationProps.engineTime;
|
|
419
423
|
}
|
|
420
424
|
|
|
421
|
-
/**
|
|
422
|
-
async
|
|
423
|
-
|
|
424
|
-
this.device
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
this.
|
|
425
|
+
/** Wait for supplied device */
|
|
426
|
+
async _initDevice() {
|
|
427
|
+
this.device = await this.props.device;
|
|
428
|
+
if (!this.device) {
|
|
429
|
+
throw new Error('No device provided');
|
|
430
|
+
}
|
|
431
|
+
this.canvas = this.device.canvasContext?.canvas || null;
|
|
432
|
+
// this._createInfoDiv();
|
|
428
433
|
}
|
|
429
434
|
|
|
430
435
|
_createInfoDiv() {
|
|
@@ -438,7 +443,9 @@ export default class AnimationLoop {
|
|
|
438
443
|
div.style.bottom = '10px';
|
|
439
444
|
div.style.width = '300px';
|
|
440
445
|
div.style.background = 'white';
|
|
441
|
-
|
|
446
|
+
if (this.canvas instanceof HTMLCanvasElement) {
|
|
447
|
+
wrapperDiv.appendChild(this.canvas);
|
|
448
|
+
}
|
|
442
449
|
wrapperDiv.appendChild(div);
|
|
443
450
|
const html = this.props.onAddHTML(div);
|
|
444
451
|
if (html) {
|
|
@@ -447,13 +454,16 @@ export default class AnimationLoop {
|
|
|
447
454
|
}
|
|
448
455
|
}
|
|
449
456
|
|
|
450
|
-
_getSizeAndAspect() {
|
|
457
|
+
_getSizeAndAspect(): {width: number; height: number; aspect: number} {
|
|
458
|
+
if (!this.device) {
|
|
459
|
+
return {width: 1, height: 1, aspect: 1};
|
|
460
|
+
}
|
|
451
461
|
// https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
|
|
452
|
-
const [width, height] = this.device
|
|
462
|
+
const [width, height] = this.device?.canvasContext?.getPixelSize() || [1, 1];
|
|
453
463
|
|
|
454
464
|
// https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
|
|
455
465
|
let aspect = 1;
|
|
456
|
-
const canvas = this.device
|
|
466
|
+
const canvas = this.device?.canvasContext?.canvas;
|
|
457
467
|
|
|
458
468
|
// @ts-expect-error
|
|
459
469
|
if (canvas && canvas.clientHeight) {
|
|
@@ -481,11 +491,11 @@ export default class AnimationLoop {
|
|
|
481
491
|
*/
|
|
482
492
|
_resizeCanvasDrawingBuffer() {
|
|
483
493
|
if (this.props.autoResizeDrawingBuffer) {
|
|
484
|
-
this.device
|
|
494
|
+
this.device?.canvasContext?.resize({useDevicePixels: this.props.useDevicePixels});
|
|
485
495
|
}
|
|
486
496
|
}
|
|
487
497
|
|
|
488
|
-
|
|
498
|
+
_beginFrameTimers() {
|
|
489
499
|
this.frameRate.timeEnd();
|
|
490
500
|
this.frameRate.timeStart();
|
|
491
501
|
|
|
@@ -505,10 +515,10 @@ export default class AnimationLoop {
|
|
|
505
515
|
// this._gpuTimeQuery.beginTimeElapsedQuery();
|
|
506
516
|
// }
|
|
507
517
|
|
|
508
|
-
|
|
518
|
+
this.cpuTime.timeStart();
|
|
509
519
|
}
|
|
510
520
|
|
|
511
|
-
|
|
521
|
+
_endFrameTimers() {
|
|
512
522
|
this.cpuTime.timeEnd();
|
|
513
523
|
|
|
514
524
|
// if (this._gpuTimeQuery) {
|
|
@@ -521,15 +531,18 @@ export default class AnimationLoop {
|
|
|
521
531
|
|
|
522
532
|
_startEventHandling() {
|
|
523
533
|
if (this.canvas) {
|
|
524
|
-
this.canvas.addEventListener('mousemove', this._onMousemove);
|
|
525
|
-
this.canvas.addEventListener('mouseleave', this._onMouseleave);
|
|
534
|
+
this.canvas.addEventListener('mousemove', this._onMousemove.bind(this));
|
|
535
|
+
this.canvas.addEventListener('mouseleave', this._onMouseleave.bind(this));
|
|
526
536
|
}
|
|
527
537
|
}
|
|
528
538
|
|
|
529
|
-
_onMousemove(
|
|
530
|
-
|
|
539
|
+
_onMousemove(event: Event) {
|
|
540
|
+
if (event instanceof MouseEvent) {
|
|
541
|
+
this._getAnimationProps()._mousePosition = [event.offsetX, event.offsetY];
|
|
542
|
+
}
|
|
531
543
|
}
|
|
532
|
-
|
|
533
|
-
|
|
544
|
+
|
|
545
|
+
_onMouseleave(event: Event) {
|
|
546
|
+
this._getAnimationProps()._mousePosition = null;
|
|
534
547
|
}
|
|
535
548
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {Device} from '@luma.gl/
|
|
1
|
+
import {Device} 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 = {
|
|
@@ -22,10 +22,10 @@ export type AnimationProps = {
|
|
|
22
22
|
tock: number;
|
|
23
23
|
|
|
24
24
|
// Initial values
|
|
25
|
-
needsRedraw?: string;
|
|
25
|
+
needsRedraw?: string | false;
|
|
26
26
|
|
|
27
|
-
timeline: Timeline;
|
|
27
|
+
timeline: Timeline | null;
|
|
28
28
|
|
|
29
29
|
// Experimental
|
|
30
|
-
_mousePosition?: [number, number]; // [offsetX, offsetY],
|
|
30
|
+
_mousePosition?: [number, number] | null; // [offsetX, offsetY],
|
|
31
31
|
};
|
|
@@ -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
|
+
}
|