@zcomponent/core 1.13.0-beta → 1.14.0-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/animation.d.ts +1 -1
- package/lib/animation/animation.js +65 -35
- package/lib/animation/clips/clip.d.ts +1 -1
- package/lib/animation/clips/clip.js +2 -2
- package/lib/animation/layer.js +1 -1
- package/lib/animation/layerclip.d.ts +12 -2
- package/lib/animation/layerclip.js +54 -17
- package/lib/animation/stream.d.ts +1 -1
- package/lib/animation/tracks/cliptrack.d.ts +1 -1
- package/lib/animation/tracks/cliptrack.js +2 -2
- package/lib/animation/tracks/streamtrack.d.ts +1 -1
- package/lib/animation/tracks/streamtrack.js +2 -2
- package/lib/animation/tracks/track.d.ts +1 -1
- package/lib/animation/tracks/track.js +1 -1
- package/lib/inflate.js +22 -2
- package/lib/observable.d.ts +1 -1
- package/lib/observable.js +70 -42
- package/package.json +1 -1
|
@@ -51,12 +51,12 @@ export declare class Animation {
|
|
|
51
51
|
tick(): void;
|
|
52
52
|
registerEntityPath(path: string, entity: any, pathParts: (string | number)[]): void;
|
|
53
53
|
evaluateTouchedPaths(paths: string[], t?: number): void;
|
|
54
|
+
private _evaluateLayer;
|
|
54
55
|
get spotlightLayer(): Layer | undefined;
|
|
55
56
|
set spotlightLayer(l: Layer | undefined);
|
|
56
57
|
clearCachedDefault(entityID: string, prop: string): void;
|
|
57
58
|
private _emitPendingEvents;
|
|
58
59
|
private _resolvePath;
|
|
59
|
-
private _evaluatePath;
|
|
60
60
|
start(): void;
|
|
61
61
|
}
|
|
62
62
|
export interface EntityPath {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Observable } from '../observable';
|
|
2
|
-
import { clone } from '../data';
|
|
3
2
|
import { Event } from '../event';
|
|
4
3
|
/** @internal */
|
|
5
4
|
export var AnimationEvents;
|
|
@@ -109,11 +108,58 @@ export class Animation {
|
|
|
109
108
|
return;
|
|
110
109
|
t = t ?? this.timeSource?.() ?? performance.now();
|
|
111
110
|
const unique = new Set([...paths]);
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
const uniqueAsArray = unique.values();
|
|
112
|
+
const resolvedPaths = [...uniqueAsArray].map(entry => this._resolvePath(entry));
|
|
113
|
+
for (const entry of resolvedPaths) {
|
|
114
|
+
if (!entry)
|
|
115
|
+
continue;
|
|
116
|
+
let byEntity = this._defaultValues.get(entry[0]);
|
|
117
|
+
if (!byEntity) {
|
|
118
|
+
byEntity = new Map();
|
|
119
|
+
this._defaultValues.set(entry[0], byEntity);
|
|
120
|
+
}
|
|
121
|
+
let observable = byEntity.get(entry[1][0]);
|
|
122
|
+
if (!observable) {
|
|
123
|
+
let val = entry[0][entry[1][0]];
|
|
124
|
+
if (val instanceof Observable)
|
|
125
|
+
val = val.value;
|
|
126
|
+
observable = new Observable(val);
|
|
127
|
+
byEntity.set(entry[1][0], observable);
|
|
128
|
+
}
|
|
129
|
+
entry[2] = observable;
|
|
130
|
+
}
|
|
131
|
+
// Reset our working values to default
|
|
132
|
+
for (const p of resolvedPaths) {
|
|
133
|
+
if (p?.[2])
|
|
134
|
+
p[2].value = undefined;
|
|
135
|
+
}
|
|
136
|
+
if (this._spotlightLayer)
|
|
137
|
+
this._evaluateLayer(t, this._spotlightLayer, resolvedPaths);
|
|
138
|
+
else {
|
|
139
|
+
for (const layer of this._layers)
|
|
140
|
+
this._evaluateLayer(t, layer, resolvedPaths);
|
|
141
|
+
}
|
|
142
|
+
for (const entry of resolvedPaths) {
|
|
143
|
+
if (!entry?.[2])
|
|
144
|
+
continue;
|
|
145
|
+
if (entry[0][entry[1][0]] instanceof Observable)
|
|
146
|
+
entry[0][entry[1][0]].value = entry[2].value;
|
|
147
|
+
else
|
|
148
|
+
entry[0][entry[1][0]] = entry[2].value;
|
|
114
149
|
}
|
|
115
150
|
this._emitPendingEvents();
|
|
116
151
|
}
|
|
152
|
+
_evaluateLayer(t, layer, paths) {
|
|
153
|
+
for (const p of paths) {
|
|
154
|
+
if (!p?.[2])
|
|
155
|
+
continue;
|
|
156
|
+
if (!layer.influencedPaths.has(p[3]))
|
|
157
|
+
continue;
|
|
158
|
+
let val = getResolved(p[2], p[1]);
|
|
159
|
+
val = layer.computePathProperty(t, p[3], val);
|
|
160
|
+
setResolved(p[2], p[1], val);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
117
163
|
get spotlightLayer() {
|
|
118
164
|
return this._spotlightLayer;
|
|
119
165
|
}
|
|
@@ -153,38 +199,7 @@ export class Animation {
|
|
|
153
199
|
const path = this._entityPaths.get(p);
|
|
154
200
|
if (!path || path.pathParts.length === 0)
|
|
155
201
|
return;
|
|
156
|
-
|
|
157
|
-
let currentKey = path.pathParts[0];
|
|
158
|
-
if (parent[currentKey] instanceof Observable) {
|
|
159
|
-
parent = parent[currentKey];
|
|
160
|
-
currentKey = 'value';
|
|
161
|
-
}
|
|
162
|
-
for (let i = 1; i < path.pathParts.length; i++) {
|
|
163
|
-
parent = parent[currentKey];
|
|
164
|
-
currentKey = path.pathParts[i];
|
|
165
|
-
}
|
|
166
|
-
return [parent, currentKey];
|
|
167
|
-
}
|
|
168
|
-
_evaluatePath(t, p) {
|
|
169
|
-
const resolved = this._resolvePath(p);
|
|
170
|
-
if (!resolved)
|
|
171
|
-
return;
|
|
172
|
-
if (!this._defaultValues.has(p)) {
|
|
173
|
-
this._defaultValues.set(p, clone(resolved[0][resolved[1]]));
|
|
174
|
-
}
|
|
175
|
-
let val = this._defaultValues.get(p);
|
|
176
|
-
if (this._spotlightLayer) {
|
|
177
|
-
if (this._spotlightLayer.influencedPaths.has(p))
|
|
178
|
-
val = this._spotlightLayer.computePathProperty(t, p, val);
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
for (const layer of this._layers) {
|
|
182
|
-
if (!layer.influencedPaths.has(p))
|
|
183
|
-
continue;
|
|
184
|
-
val = layer.computePathProperty(t, p, val);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
resolved[0][resolved[1]] = val;
|
|
202
|
+
return [path.entity, path.pathParts, undefined, p];
|
|
188
203
|
}
|
|
189
204
|
start() {
|
|
190
205
|
for (const layer of this._layers) {
|
|
@@ -195,3 +210,18 @@ export class Animation {
|
|
|
195
210
|
}
|
|
196
211
|
}
|
|
197
212
|
}
|
|
213
|
+
function getResolved(o, pathParts) {
|
|
214
|
+
let current = o.value;
|
|
215
|
+
for (let i = 1; i < pathParts.length; i++)
|
|
216
|
+
current = current[pathParts[i]];
|
|
217
|
+
return current;
|
|
218
|
+
}
|
|
219
|
+
function setResolved(o, pathParts, val) {
|
|
220
|
+
let target = o;
|
|
221
|
+
let key = 'value';
|
|
222
|
+
for (let i = 1; i < pathParts.length; i++) {
|
|
223
|
+
target = target[key];
|
|
224
|
+
key = pathParts[i];
|
|
225
|
+
}
|
|
226
|
+
target[key] = val;
|
|
227
|
+
}
|
|
@@ -34,5 +34,5 @@ export declare class Clip {
|
|
|
34
34
|
streamPause(isActive: boolean, active: LayerClip | null | undefined): void;
|
|
35
35
|
streamSeek(t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined): void;
|
|
36
36
|
streamTick(clipState: StreamState, t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined, force?: boolean, stalled?: boolean, parentWeight?: number): void;
|
|
37
|
-
|
|
37
|
+
isStalled(): boolean;
|
|
38
38
|
}
|
|
@@ -131,9 +131,9 @@ export class Clip {
|
|
|
131
131
|
track.streamTick(clipState, t, rate, isActive, active, force, stalled, parentWeight);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
-
|
|
134
|
+
isStalled() {
|
|
135
135
|
for (const track of this._tracks) {
|
|
136
|
-
if (track.
|
|
136
|
+
if (track.isStalled())
|
|
137
137
|
return true;
|
|
138
138
|
}
|
|
139
139
|
return false;
|
package/lib/animation/layer.js
CHANGED
|
@@ -45,7 +45,7 @@ export class Layer {
|
|
|
45
45
|
this._queue.splice(i, 1);
|
|
46
46
|
}
|
|
47
47
|
if (entry.layerClip && entry === this._active) {
|
|
48
|
-
if (next && (entry.layerClip.state === StreamState.Ended || next.fadeTime >= entry.layerClip.getRemainingTimeEstimate())) {
|
|
48
|
+
if (next && (entry.layerClip.state.value === StreamState.Ended || next.fadeTime >= entry.layerClip.getRemainingTimeEstimate())) {
|
|
49
49
|
next.startTime = t;
|
|
50
50
|
this._active = next;
|
|
51
51
|
this.animation._pendingEvents.push({ evt: AnimationEvents.onLayerClipActive, args: [this._active.layerClip] });
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { FadeParameters } from '../data';
|
|
2
|
+
import { Event } from '../event';
|
|
3
|
+
import { Observable } from '../observable';
|
|
2
4
|
import { Animation } from './animation';
|
|
3
5
|
import { AnimationState } from './animationstate';
|
|
4
6
|
import { Clip } from './clips/clip';
|
|
@@ -24,13 +26,21 @@ export declare class LayerClip implements Stream {
|
|
|
24
26
|
private _lastClipTime;
|
|
25
27
|
private _lastLoop;
|
|
26
28
|
private _stopped;
|
|
27
|
-
|
|
29
|
+
private _state;
|
|
30
|
+
state: Observable<StreamState, never>;
|
|
31
|
+
playing: Observable<boolean, never>;
|
|
32
|
+
stalled: Observable<boolean, never>;
|
|
33
|
+
onPlaying: Event<[LayerClip]>;
|
|
34
|
+
onPaused: Event<[LayerClip]>;
|
|
35
|
+
onEnded: Event<[LayerClip]>;
|
|
36
|
+
onLoop: Event<[LayerClip]>;
|
|
28
37
|
constructor(layer: Layer, clip: Clip, scriptName?: string | undefined, id?: string | undefined);
|
|
29
38
|
private _clipDirty;
|
|
30
39
|
tick(touchedPaths: string[], force?: boolean): void;
|
|
31
40
|
computePathProperty(p: string, valueBefore: any): any;
|
|
32
41
|
getRemainingTimeEstimate(): number;
|
|
33
42
|
private _getTime;
|
|
43
|
+
private _stateUpdate;
|
|
34
44
|
queue(opts?: LayerClipPlayOptions): void;
|
|
35
45
|
length(): number;
|
|
36
46
|
play(opts?: LayerClipPlayOptions): void;
|
|
@@ -43,7 +53,7 @@ export declare class LayerClip implements Stream {
|
|
|
43
53
|
_restore(state: AnimationState): void;
|
|
44
54
|
get clipTime(): number;
|
|
45
55
|
stop(): void;
|
|
46
|
-
|
|
56
|
+
isStalled(): boolean;
|
|
47
57
|
}
|
|
48
58
|
export interface LayerClipSeekOptions {
|
|
49
59
|
fade?: FadeParameters | null;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Event } from '../event';
|
|
2
|
+
import { Observable } from '../observable';
|
|
1
3
|
import { AnimationEvents } from './animation';
|
|
2
4
|
import { StreamState } from './stream';
|
|
3
5
|
import { resolveClipTimeLoops } from './tracks/track';
|
|
@@ -16,27 +18,51 @@ export class LayerClip {
|
|
|
16
18
|
this._rate = 1;
|
|
17
19
|
this._loop = false;
|
|
18
20
|
this._stopped = false;
|
|
19
|
-
this.
|
|
21
|
+
this._state = StreamState.Paused;
|
|
22
|
+
this.state = new Observable(this._state);
|
|
23
|
+
this.playing = new Observable(false);
|
|
24
|
+
this.stalled = new Observable(false);
|
|
25
|
+
this.onPlaying = new Event();
|
|
26
|
+
this.onPaused = new Event();
|
|
27
|
+
this.onEnded = new Event();
|
|
28
|
+
this.onLoop = new Event();
|
|
20
29
|
this._clipDirty = (v) => {
|
|
21
30
|
if (v)
|
|
22
31
|
this._lastClipTime = undefined;
|
|
23
32
|
};
|
|
33
|
+
this._stateUpdate = (s) => {
|
|
34
|
+
this.playing.value = s === StreamState.Playing;
|
|
35
|
+
switch (s) {
|
|
36
|
+
case StreamState.Ended:
|
|
37
|
+
this.onEnded.emit(this);
|
|
38
|
+
break;
|
|
39
|
+
case StreamState.Playing:
|
|
40
|
+
this.onPlaying.emit(this);
|
|
41
|
+
break;
|
|
42
|
+
case StreamState.Paused:
|
|
43
|
+
this.onPaused.emit(this);
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
24
47
|
this.animation = layer.animation;
|
|
25
48
|
this._t1 = clip.length;
|
|
26
49
|
layer._registerLayerClip(this);
|
|
27
50
|
this.clip.influencedPathsDirty.addListener(this._clipDirty);
|
|
28
51
|
if (id)
|
|
29
52
|
layer.animation.layerClipByID.set(id, this);
|
|
53
|
+
this.state.addListener(this._stateUpdate);
|
|
30
54
|
}
|
|
31
55
|
tick(touchedPaths, force) {
|
|
32
56
|
const t = this._getTime();
|
|
33
57
|
if (this._stallStartTime !== undefined) {
|
|
34
|
-
if (!this.clip.
|
|
58
|
+
if (!this.clip.isStalled())
|
|
35
59
|
this._cancelStall();
|
|
36
60
|
}
|
|
37
|
-
else if (this.
|
|
38
|
-
if (this.clip.
|
|
61
|
+
else if (this._state === StreamState.Playing) {
|
|
62
|
+
if (this.clip.isStalled()) {
|
|
39
63
|
this._stallStartTime = t;
|
|
64
|
+
this.stalled.value = true;
|
|
65
|
+
}
|
|
40
66
|
}
|
|
41
67
|
const t0 = this._t0 + (t - (this._pauseTime ?? t)) + (t - (this._stallStartTime ?? t));
|
|
42
68
|
const t1 = this._t1 + (t - (this._pauseTime ?? t)) + (t - (this._stallStartTime ?? t));
|
|
@@ -45,14 +71,18 @@ export class LayerClip {
|
|
|
45
71
|
if (ct !== this._lastClipTime || force) {
|
|
46
72
|
touchedPaths.push(...this.clip.influencedPaths);
|
|
47
73
|
}
|
|
48
|
-
if (this.
|
|
74
|
+
if (this._state === StreamState.Playing && t >= this._t1) {
|
|
49
75
|
this.pause();
|
|
50
|
-
this.
|
|
76
|
+
this._state = StreamState.Ended;
|
|
77
|
+
this.state.value = this._state;
|
|
51
78
|
}
|
|
52
79
|
else {
|
|
53
80
|
const [bt, loop] = resolveClipTimeLoops(t, t0, this._rate >= 0 ? 0 : this.clip.length, this._rate, this.clip.length, this._rate < 0, t1);
|
|
54
|
-
this.clip.streamTick(this.
|
|
81
|
+
this.clip.streamTick(this._state, bt, this._rate, this.layer.active === this, this.layer.active, loop !== this._lastLoop, this._stallStartTime !== undefined, 1);
|
|
82
|
+
const isNewLoop = this._lastLoop !== undefined && this._lastLoop !== loop;
|
|
55
83
|
this._lastLoop = loop;
|
|
84
|
+
if (isNewLoop)
|
|
85
|
+
this.onLoop.emit(this);
|
|
56
86
|
}
|
|
57
87
|
}
|
|
58
88
|
computePathProperty(p, valueBefore) {
|
|
@@ -85,7 +115,7 @@ export class LayerClip {
|
|
|
85
115
|
this._stopped = false;
|
|
86
116
|
this._loop = opts?.loop ?? this.defaultLoop;
|
|
87
117
|
const t = this._getTime();
|
|
88
|
-
if (this.
|
|
118
|
+
if (this._state === StreamState.Ended) {
|
|
89
119
|
this._t0 = t;
|
|
90
120
|
}
|
|
91
121
|
else if (this._pauseTime !== undefined) {
|
|
@@ -108,7 +138,7 @@ export class LayerClip {
|
|
|
108
138
|
}
|
|
109
139
|
const t0 = this._t0 + (t - (this._pauseTime ?? t));
|
|
110
140
|
const t1 = this._t1 + (t - (this._pauseTime ?? t));
|
|
111
|
-
this.
|
|
141
|
+
this._state = StreamState.Playing;
|
|
112
142
|
this.animation._pendingEvents.push({ evt: AnimationEvents.onLayerClipState, args: [this] });
|
|
113
143
|
this._lastClipTime = undefined;
|
|
114
144
|
this._lastTickTime = undefined;
|
|
@@ -116,21 +146,25 @@ export class LayerClip {
|
|
|
116
146
|
this.layer._activateLayerClip(this, opts);
|
|
117
147
|
this.layer._evaulate();
|
|
118
148
|
}
|
|
119
|
-
if (this.clip.
|
|
149
|
+
if (this.clip.isStalled()) {
|
|
120
150
|
this._stallStartTime = t;
|
|
151
|
+
this.stalled.value = true;
|
|
152
|
+
}
|
|
121
153
|
const [bt, loop] = resolveClipTimeLoops(t, t0, this._rate >= 0 ? 0 : this.clip.length, this._rate, this.clip.length, this._rate < 0, t1);
|
|
122
|
-
this.clip.streamTick(this.
|
|
154
|
+
this.clip.streamTick(this._state, bt, this._rate, this.layer.active === this, this.layer.active, loop !== this._lastLoop, this._stallStartTime !== undefined, 1);
|
|
123
155
|
this._lastLoop = loop;
|
|
156
|
+
this.state.value = this._state;
|
|
124
157
|
}
|
|
125
158
|
pause() {
|
|
126
159
|
delete this._lastLoop;
|
|
127
|
-
if (this._pauseTime !== undefined || this.
|
|
160
|
+
if (this._pauseTime !== undefined || this._state !== StreamState.Playing)
|
|
128
161
|
return;
|
|
129
|
-
this.
|
|
162
|
+
this._state = StreamState.Paused;
|
|
130
163
|
this.animation._pendingEvents.push({ evt: AnimationEvents.onLayerClipState, args: [this] });
|
|
131
164
|
this._pauseTime = this._getTime();
|
|
132
165
|
this._cancelStall();
|
|
133
166
|
this.clip.streamPause(this.layer.active === this, this.layer.active);
|
|
167
|
+
this.state.value = this._state;
|
|
134
168
|
}
|
|
135
169
|
_cancelStall() {
|
|
136
170
|
if (this._stallStartTime === undefined)
|
|
@@ -139,6 +173,7 @@ export class LayerClip {
|
|
|
139
173
|
this._t0 += t - this._stallStartTime;
|
|
140
174
|
this._t1 += t - this._stallStartTime;
|
|
141
175
|
delete this._stallStartTime;
|
|
176
|
+
this.stalled.value = false;
|
|
142
177
|
}
|
|
143
178
|
seek(ct, opts) {
|
|
144
179
|
const t = this._getTime();
|
|
@@ -181,7 +216,7 @@ export class LayerClip {
|
|
|
181
216
|
rate: this._rate,
|
|
182
217
|
loop: this._loop,
|
|
183
218
|
stopped: this._stopped,
|
|
184
|
-
state: this.
|
|
219
|
+
state: this._state,
|
|
185
220
|
};
|
|
186
221
|
state.byLayerClip[this.id] = ret;
|
|
187
222
|
}
|
|
@@ -199,7 +234,8 @@ export class LayerClip {
|
|
|
199
234
|
this._rate = entry.rate;
|
|
200
235
|
this._loop = entry.loop;
|
|
201
236
|
this._stopped = entry.stopped;
|
|
202
|
-
this.
|
|
237
|
+
this._state = entry.state;
|
|
238
|
+
this.state.value = this._state;
|
|
203
239
|
}
|
|
204
240
|
get clipTime() {
|
|
205
241
|
return this._lastTickTime !== undefined ? this._lastTickTime : this.defaultPlaySpeed > 0 ? 0 : this.clip.length;
|
|
@@ -213,10 +249,11 @@ export class LayerClip {
|
|
|
213
249
|
delete this._stallStartTime;
|
|
214
250
|
this._rate = 1;
|
|
215
251
|
this.clip.streamTick(StreamState.Ended, this._t0, 1, this.layer.active === this, this.layer.active, true);
|
|
216
|
-
this.
|
|
252
|
+
this._state = StreamState.Ended;
|
|
217
253
|
this.animation._pendingEvents.push({ evt: AnimationEvents.onLayerClipState, args: [this] });
|
|
254
|
+
this.state.value = this._state;
|
|
218
255
|
}
|
|
219
|
-
|
|
256
|
+
isStalled() {
|
|
220
257
|
return this._stallStartTime !== undefined;
|
|
221
258
|
}
|
|
222
259
|
}
|
|
@@ -31,5 +31,5 @@ export declare class ClipTrack extends Track {
|
|
|
31
31
|
streamSeek(t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined): void;
|
|
32
32
|
streamTick(clipState: StreamState, t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined, force?: boolean, stalled?: boolean, parentWeight?: number): void;
|
|
33
33
|
private _resolveBlock;
|
|
34
|
-
|
|
34
|
+
isStalled(): boolean;
|
|
35
35
|
}
|
|
@@ -39,5 +39,5 @@ export declare class StreamTrack extends Track {
|
|
|
39
39
|
streamTick(clipState: StreamState, t: number, rate: number, isActive: boolean, active: LayerClip | null | undefined, force?: boolean, stalled?: boolean, parentWeight?: number): void;
|
|
40
40
|
private _applyState;
|
|
41
41
|
private _resolveBlock;
|
|
42
|
-
|
|
42
|
+
isStalled(): boolean;
|
|
43
43
|
}
|
|
@@ -7,7 +7,7 @@ export declare abstract class Track {
|
|
|
7
7
|
constructor(anim: Animation, id?: string | undefined);
|
|
8
8
|
abstract get influencedPaths(): string[];
|
|
9
9
|
abstract computePathProperty(t: number, p: string, valueBefore: any, parentWeight?: number): any;
|
|
10
|
-
|
|
10
|
+
isStalled(): boolean;
|
|
11
11
|
}
|
|
12
12
|
export declare function resolveKeyframeValue(t: number, before: Keyframe, after: Keyframe | undefined): any;
|
|
13
13
|
export declare function resolveKeyframes(keyframes: Keyframe[], t: number): [before: Keyframe | undefined, after: Keyframe | undefined];
|
package/lib/inflate.js
CHANGED
|
@@ -152,7 +152,17 @@ export function updateClipFromData(zcomp, clip, data) {
|
|
|
152
152
|
clip.defaultFadeParameters = resolvedFadeParameters(data.defaultFadeParameters, zcomp.animation.curves);
|
|
153
153
|
clip.length = data.length;
|
|
154
154
|
clip.clearTracks();
|
|
155
|
-
|
|
155
|
+
const tracks = Object.values(data.tracks);
|
|
156
|
+
tracks.sort((atrack, btrack) => {
|
|
157
|
+
let a = atrack.order ?? 'A0';
|
|
158
|
+
let b = btrack.order ?? 'A0';
|
|
159
|
+
if (a === b) {
|
|
160
|
+
a = atrack.id;
|
|
161
|
+
b = btrack.id;
|
|
162
|
+
}
|
|
163
|
+
return a < b ? -1 : 1;
|
|
164
|
+
});
|
|
165
|
+
for (const track of Object.values(tracks)) {
|
|
156
166
|
if (!track)
|
|
157
167
|
continue;
|
|
158
168
|
const instance = createTrackFromData(zcomp, clip.animation, track);
|
|
@@ -195,7 +205,17 @@ export function populateAnimationTracksFromData(zcomp, anim, data) {
|
|
|
195
205
|
const clip = anim.clipByID.get(clipData.id);
|
|
196
206
|
if (!clip)
|
|
197
207
|
continue;
|
|
198
|
-
|
|
208
|
+
const tracks = Object.values(clipData.tracks);
|
|
209
|
+
tracks.sort((atrack, btrack) => {
|
|
210
|
+
let a = atrack.order ?? 'A0';
|
|
211
|
+
let b = btrack.order ?? 'A0';
|
|
212
|
+
if (a === b) {
|
|
213
|
+
a = atrack.id;
|
|
214
|
+
b = btrack.id;
|
|
215
|
+
}
|
|
216
|
+
return a < b ? -1 : 1;
|
|
217
|
+
});
|
|
218
|
+
for (const track of Object.values(tracks)) {
|
|
199
219
|
if (!track)
|
|
200
220
|
continue;
|
|
201
221
|
const instance = createTrackFromData(zcomp, anim, track);
|
package/lib/observable.d.ts
CHANGED
|
@@ -33,10 +33,10 @@ type Resolved<T, M> = [T] extends [never] ? M : T;
|
|
|
33
33
|
* @typeParam TypeInternal - An internal type used to improve automatic type detection
|
|
34
34
|
*/
|
|
35
35
|
export declare class Observable<Type = never, TypeInternal extends any[] | [] | never = never> extends Emitter<[Resolved<Type, TypeInternal>]> {
|
|
36
|
-
private _default;
|
|
37
36
|
private _deep;
|
|
38
37
|
private _proxies;
|
|
39
38
|
private _value;
|
|
39
|
+
private _default;
|
|
40
40
|
/**
|
|
41
41
|
* Constructs a new Observable
|
|
42
42
|
*
|
package/lib/observable.js
CHANGED
|
@@ -32,21 +32,12 @@ import { Emitter } from "./emitter";
|
|
|
32
32
|
* @typeParam TypeInternal - An internal type used to improve automatic type detection
|
|
33
33
|
*/
|
|
34
34
|
export class Observable extends Emitter {
|
|
35
|
-
constructor(
|
|
35
|
+
constructor(def, withHandler, _deep = true, callWithImmediately = false) {
|
|
36
36
|
super();
|
|
37
|
-
this._default = _default;
|
|
38
37
|
this._deep = _deep;
|
|
39
38
|
this._proxies = new WeakMap();
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
initial = this._default.slice();
|
|
43
|
-
this._default = this._default.slice();
|
|
44
|
-
}
|
|
45
|
-
else if (typeof this._default === 'object' && this._deep && this._default !== null && Object.getPrototypeOf(this._default) !== Object.prototype) {
|
|
46
|
-
initial = { ...this._default };
|
|
47
|
-
this._default = { ...this._default };
|
|
48
|
-
}
|
|
49
|
-
this._value = this._wrap(initial);
|
|
39
|
+
this._default = clone(def, _deep);
|
|
40
|
+
this._value = this._wrap(clone(def, _deep));
|
|
50
41
|
if (withHandler)
|
|
51
42
|
this.addListener(withHandler, 0, callWithImmediately);
|
|
52
43
|
}
|
|
@@ -59,48 +50,43 @@ export class Observable extends Emitter {
|
|
|
59
50
|
return this._value.proxy;
|
|
60
51
|
}
|
|
61
52
|
_wrap(v) {
|
|
62
|
-
if (!
|
|
63
|
-
|
|
64
|
-
v === null ||
|
|
65
|
-
Object.getPrototypeOf(v) !== Object.prototype ||
|
|
66
|
-
this._deep === false ||
|
|
67
|
-
typeof v === 'function') {
|
|
68
|
-
return { proxy: v, target: v };
|
|
69
|
-
}
|
|
70
|
-
}
|
|
53
|
+
if (!shouldWrap(v) || !this._deep)
|
|
54
|
+
return { proxy: v, target: v };
|
|
71
55
|
const that = this;
|
|
72
56
|
return {
|
|
73
57
|
target: v,
|
|
74
58
|
proxy: new Proxy(v, {
|
|
75
59
|
get(target, p, receiver) {
|
|
76
60
|
const val = target[p];
|
|
61
|
+
if (!shouldWrap(val))
|
|
62
|
+
return val;
|
|
77
63
|
if (Array.isArray(target) && p === "splice") {
|
|
78
|
-
return function (...args) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (Object.getPrototypeOf(val) !== Object.prototype)
|
|
86
|
-
return val;
|
|
87
|
-
if (typeof val === 'function')
|
|
88
|
-
return val;
|
|
64
|
+
return function (...args) {
|
|
65
|
+
for (let i = 2; i < args.length; i++) {
|
|
66
|
+
args[i] = clone(args[i], true);
|
|
67
|
+
}
|
|
68
|
+
val.apply(target, args);
|
|
69
|
+
that._emitValue();
|
|
70
|
+
};
|
|
89
71
|
}
|
|
90
72
|
if (val['__z_is_observable'])
|
|
91
73
|
return val;
|
|
92
74
|
const proxy = that._proxies.get(val) || that._wrap(val);
|
|
93
75
|
that._proxies.set(val, proxy);
|
|
94
|
-
return proxy;
|
|
76
|
+
return proxy.proxy;
|
|
95
77
|
},
|
|
96
78
|
set(target, p, val) {
|
|
97
|
-
target[p]
|
|
98
|
-
|
|
79
|
+
const changed = target[p] !== val;
|
|
80
|
+
target[p] = clone(val, true);
|
|
81
|
+
if (changed)
|
|
82
|
+
that._emitValue();
|
|
99
83
|
return true;
|
|
100
84
|
},
|
|
101
85
|
deleteProperty(target, p) {
|
|
86
|
+
const changed = target[p] !== undefined;
|
|
102
87
|
delete target[p];
|
|
103
|
-
|
|
88
|
+
if (changed)
|
|
89
|
+
that._emitValue();
|
|
104
90
|
return true;
|
|
105
91
|
}
|
|
106
92
|
})
|
|
@@ -108,13 +94,10 @@ export class Observable extends Emitter {
|
|
|
108
94
|
}
|
|
109
95
|
set value(v) {
|
|
110
96
|
v = v ?? this._default;
|
|
111
|
-
|
|
112
|
-
|
|
97
|
+
const changed = v !== this._value.proxy;
|
|
98
|
+
this._value = this._wrap(clone(v, this._deep));
|
|
99
|
+
if (changed)
|
|
113
100
|
this._emitValue();
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
this._value = this._wrap(Array.isArray(v) ? [...v] : v);
|
|
117
|
-
this._emitValue();
|
|
118
101
|
}
|
|
119
102
|
addListener(fn, priority = 0, callImmediately = true) {
|
|
120
103
|
super.addListener(fn);
|
|
@@ -131,3 +114,48 @@ export class Observable extends Emitter {
|
|
|
131
114
|
this._emit(this._value.proxy);
|
|
132
115
|
}
|
|
133
116
|
}
|
|
117
|
+
function clone(a, deep) {
|
|
118
|
+
if (!deep) {
|
|
119
|
+
if (Array.isArray(a))
|
|
120
|
+
a.slice();
|
|
121
|
+
if (typeof a === 'object' && a !== null) {
|
|
122
|
+
const proto = Object.getPrototypeOf(a);
|
|
123
|
+
if (proto === Object.prototype || proto === null) {
|
|
124
|
+
return { ...a };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return a;
|
|
128
|
+
}
|
|
129
|
+
if (Array.isArray(a)) {
|
|
130
|
+
const ret = new Array(a.length);
|
|
131
|
+
for (let i = 0; i < ret.length; i++) {
|
|
132
|
+
ret[i] = clone(a[i], true);
|
|
133
|
+
}
|
|
134
|
+
return ret;
|
|
135
|
+
}
|
|
136
|
+
if (typeof a === 'object' && a !== null) {
|
|
137
|
+
const proto = Object.getPrototypeOf(a);
|
|
138
|
+
if (proto === Object.prototype || proto === null) {
|
|
139
|
+
const ret = Object.create(null);
|
|
140
|
+
for (const entry of Object.getOwnPropertyNames(a)) {
|
|
141
|
+
ret[entry] = clone(a[entry], true);
|
|
142
|
+
}
|
|
143
|
+
return ret;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return a;
|
|
147
|
+
}
|
|
148
|
+
function shouldWrap(a) {
|
|
149
|
+
if (Array.isArray(a))
|
|
150
|
+
return true;
|
|
151
|
+
if (a === null)
|
|
152
|
+
return false;
|
|
153
|
+
if (typeof a === 'object' && a !== null) {
|
|
154
|
+
const proto = Object.getPrototypeOf(a);
|
|
155
|
+
if (proto === Object.prototype || proto === null)
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
if (typeof a === 'function')
|
|
159
|
+
return false;
|
|
160
|
+
return false;
|
|
161
|
+
}
|