@zcomponent/core 1.3.0-beta → 1.4.1-beta
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/lib/animation/clips/clip.d.ts +9 -4
- package/lib/animation/clips/clip.js +11 -8
- package/lib/animation/layerclip.d.ts +1 -0
- package/lib/animation/layerclip.js +19 -7
- package/lib/animation/tracks/cliptrack.d.ts +7 -3
- package/lib/animation/tracks/cliptrack.js +33 -10
- package/lib/animation/tracks/functiontrack.d.ts +32 -0
- package/lib/animation/tracks/functiontrack.js +95 -0
- package/lib/animation/tracks/streamtrack.d.ts +7 -4
- package/lib/animation/tracks/streamtrack.js +64 -47
- package/lib/animation/tracks/track.d.ts +1 -0
- package/lib/animation/tracks/track.js +25 -0
- package/lib/components/Audio.d.ts +6 -3
- package/lib/components/Audio.js +38 -12
- package/lib/data/animation.d.ts +1 -0
- package/lib/inflate.js +23 -0
- package/lib/selectors.d.ts +0 -1
- package/package.json +5 -5
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import * as Data from '../../data';
|
|
2
2
|
import { Observable } from '../../observable';
|
|
3
3
|
import { Animation } from '../animation';
|
|
4
|
+
import { LayerClip } from '../layerclip';
|
|
4
5
|
import { StreamState } from '../stream';
|
|
6
|
+
import { ClipTrack } from '../tracks/cliptrack';
|
|
7
|
+
import { FunctionTrack } from '../tracks/functiontrack';
|
|
8
|
+
import { StreamTrack } from '../tracks/streamtrack';
|
|
5
9
|
import { Track } from '../tracks/track';
|
|
6
10
|
export declare class Clip {
|
|
7
11
|
animation: Animation;
|
|
@@ -10,11 +14,12 @@ export declare class Clip {
|
|
|
10
14
|
readonly id?: string | undefined;
|
|
11
15
|
influencedPathsDirty: Observable<boolean, never>;
|
|
12
16
|
defaultFadeParameters?: Partial<Data.FadeParameters>;
|
|
17
|
+
/** @internal */
|
|
18
|
+
_streamTracks: (StreamTrack | ClipTrack | FunctionTrack)[];
|
|
13
19
|
private _influencedPaths;
|
|
14
20
|
private _tracksByPath;
|
|
15
21
|
private _tracksByPathDirty;
|
|
16
22
|
private _tracks;
|
|
17
|
-
private _streamTracks;
|
|
18
23
|
constructor(animation: Animation, length: number, scriptName?: string | undefined, id?: string | undefined);
|
|
19
24
|
computePathProperty(t: number, p: string, valueBefore: any, parentWeight?: number): any;
|
|
20
25
|
addTrack(t: Track): void;
|
|
@@ -26,7 +31,7 @@ export declare class Clip {
|
|
|
26
31
|
[id: string]: Partial<Data.FadeParameters>;
|
|
27
32
|
}): void;
|
|
28
33
|
resolveClipTime(t: number, t0: number, s0: number, rate: number, t1?: number): number;
|
|
29
|
-
streamPause(): void;
|
|
30
|
-
streamSeek(t: number): void;
|
|
31
|
-
streamTick(
|
|
34
|
+
streamPause(isActive: boolean, active: LayerClip | null | undefined): void;
|
|
35
|
+
streamSeek(t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined): void;
|
|
36
|
+
streamTick(clipState: StreamState, t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined, force?: boolean, parentWeight?: number): void;
|
|
32
37
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Observable } from '../../observable';
|
|
2
2
|
import { ClipTrack } from '../tracks/cliptrack';
|
|
3
|
+
import { FunctionTrack } from '../tracks/functiontrack';
|
|
3
4
|
import { PropertyTrack } from '../tracks/propertytrack';
|
|
4
5
|
import { StreamTrack } from '../tracks/streamtrack';
|
|
5
6
|
export class Clip {
|
|
@@ -9,11 +10,12 @@ export class Clip {
|
|
|
9
10
|
this.scriptName = scriptName;
|
|
10
11
|
this.id = id;
|
|
11
12
|
this.influencedPathsDirty = new Observable(false);
|
|
13
|
+
/** @internal */
|
|
14
|
+
this._streamTracks = [];
|
|
12
15
|
this._influencedPaths = [];
|
|
13
16
|
this._tracksByPath = new Map();
|
|
14
17
|
this._tracksByPathDirty = false;
|
|
15
18
|
this._tracks = [];
|
|
16
|
-
this._streamTracks = [];
|
|
17
19
|
this._dirty = (v) => {
|
|
18
20
|
if (v) {
|
|
19
21
|
this.influencedPathsDirty.value = true;
|
|
@@ -37,7 +39,7 @@ export class Clip {
|
|
|
37
39
|
t.influencedPathsDirty.addListener(this._dirty);
|
|
38
40
|
this.influencedPathsDirty.value = true;
|
|
39
41
|
this._tracksByPathDirty = true;
|
|
40
|
-
if (t instanceof StreamTrack || t instanceof ClipTrack)
|
|
42
|
+
if (t instanceof StreamTrack || t instanceof ClipTrack || t instanceof FunctionTrack)
|
|
41
43
|
this._streamTracks.push(t);
|
|
42
44
|
}
|
|
43
45
|
clearTracks() {
|
|
@@ -100,6 +102,7 @@ export class Clip {
|
|
|
100
102
|
}
|
|
101
103
|
}
|
|
102
104
|
resolveClipTime(t, t0, s0, rate, t1 = Infinity) {
|
|
105
|
+
// return this.resolveClipTimeLoops(t, t0, s0, rate, t1)[0];
|
|
103
106
|
if (this.length === 0)
|
|
104
107
|
return 0;
|
|
105
108
|
t = Math.min(t, t1);
|
|
@@ -113,19 +116,19 @@ export class Clip {
|
|
|
113
116
|
bounded += this.length;
|
|
114
117
|
return bounded;
|
|
115
118
|
}
|
|
116
|
-
streamPause() {
|
|
119
|
+
streamPause(isActive, active) {
|
|
117
120
|
for (const track of this._streamTracks) {
|
|
118
|
-
track.streamPause();
|
|
121
|
+
track.streamPause(isActive, active);
|
|
119
122
|
}
|
|
120
123
|
}
|
|
121
|
-
streamSeek(t) {
|
|
124
|
+
streamSeek(t, rate, isActive, active) {
|
|
122
125
|
for (const track of this._streamTracks) {
|
|
123
|
-
track.streamSeek(t);
|
|
126
|
+
track.streamSeek(t, rate, isActive, active);
|
|
124
127
|
}
|
|
125
128
|
}
|
|
126
|
-
streamTick(
|
|
129
|
+
streamTick(clipState, t, rate, isActive, active, force = false, parentWeight) {
|
|
127
130
|
for (const track of this._streamTracks) {
|
|
128
|
-
track.streamTick(
|
|
131
|
+
track.streamTick(clipState, t, rate, isActive, active, force, parentWeight);
|
|
129
132
|
}
|
|
130
133
|
}
|
|
131
134
|
}
|
|
@@ -21,6 +21,7 @@ export declare class LayerClip implements Stream {
|
|
|
21
21
|
private _loop;
|
|
22
22
|
private _lastTickTime;
|
|
23
23
|
private _lastClipTime;
|
|
24
|
+
private _lastLoop;
|
|
24
25
|
private _stopped;
|
|
25
26
|
state: StreamState;
|
|
26
27
|
constructor(layer: Layer, clip: Clip, scriptName?: string | undefined, id?: string | undefined);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AnimationEvents } from './animation';
|
|
2
2
|
import { StreamState } from './stream';
|
|
3
|
+
import { resolveClipTimeLoops } from './tracks/track';
|
|
3
4
|
export class LayerClip {
|
|
4
5
|
constructor(layer, clip, scriptName, id) {
|
|
5
6
|
this.layer = layer;
|
|
@@ -40,7 +41,11 @@ export class LayerClip {
|
|
|
40
41
|
this.pause();
|
|
41
42
|
this.state = StreamState.Ended;
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
+
else {
|
|
45
|
+
const [bt, loop] = resolveClipTimeLoops(t, t0, this._rate >= 0 ? 0 : this.clip.length, this._rate, this.clip.length, this._rate < 0, t1);
|
|
46
|
+
this.clip.streamTick(this.state, bt, this._rate, this.layer.active === this, this.layer.active, loop !== this._lastLoop, 1);
|
|
47
|
+
this._lastLoop = loop;
|
|
48
|
+
}
|
|
44
49
|
}
|
|
45
50
|
computePathProperty(p, valueBefore) {
|
|
46
51
|
const t = this._getTime();
|
|
@@ -71,7 +76,6 @@ export class LayerClip {
|
|
|
71
76
|
}
|
|
72
77
|
this._stopped = false;
|
|
73
78
|
this._loop = opts?.loop ?? this.defaultLoop;
|
|
74
|
-
this._rate = opts?.speed ?? this.defaultPlaySpeed;
|
|
75
79
|
const t = this._getTime();
|
|
76
80
|
if (this.state === StreamState.Ended) {
|
|
77
81
|
this._t0 = t;
|
|
@@ -79,7 +83,11 @@ export class LayerClip {
|
|
|
79
83
|
else if (this._pauseTime !== undefined) {
|
|
80
84
|
this._t0 = t - (this._pauseTime - this._t0);
|
|
81
85
|
}
|
|
86
|
+
if (Math.sign(this._rate) !== Math.sign(opts?.speed ?? 1)) {
|
|
87
|
+
this._t0 = 2 * t - this.clip.length - this._t0;
|
|
88
|
+
}
|
|
82
89
|
delete this._pauseTime;
|
|
90
|
+
this._rate = opts?.speed ?? this.defaultPlaySpeed;
|
|
83
91
|
if (this._loop)
|
|
84
92
|
this._t1 = Infinity;
|
|
85
93
|
else {
|
|
@@ -92,8 +100,6 @@ export class LayerClip {
|
|
|
92
100
|
}
|
|
93
101
|
const t0 = this._t0 + (t - (this._pauseTime ?? t));
|
|
94
102
|
const t1 = this._t1 + (t - (this._pauseTime ?? t));
|
|
95
|
-
const ct = this.clip.resolveClipTime(t, t0, this._rate >= 0 ? 0 : this.clip.length, this._rate, t1);
|
|
96
|
-
this.clip.streamTick(StreamState.Playing, ct, this._rate, true);
|
|
97
103
|
this.state = StreamState.Playing;
|
|
98
104
|
this.animation._pendingEvents.push({ evt: AnimationEvents.onLayerClipState, args: [this] });
|
|
99
105
|
this._lastClipTime = undefined;
|
|
@@ -102,14 +108,18 @@ export class LayerClip {
|
|
|
102
108
|
this.layer._activateLayerClip(this, opts);
|
|
103
109
|
this.layer._evaulate();
|
|
104
110
|
}
|
|
111
|
+
const [bt, loop] = resolveClipTimeLoops(t, t0, this._rate >= 0 ? 0 : this.clip.length, this._rate, this.clip.length, this._rate < 0, t1);
|
|
112
|
+
this.clip.streamTick(this.state, bt, this._rate, this.layer.active === this, this.layer.active, loop !== this._lastLoop, 1);
|
|
113
|
+
this._lastLoop = loop;
|
|
105
114
|
}
|
|
106
115
|
pause() {
|
|
116
|
+
delete this._lastLoop;
|
|
107
117
|
if (this._pauseTime !== undefined || this.state !== StreamState.Playing)
|
|
108
118
|
return;
|
|
109
119
|
this.state = StreamState.Paused;
|
|
110
120
|
this.animation._pendingEvents.push({ evt: AnimationEvents.onLayerClipState, args: [this] });
|
|
111
121
|
this._pauseTime = this._getTime();
|
|
112
|
-
this.clip.streamPause();
|
|
122
|
+
this.clip.streamPause(this.layer.active === this, this.layer.active);
|
|
113
123
|
}
|
|
114
124
|
seek(ct, opts) {
|
|
115
125
|
const t = this._getTime();
|
|
@@ -132,7 +142,8 @@ export class LayerClip {
|
|
|
132
142
|
if (this.layer.active !== this && !opts?.dontActivateLayer) {
|
|
133
143
|
this.layer._activateLayerClip(this, { fade: opts?.fade });
|
|
134
144
|
}
|
|
135
|
-
this.
|
|
145
|
+
delete this._lastLoop;
|
|
146
|
+
this.clip.streamSeek(ct, this._rate, this.layer.active === this, this.layer.active);
|
|
136
147
|
this.layer._evaulate();
|
|
137
148
|
}
|
|
138
149
|
/** @internal */
|
|
@@ -178,8 +189,9 @@ export class LayerClip {
|
|
|
178
189
|
this._pauseTime = this._t0;
|
|
179
190
|
this._lastClipTime = undefined;
|
|
180
191
|
this._lastTickTime = undefined;
|
|
192
|
+
delete this._lastLoop;
|
|
181
193
|
this._rate = 1;
|
|
182
|
-
this.clip.streamTick(StreamState.Ended, this._t0, 1, true);
|
|
194
|
+
this.clip.streamTick(StreamState.Ended, this._t0, 1, this.layer.active === this, this.layer.active, true);
|
|
183
195
|
this.state = StreamState.Ended;
|
|
184
196
|
this.animation._pendingEvents.push({ evt: AnimationEvents.onLayerClipState, args: [this] });
|
|
185
197
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ClipTrackEntity } from '../../data';
|
|
2
2
|
import { Clip } from '../clips/clip';
|
|
3
3
|
import { Keyframe } from '../keyframe';
|
|
4
|
+
import { LayerClip } from '../layerclip';
|
|
4
5
|
import { StreamState } from '../stream';
|
|
5
6
|
import { Track } from './track';
|
|
6
7
|
export declare class ClipTrack extends Track {
|
|
@@ -11,6 +12,8 @@ export declare class ClipTrack extends Track {
|
|
|
11
12
|
private _entities;
|
|
12
13
|
private _entitiesById;
|
|
13
14
|
private _entitiesDirty;
|
|
15
|
+
private _lastTick?;
|
|
16
|
+
private _lastLoopNumber?;
|
|
14
17
|
constructor(clip: Clip, id?: string);
|
|
15
18
|
get influencedPaths(): string[];
|
|
16
19
|
addWeight(k: Keyframe): void;
|
|
@@ -24,7 +27,8 @@ export declare class ClipTrack extends Track {
|
|
|
24
27
|
}): void;
|
|
25
28
|
get sortedBlocks(): ClipTrackEntity[];
|
|
26
29
|
computePathProperty(t: number, p: string, valueBefore: any, parentWeight?: number): any;
|
|
27
|
-
streamPause(): void;
|
|
28
|
-
streamSeek(t: number): void;
|
|
29
|
-
streamTick(clipState: StreamState, t: number, rate: number, force?: boolean, parentWeight?: number): void;
|
|
30
|
+
streamPause(isActive: boolean, active: LayerClip | null | undefined): void;
|
|
31
|
+
streamSeek(t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined): void;
|
|
32
|
+
streamTick(clipState: StreamState, t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined, force?: boolean, parentWeight?: number): void;
|
|
33
|
+
private _resolveBlock;
|
|
30
34
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolveKeyframes, resolveKeyframeValue, Track } from './track';
|
|
1
|
+
import { resolveClipTimeLoops, resolveKeyframes, resolveKeyframeValue, Track } from './track';
|
|
2
2
|
export class ClipTrack extends Track {
|
|
3
3
|
constructor(clip, id) {
|
|
4
4
|
super(clip.animation, id);
|
|
@@ -65,29 +65,52 @@ export class ClipTrack extends Track {
|
|
|
65
65
|
}
|
|
66
66
|
return valueBefore;
|
|
67
67
|
}
|
|
68
|
-
streamPause() {
|
|
69
|
-
this.clip.streamPause();
|
|
68
|
+
streamPause(isActive, active) {
|
|
69
|
+
this.clip.streamPause(isActive, active);
|
|
70
70
|
}
|
|
71
|
-
streamSeek(t) {
|
|
71
|
+
streamSeek(t, rate, isActive, active) {
|
|
72
72
|
const blocks = this.sortedBlocks;
|
|
73
73
|
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
74
74
|
const block = blocks[i];
|
|
75
75
|
if (block.t0 > t)
|
|
76
76
|
continue;
|
|
77
77
|
const ct = this.clip.resolveClipTime(t, block.t0, block.s0, block.rate, block.t1);
|
|
78
|
-
this.clip.streamSeek(ct);
|
|
78
|
+
this.clip.streamSeek(ct, rate, isActive, active);
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
streamTick(clipState, t, rate, force = false, parentWeight) {
|
|
82
|
+
streamTick(clipState, t, rate, isActive, active, force = false, parentWeight) {
|
|
83
|
+
if (force)
|
|
84
|
+
delete this._lastLoopNumber;
|
|
85
|
+
const block = this._resolveBlock(t, rate);
|
|
86
|
+
const lastBlock = this._lastTick === undefined ? undefined : this._resolveBlock(this._lastTick, rate);
|
|
87
|
+
this._lastTick = t;
|
|
88
|
+
if (!block) {
|
|
89
|
+
this.clip.streamPause(isActive, active);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
const [bt, loopNumber] = resolveClipTimeLoops(t, block.t0, block.s0, block.rate, this.clip.length, (rate * block.rate) < 0, block.t1);
|
|
93
|
+
if ((t === block.t1 && rate >= +0) || (t === block.t0 && rate < 0)) {
|
|
94
|
+
this.clip.streamPause(isActive, active);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.clip.streamTick(clipState, bt, rate * block.rate, isActive, active, this._lastLoopNumber !== loopNumber || block !== lastBlock, parentWeight);
|
|
98
|
+
this._lastLoopNumber = loopNumber;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
_resolveBlock(t, rate) {
|
|
83
103
|
const blocks = this.sortedBlocks;
|
|
84
104
|
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
85
105
|
const block = blocks[i];
|
|
86
|
-
if (block.t0 > t)
|
|
106
|
+
if (rate >= +0 && block.t0 > t)
|
|
87
107
|
continue;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
108
|
+
if (rate < 0 && block.t0 >= t)
|
|
109
|
+
continue;
|
|
110
|
+
if (block.t1 !== undefined && block.t1 < t && rate >= +0)
|
|
111
|
+
return undefined;
|
|
112
|
+
return block;
|
|
91
113
|
}
|
|
114
|
+
return undefined;
|
|
92
115
|
}
|
|
93
116
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ByID } from '../../data';
|
|
2
|
+
import { Animation } from '../animation';
|
|
3
|
+
import { LayerClip } from '../layerclip';
|
|
4
|
+
import { StreamState } from '../stream';
|
|
5
|
+
import { Track } from './track';
|
|
6
|
+
export interface ResolvedFunctionTrackEntity {
|
|
7
|
+
id: string;
|
|
8
|
+
obj: any;
|
|
9
|
+
func: (...args: any[]) => any;
|
|
10
|
+
t0: number;
|
|
11
|
+
args: ByID<any>;
|
|
12
|
+
}
|
|
13
|
+
export declare class FunctionTrack extends Track {
|
|
14
|
+
readonly animation: Animation;
|
|
15
|
+
private _entities;
|
|
16
|
+
private _entitiesById;
|
|
17
|
+
private _entitiesDirty;
|
|
18
|
+
private _lastTick?;
|
|
19
|
+
constructor(animation: Animation);
|
|
20
|
+
get influencedPaths(): string[];
|
|
21
|
+
computePathProperty(t: number, p: string, valueBefore: any, parentWeight?: number): any;
|
|
22
|
+
addBlock(k: ResolvedFunctionTrackEntity): void;
|
|
23
|
+
setBlocksById(weights: {
|
|
24
|
+
[id: string]: ResolvedFunctionTrackEntity;
|
|
25
|
+
}): void;
|
|
26
|
+
get sortedBlocks(): ResolvedFunctionTrackEntity[];
|
|
27
|
+
streamSeek(t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined): void;
|
|
28
|
+
streamTick(clipState: StreamState, t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined, force?: boolean, parentWeight?: number): void;
|
|
29
|
+
streamPause(isActive: boolean, active: LayerClip | null | undefined): void;
|
|
30
|
+
private _resolveBlocksBetween;
|
|
31
|
+
private _getBoundedT;
|
|
32
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Track } from './track';
|
|
2
|
+
export class FunctionTrack extends Track {
|
|
3
|
+
constructor(animation) {
|
|
4
|
+
super(animation);
|
|
5
|
+
this.animation = animation;
|
|
6
|
+
this._entities = [];
|
|
7
|
+
this._entitiesById = {};
|
|
8
|
+
this._entitiesDirty = false;
|
|
9
|
+
}
|
|
10
|
+
get influencedPaths() {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
computePathProperty(t, p, valueBefore, parentWeight) {
|
|
14
|
+
// n/a
|
|
15
|
+
}
|
|
16
|
+
addBlock(k) {
|
|
17
|
+
this._entitiesById[k.id] = k;
|
|
18
|
+
this._entitiesDirty = true;
|
|
19
|
+
}
|
|
20
|
+
setBlocksById(weights) {
|
|
21
|
+
this._entitiesById = weights;
|
|
22
|
+
this._entitiesDirty = true;
|
|
23
|
+
}
|
|
24
|
+
get sortedBlocks() {
|
|
25
|
+
if (!this._entitiesDirty)
|
|
26
|
+
return this._entities;
|
|
27
|
+
this._entities = Object.values(this._entitiesById);
|
|
28
|
+
this._entities.sort((a, b) => a.t0 - b.t0);
|
|
29
|
+
this._entitiesDirty = false;
|
|
30
|
+
return this._entities;
|
|
31
|
+
}
|
|
32
|
+
streamSeek(t, rate, isActive, active) {
|
|
33
|
+
this._lastTick = t;
|
|
34
|
+
}
|
|
35
|
+
streamTick(clipState, t, rate, isActive, active, force = false, parentWeight) {
|
|
36
|
+
// if (clipState !== StreamState.Playing || this._lastTick === undefined) {
|
|
37
|
+
// this._lastTick = t;
|
|
38
|
+
// return;
|
|
39
|
+
// }
|
|
40
|
+
// if (this._lastTick === undefined) {
|
|
41
|
+
// this._lastTick = rate > +0 ? 0 : clipLength;
|
|
42
|
+
// }
|
|
43
|
+
// const blocks = this._resolveBlocksBetween(this._lastTick, t, rate, clipLength);
|
|
44
|
+
// for (const block of blocks) {
|
|
45
|
+
// const args: any[] = [];
|
|
46
|
+
// for (let i = 0; i < block.args.length; i++) {
|
|
47
|
+
// args[i] = block.args[i];
|
|
48
|
+
// }
|
|
49
|
+
// block.func.call(block.obj, ...args);
|
|
50
|
+
// }
|
|
51
|
+
// this._lastTick = t;
|
|
52
|
+
}
|
|
53
|
+
streamPause(isActive, active) {
|
|
54
|
+
}
|
|
55
|
+
_resolveBlocksBetween(tstart, tend, rate, clipLength) {
|
|
56
|
+
const blocks = this.sortedBlocks;
|
|
57
|
+
if (rate < 0) {
|
|
58
|
+
const tmp = tstart;
|
|
59
|
+
tstart = tend;
|
|
60
|
+
tend = tmp;
|
|
61
|
+
}
|
|
62
|
+
const [boundedEnd, loopNoEnd] = this._getBoundedT(tend, clipLength, rate);
|
|
63
|
+
let [bounded, loopNo] = this._getBoundedT(tstart, clipLength, rate);
|
|
64
|
+
const ret = [];
|
|
65
|
+
while (loopNo < loopNoEnd || (loopNo === loopNoEnd && bounded <= boundedEnd)) {
|
|
66
|
+
const t1 = (loopNoEnd > loopNo) ? Infinity : boundedEnd;
|
|
67
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
68
|
+
const b = blocks[i];
|
|
69
|
+
if (b.t0 >= bounded && b.t0 <= t1) {
|
|
70
|
+
ret.push(b);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (loopNo >= loopNoEnd) {
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
// Move to the start of the next loop
|
|
77
|
+
loopNo++;
|
|
78
|
+
bounded = 0;
|
|
79
|
+
}
|
|
80
|
+
return ret;
|
|
81
|
+
}
|
|
82
|
+
_getBoundedT(ct, clipLength, rate) {
|
|
83
|
+
let t = ct;
|
|
84
|
+
let loop = 0;
|
|
85
|
+
while (t >= clipLength) {
|
|
86
|
+
t -= clipLength;
|
|
87
|
+
loop++;
|
|
88
|
+
}
|
|
89
|
+
while (t < 0) {
|
|
90
|
+
t += clipLength;
|
|
91
|
+
loop++;
|
|
92
|
+
}
|
|
93
|
+
return [t, loop];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { StreamTrackEntity } from '../../data';
|
|
2
2
|
import { Animation } from '../animation';
|
|
3
3
|
import { Keyframe } from '../keyframe';
|
|
4
|
+
import { LayerClip } from '../layerclip';
|
|
4
5
|
import { Stream, StreamState } from '../stream';
|
|
5
6
|
import { Track } from './track';
|
|
6
7
|
export declare class StreamTrack extends Track {
|
|
@@ -16,6 +17,7 @@ export declare class StreamTrack extends Track {
|
|
|
16
17
|
private _weightsDirty;
|
|
17
18
|
private _lastTick?;
|
|
18
19
|
private _lastLoopNumber?;
|
|
20
|
+
private _lastState;
|
|
19
21
|
private _lastRate;
|
|
20
22
|
constructor(animation: Animation, _entity: any, _property: (string | number)[]);
|
|
21
23
|
get influencedPaths(): string[];
|
|
@@ -30,10 +32,11 @@ export declare class StreamTrack extends Track {
|
|
|
30
32
|
[id: string]: StreamTrackEntity;
|
|
31
33
|
}): void;
|
|
32
34
|
get sortedBlocks(): StreamTrackEntity[];
|
|
33
|
-
streamPause(): void;
|
|
34
|
-
streamSeek(t: number): void;
|
|
35
|
-
|
|
35
|
+
streamPause(isActive: boolean, active: LayerClip | null | undefined): void;
|
|
36
|
+
streamSeek(t: number, resolvedRate: number, isActive: boolean, active: LayerClip | null | undefined): void;
|
|
37
|
+
private _isPlayingInClip;
|
|
38
|
+
private _isPlayingInLayerClip;
|
|
39
|
+
streamTick(clipState: StreamState, t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined, force?: boolean, parentWeight?: number): void;
|
|
36
40
|
private _applyState;
|
|
37
41
|
private _resolveBlock;
|
|
38
|
-
private _resolveBlockTime;
|
|
39
42
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { StreamState } from '../stream';
|
|
2
|
-
import {
|
|
2
|
+
import { ClipTrack } from './cliptrack';
|
|
3
|
+
import { resolveClipTimeLoops, Track } from './track';
|
|
3
4
|
export class StreamTrack extends Track {
|
|
4
5
|
constructor(animation, _entity, _property) {
|
|
5
6
|
super(animation);
|
|
@@ -12,7 +13,6 @@ export class StreamTrack extends Track {
|
|
|
12
13
|
this._weights = [];
|
|
13
14
|
this._weightsById = {};
|
|
14
15
|
this._weightsDirty = false;
|
|
15
|
-
this._lastRate = 1;
|
|
16
16
|
}
|
|
17
17
|
get influencedPaths() {
|
|
18
18
|
return [];
|
|
@@ -60,47 +60,76 @@ export class StreamTrack extends Track {
|
|
|
60
60
|
this._entitiesDirty = false;
|
|
61
61
|
return this._entities;
|
|
62
62
|
}
|
|
63
|
-
streamPause() {
|
|
63
|
+
streamPause(isActive, active) {
|
|
64
|
+
if (!isActive && this._isPlayingInLayerClip(active)) {
|
|
65
|
+
delete this._lastLoopNumber;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (this._lastState === StreamState.Paused)
|
|
69
|
+
return;
|
|
64
70
|
this.stream?.pause();
|
|
71
|
+
this._lastState = StreamState.Paused;
|
|
65
72
|
}
|
|
66
|
-
streamSeek(t) {
|
|
67
|
-
|
|
73
|
+
streamSeek(t, resolvedRate, isActive, active) {
|
|
74
|
+
if (!isActive && this._isPlayingInLayerClip(active)) {
|
|
75
|
+
delete this._lastLoopNumber;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const blockNow = this._resolveBlock(t, 1);
|
|
68
79
|
if (!blockNow)
|
|
69
80
|
return;
|
|
70
|
-
const [bt, loopNumber] =
|
|
81
|
+
const [bt, loopNumber] = resolveClipTimeLoops(t, blockNow.t0, blockNow.s0, blockNow.rate, this.stream?.length?.() ?? Infinity, (resolvedRate * blockNow.rate) < 0, blockNow.t1);
|
|
71
82
|
this.stream?.seek(bt);
|
|
72
83
|
this._lastLoopNumber = loopNumber;
|
|
73
84
|
}
|
|
74
|
-
|
|
75
|
-
let
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
85
|
+
_isPlayingInClip(stream, clip) {
|
|
86
|
+
for (let s of clip._streamTracks) {
|
|
87
|
+
if (s instanceof StreamTrack && s.stream === stream)
|
|
88
|
+
return true;
|
|
89
|
+
if (s instanceof ClipTrack && this._isPlayingInClip(stream, s.clip))
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
_isPlayingInLayerClip(layerClip) {
|
|
95
|
+
if (!layerClip)
|
|
96
|
+
return false;
|
|
97
|
+
const stream = this.stream;
|
|
98
|
+
if (!stream)
|
|
99
|
+
return false;
|
|
100
|
+
return this._isPlayingInClip(stream, layerClip.clip);
|
|
101
|
+
}
|
|
102
|
+
streamTick(clipState, t, rate, isActive, active, force = false, parentWeight) {
|
|
103
|
+
if (!isActive && this._isPlayingInLayerClip(active)) {
|
|
104
|
+
delete this._lastLoopNumber;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (force)
|
|
108
|
+
delete this._lastLoopNumber;
|
|
109
|
+
const block = this._resolveBlock(t, rate);
|
|
110
|
+
let desiredState = clipState;
|
|
111
|
+
const lastBlock = this._lastTick === undefined ? undefined : this._resolveBlock(this._lastTick, rate);
|
|
81
112
|
this._lastTick = t;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
113
|
+
if (!block) {
|
|
114
|
+
desiredState = StreamState.Paused;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
const [bt, loopNumber] = resolveClipTimeLoops(t, block.t0, block.s0, block.rate, this.stream?.length?.() ?? Infinity, (rate * block.rate) < 0, block.t1);
|
|
118
|
+
if ((t === block.t1 && rate >= +0) || (t === block.t0 && rate < 0)) {
|
|
86
119
|
desiredState = StreamState.Paused;
|
|
87
|
-
|
|
88
|
-
const [bt, loopNumber] = this._resolveBlockTime(t, blockNow.t0, blockNow.s0, blockNow.rate, blockNow.t1);
|
|
89
|
-
this._lastLoopNumber = loopNumber;
|
|
90
|
-
this.stream?.seek(bt);
|
|
120
|
+
force = true;
|
|
91
121
|
}
|
|
92
|
-
this.
|
|
93
|
-
}
|
|
94
|
-
if (blockNow) {
|
|
95
|
-
const [bt, loopNumber] = this._resolveBlockTime(t, blockNow.t0, blockNow.s0, blockNow.rate, blockNow.t1);
|
|
96
|
-
if (loopNumber !== this._lastLoopNumber) {
|
|
97
|
-
console.log('Loop number changed', loopNumber, 'last', this._lastLoopNumber, 'seek', bt);
|
|
122
|
+
else if (this._lastLoopNumber !== loopNumber || lastBlock !== block) {
|
|
98
123
|
this._lastLoopNumber = loopNumber;
|
|
124
|
+
force = true;
|
|
99
125
|
this.stream?.seek(bt);
|
|
100
126
|
}
|
|
101
127
|
}
|
|
128
|
+
this._applyState(desiredState, (block?.rate ?? 1) * rate, force);
|
|
102
129
|
}
|
|
103
|
-
_applyState(s, rate) {
|
|
130
|
+
_applyState(s, rate, force) {
|
|
131
|
+
if (s === this._lastState && !force && (s !== StreamState.Playing || this._lastRate === rate))
|
|
132
|
+
return;
|
|
104
133
|
switch (s) {
|
|
105
134
|
case StreamState.Playing:
|
|
106
135
|
this.stream?.play({ speed: rate });
|
|
@@ -112,33 +141,21 @@ export class StreamTrack extends Track {
|
|
|
112
141
|
this.stream?.stop();
|
|
113
142
|
break;
|
|
114
143
|
}
|
|
144
|
+
this._lastState = s;
|
|
145
|
+
this._lastRate = rate;
|
|
115
146
|
}
|
|
116
|
-
_resolveBlock(t) {
|
|
147
|
+
_resolveBlock(t, rate) {
|
|
117
148
|
const blocks = this.sortedBlocks;
|
|
118
149
|
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
119
150
|
const block = blocks[i];
|
|
120
|
-
if (block.t0 > t)
|
|
151
|
+
if (rate >= +0 && block.t0 > t)
|
|
121
152
|
continue;
|
|
122
|
-
if (
|
|
153
|
+
if (rate < 0 && block.t0 >= t)
|
|
154
|
+
continue;
|
|
155
|
+
if (block.t1 !== undefined && block.t1 < t && rate >= +0)
|
|
123
156
|
return undefined;
|
|
124
157
|
return block;
|
|
125
158
|
}
|
|
126
159
|
return undefined;
|
|
127
160
|
}
|
|
128
|
-
_resolveBlockTime(t, t0, s0, rate, t1 = Infinity) {
|
|
129
|
-
const length = this.stream?.length?.() ?? Infinity;
|
|
130
|
-
if (length === 0)
|
|
131
|
-
return [0, 0];
|
|
132
|
-
t = Math.min(t, t1);
|
|
133
|
-
const ct = s0 + (t - t0) * rate;
|
|
134
|
-
const loopNumber = Math.floor(ct / length);
|
|
135
|
-
let bounded = ct % length;
|
|
136
|
-
if (bounded < 0)
|
|
137
|
-
bounded += length;
|
|
138
|
-
if (bounded === 0 && rate >= +0 && t === t1)
|
|
139
|
-
bounded += length;
|
|
140
|
-
if (bounded === 0 && rate < 0 && t === t0)
|
|
141
|
-
bounded += length;
|
|
142
|
-
return [bounded, loopNumber];
|
|
143
|
-
}
|
|
144
161
|
}
|
|
@@ -10,3 +10,4 @@ export declare abstract class Track {
|
|
|
10
10
|
}
|
|
11
11
|
export declare function resolveKeyframeValue(t: number, before: Keyframe, after: Keyframe | undefined): any;
|
|
12
12
|
export declare function resolveKeyframes(keyframes: Keyframe[], t: number): [before: Keyframe | undefined, after: Keyframe | undefined];
|
|
13
|
+
export declare function resolveClipTimeLoops(t: number, t0: number, s0: number, rate: number, length: number, timeBackwards: boolean, t1?: number): [ct: number, loop: number];
|
|
@@ -31,3 +31,28 @@ export function resolveKeyframes(keyframes, t) {
|
|
|
31
31
|
}
|
|
32
32
|
return [keyframeBefore, keyframeAfter];
|
|
33
33
|
}
|
|
34
|
+
export function resolveClipTimeLoops(t, t0, s0, rate, length, timeBackwards, t1 = Infinity) {
|
|
35
|
+
if (length === 0)
|
|
36
|
+
return [0, 0];
|
|
37
|
+
t = Math.min(t, t1);
|
|
38
|
+
let ct = s0 + (t - t0) * rate;
|
|
39
|
+
let loop = 0;
|
|
40
|
+
// if (rate < 0) ct += length;
|
|
41
|
+
while ((ct >= length && !timeBackwards) || (ct > length && timeBackwards)) {
|
|
42
|
+
ct -= length;
|
|
43
|
+
loop++;
|
|
44
|
+
}
|
|
45
|
+
while ((ct < 0 && !timeBackwards) || (ct <= 0 && timeBackwards)) {
|
|
46
|
+
ct += length;
|
|
47
|
+
loop++;
|
|
48
|
+
}
|
|
49
|
+
if (ct === 0 && !timeBackwards && t === t1) {
|
|
50
|
+
ct += length;
|
|
51
|
+
loop--;
|
|
52
|
+
}
|
|
53
|
+
if (ct === 0 && timeBackwards && t === t1) {
|
|
54
|
+
ct += length;
|
|
55
|
+
loop--;
|
|
56
|
+
}
|
|
57
|
+
return [ct, loop];
|
|
58
|
+
}
|
|
@@ -29,17 +29,20 @@ export declare class Audio extends Component<undefined, AudioConstructorProps> i
|
|
|
29
29
|
destination: AudioNode;
|
|
30
30
|
audioBuffer?: AudioBuffer;
|
|
31
31
|
private _gain;
|
|
32
|
+
private _reversed?;
|
|
32
33
|
private _playhead;
|
|
34
|
+
private _rate;
|
|
33
35
|
private _session?;
|
|
36
|
+
constructor(mgr: ContextManager, props: AudioConstructorProps);
|
|
37
|
+
private _load;
|
|
38
|
+
private _updateVolume;
|
|
34
39
|
/** @zprop
|
|
35
40
|
* @zdefault false
|
|
36
41
|
* @zgroup Audio
|
|
37
42
|
* @zgrouppriority 20
|
|
38
43
|
*/
|
|
39
44
|
muted: Observable<boolean, never>;
|
|
40
|
-
|
|
41
|
-
private _load;
|
|
42
|
-
private _updateVolume;
|
|
45
|
+
private _getReversed;
|
|
43
46
|
/**
|
|
44
47
|
* @zprop
|
|
45
48
|
* @ztype proportion
|
package/lib/components/Audio.js
CHANGED
|
@@ -14,15 +14,16 @@ export class Audio extends Component {
|
|
|
14
14
|
constructor(mgr, props) {
|
|
15
15
|
super(mgr, props);
|
|
16
16
|
this._playhead = 0;
|
|
17
|
+
this._rate = 1;
|
|
18
|
+
this._updateVolume = () => {
|
|
19
|
+
this._gain.gain.value = this.muted.value === true ? 0 : this.volume.value;
|
|
20
|
+
};
|
|
17
21
|
/** @zprop
|
|
18
22
|
* @zdefault false
|
|
19
23
|
* @zgroup Audio
|
|
20
24
|
* @zgrouppriority 20
|
|
21
25
|
*/
|
|
22
|
-
this.muted = new Observable(false);
|
|
23
|
-
this._updateVolume = () => {
|
|
24
|
-
this._gain.gain.value = this.muted.value === true ? 0 : this.volume.value;
|
|
25
|
-
};
|
|
26
|
+
this.muted = new Observable(false, this._updateVolume);
|
|
26
27
|
/**
|
|
27
28
|
* @zprop
|
|
28
29
|
* @ztype proportion
|
|
@@ -46,20 +47,43 @@ export class Audio extends Component {
|
|
|
46
47
|
const audioContext = useAudioContext(this.contextManager);
|
|
47
48
|
this.audioBuffer = await audioContext.decodeAudioData(data);
|
|
48
49
|
}
|
|
50
|
+
_getReversed(inp) {
|
|
51
|
+
if (!this._reversed) {
|
|
52
|
+
const audioContext = useAudioContext(this.contextManager);
|
|
53
|
+
this._reversed = audioContext.createBuffer(inp.numberOfChannels, inp.length, inp.sampleRate);
|
|
54
|
+
for (let i = 0; i < inp.numberOfChannels; i++) {
|
|
55
|
+
const source = inp.getChannelData(i);
|
|
56
|
+
const destination = this._reversed.getChannelData(i);
|
|
57
|
+
for (let j = 0; j < inp.length; j++) {
|
|
58
|
+
destination[j] = source[inp.length - j];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return this._reversed;
|
|
63
|
+
}
|
|
49
64
|
/** @zprop */
|
|
50
65
|
play(opts) {
|
|
51
66
|
if (!this.audioBuffer)
|
|
52
67
|
return;
|
|
53
68
|
if (this._session)
|
|
54
|
-
this.
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
this.pause();
|
|
70
|
+
this._rate = opts?.speed ?? 1;
|
|
71
|
+
let resolvedPlayhead = this._playhead;
|
|
72
|
+
if (this._rate >= +0) {
|
|
73
|
+
if (this._playhead >= this.audioBuffer.duration)
|
|
74
|
+
this._playhead = 0;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
if (this._playhead <= 0)
|
|
78
|
+
this._playhead = this.audioBuffer.duration;
|
|
79
|
+
resolvedPlayhead = Math.max(this.audioBuffer.duration - this._playhead, 0);
|
|
80
|
+
}
|
|
57
81
|
const source = this.audioContext.createBufferSource();
|
|
58
|
-
source.
|
|
59
|
-
source.
|
|
82
|
+
source.playbackRate.value = Math.abs(this._rate);
|
|
83
|
+
source.buffer = this._rate < 0 ? this._getReversed(this.audioBuffer) : this.audioBuffer;
|
|
60
84
|
source.connect(this.destination);
|
|
61
|
-
const startedAt = this.audioContext.currentTime - (
|
|
62
|
-
source.start(0,
|
|
85
|
+
const startedAt = this.audioContext.currentTime - (resolvedPlayhead / source.playbackRate.value);
|
|
86
|
+
source.start(0, resolvedPlayhead);
|
|
63
87
|
this._session = { source, startedAt };
|
|
64
88
|
}
|
|
65
89
|
/** @zprop */
|
|
@@ -67,6 +91,8 @@ export class Audio extends Component {
|
|
|
67
91
|
if (!this._session)
|
|
68
92
|
return;
|
|
69
93
|
this._playhead = this._session.source.playbackRate.value * (this.audioContext.currentTime - this._session.startedAt);
|
|
94
|
+
if (this._rate < 0)
|
|
95
|
+
this._playhead = (this.audioBuffer?.length ?? 0) - this._playhead;
|
|
70
96
|
this._session.source.stop();
|
|
71
97
|
this._session.source.disconnect();
|
|
72
98
|
delete this._session;
|
|
@@ -83,7 +109,7 @@ export class Audio extends Component {
|
|
|
83
109
|
this.pause();
|
|
84
110
|
this._playhead = t / 1000;
|
|
85
111
|
if (previousSession)
|
|
86
|
-
this.play({ speed:
|
|
112
|
+
this.play({ speed: this._rate });
|
|
87
113
|
}
|
|
88
114
|
length() {
|
|
89
115
|
return this.audioBuffer ? (this.audioBuffer.duration * 1000) : undefined;
|
package/lib/data/animation.d.ts
CHANGED
package/lib/inflate.js
CHANGED
|
@@ -6,6 +6,7 @@ import { Layer } from './animation/layer';
|
|
|
6
6
|
import { ClipTrack } from './animation/tracks/cliptrack';
|
|
7
7
|
import { Bezier } from './animation/bezier';
|
|
8
8
|
import { StreamTrack } from './animation/tracks/streamtrack';
|
|
9
|
+
import { FunctionTrack } from './animation/tracks/functiontrack';
|
|
9
10
|
export function createTrackFromData(zcomp, anim, data) {
|
|
10
11
|
switch (data.type) {
|
|
11
12
|
case Data.TrackType.Property: {
|
|
@@ -37,6 +38,28 @@ export function createTrackFromData(zcomp, anim, data) {
|
|
|
37
38
|
ret.setWeightsById(processKeyframes(data.weight, anim.curves));
|
|
38
39
|
return ret;
|
|
39
40
|
}
|
|
41
|
+
case Data.TrackType.Function: {
|
|
42
|
+
const ret = new FunctionTrack(anim);
|
|
43
|
+
const blocks = Object.create(null);
|
|
44
|
+
const dt = false; //isDesignTime(zcomp.contextManager);
|
|
45
|
+
for (const block of Object.values(data.data)) {
|
|
46
|
+
if (dt && !block?.runAtDesignTime)
|
|
47
|
+
continue;
|
|
48
|
+
if (block?.type !== 'entity')
|
|
49
|
+
continue;
|
|
50
|
+
const obj = zcomp.entityByID.get(block.entityID);
|
|
51
|
+
const func = obj?.[block.functionName];
|
|
52
|
+
if (typeof func !== 'function')
|
|
53
|
+
continue;
|
|
54
|
+
blocks[block.id] = {
|
|
55
|
+
...block,
|
|
56
|
+
obj,
|
|
57
|
+
func,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
ret.setBlocksById(blocks);
|
|
61
|
+
return ret;
|
|
62
|
+
}
|
|
40
63
|
}
|
|
41
64
|
return undefined;
|
|
42
65
|
}
|
package/lib/selectors.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { BehaviorByID, EntityPropOverride, Import, NodeByID, ParsedImport, Props, ZComponentData } from './data/core';
|
|
2
2
|
import * as Data from './data';
|
|
3
|
-
import { Layer } from './animation';
|
|
4
3
|
import { ZValues } from './values/values';
|
|
5
4
|
export declare function parseImport(i: Import): ParsedImport;
|
|
6
5
|
export declare function constructImport(from: string, destFile: string, imp: string): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zcomponent/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1-beta",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
"scripts": {
|
|
22
22
|
"build": "rm -rf lib && tsc",
|
|
23
23
|
"build-animation-tests": "tsc -p ./tsconfig.test.animation.json",
|
|
24
|
-
"test": "
|
|
25
|
-
"tests": "parcel serve tests/index.html -p 8088"
|
|
24
|
+
"test": "env TS_NODE_PROJECT=\"tsconfig.testing.json\" mocha --es-module-specifier-resolution=node"
|
|
26
25
|
},
|
|
27
26
|
"author": "Zappar Limited",
|
|
28
27
|
"license": "Proprietary",
|
|
29
28
|
"devDependencies": {
|
|
30
|
-
"@
|
|
31
|
-
"
|
|
29
|
+
"@types/mocha": "^10.0.1",
|
|
30
|
+
"mocha": "^10.2.0",
|
|
31
|
+
"ts-node": "^10.9.1",
|
|
32
32
|
"typescript": "^4.9.4"
|
|
33
33
|
},
|
|
34
34
|
"zexports": [
|