@neta-art/cohub 8.24.0 → 9.0.0
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/dist/board/animation.d.ts +57 -181
- package/dist/board/animation.js +374 -220
- package/dist/board/core/arrow-geometry.d.ts +33 -18
- package/dist/board/core/arrow-geometry.js +283 -52
- package/dist/board/core/draw-geometry.d.ts +22 -36
- package/dist/board/core/draw-geometry.js +148 -85
- package/dist/board/core/export-assets.d.ts +3 -6
- package/dist/board/core/export-assets.js +0 -2
- package/dist/board/core/export-plan.d.ts +12 -63
- package/dist/board/core/export-plan.js +55 -94
- package/dist/board/core/palette.d.ts +4 -21
- package/dist/board/core/palette.js +8 -13
- package/dist/board/core/scene.d.ts +33 -0
- package/dist/board/core/scene.js +302 -0
- package/dist/board/core/shape-definition.d.ts +12 -24
- package/dist/board/core/shape-definition.js +0 -19
- package/dist/board/core/shape-types.d.ts +6 -120
- package/dist/board/core/shape-types.js +5 -5
- package/dist/board/core/text-metrics.d.ts +8 -11
- package/dist/board/core/text-metrics.js +5 -34
- package/dist/board/core/tool-styles.d.ts +6 -16
- package/dist/board/core/tool-styles.js +17 -25
- package/dist/board/export/index.d.ts +10 -17
- package/dist/board/export/index.js +22 -21
- package/dist/board/export/scene.d.ts +10 -16
- package/dist/board/export/scene.js +17 -30
- package/dist/board/geometry.d.ts +27 -56
- package/dist/board/geometry.js +7 -67
- package/dist/board/headless/index.d.ts +6 -27
- package/dist/board/headless/index.js +4 -19
- package/dist/board/headless/sketch.d.ts +19 -0
- package/dist/board/headless/sketch.js +146 -0
- package/dist/board/image-key.d.ts +2 -12
- package/dist/board/image-key.js +3 -13
- package/dist/board/index.d.ts +18 -20
- package/dist/board/index.js +17 -17
- package/dist/board/media-playback.d.ts +3 -6
- package/dist/board/media-playback.js +6 -6
- package/dist/board/presets.d.ts +150 -0
- package/dist/board/presets.js +226 -0
- package/dist/board/render/board-background.d.ts +5 -3
- package/dist/board/render/board-background.js +8 -7
- package/dist/board/render/clip.d.ts +14 -0
- package/dist/board/render/clip.js +47 -0
- package/dist/board/render/index.d.ts +8 -5
- package/dist/board/render/index.js +7 -4
- package/dist/board/render/media-interaction.d.ts +4 -5
- package/dist/board/render/media-interaction.js +1 -2
- package/dist/board/render/palette.d.ts +6 -2
- package/dist/board/render/palette.js +7 -1
- package/dist/board/render/renderers/arrow-card-renderer.js +69 -71
- package/dist/board/render/renderers/audio-card-renderer.js +3 -3
- package/dist/board/render/renderers/base-card-renderer.d.ts +6 -17
- package/dist/board/render/renderers/base-card-renderer.js +1 -24
- package/dist/board/render/renderers/board-renderer-registry.d.ts +20 -50
- package/dist/board/render/renderers/board-renderer-registry.js +6 -7
- package/dist/board/render/renderers/draw-card-renderer.js +89 -56
- package/dist/board/render/renderers/effect-card-renderer.d.ts +6 -0
- package/dist/board/render/renderers/effect-card-renderer.js +197 -0
- package/dist/board/render/renderers/far-plate.d.ts +4 -21
- package/dist/board/render/renderers/far-plate.js +15 -34
- package/dist/board/render/renderers/file-card-renderer.d.ts +4 -25
- package/dist/board/render/renderers/file-card-renderer.js +8 -58
- package/dist/board/render/renderers/frame-card-renderer.js +28 -28
- package/dist/board/render/renderers/image-card-renderer.d.ts +4 -3
- package/dist/board/render/renderers/image-card-renderer.js +0 -9
- package/dist/board/render/renderers/shape-card-renderer.d.ts +9 -0
- package/dist/board/render/renderers/shape-card-renderer.js +240 -0
- package/dist/board/render/renderers/sketch-card-renderer.d.ts +5 -0
- package/dist/board/render/renderers/sketch-card-renderer.js +98 -0
- package/dist/board/render/renderers/task-card-renderer.d.ts +0 -1
- package/dist/board/render/renderers/task-card-renderer.js +14 -16
- package/dist/board/render/renderers/text-card-renderer.d.ts +1 -3
- package/dist/board/render/renderers/text-card-renderer.js +56 -46
- package/dist/board/render/renderers/unknown-card-renderer.js +4 -10
- package/dist/board/render/renderers/video-card-renderer.d.ts +4 -2
- package/dist/board/render/renderers/video-card-renderer.js +2 -1
- package/dist/board/render/sketch-host.d.ts +14 -0
- package/dist/board/render/sketch-host.js +216 -0
- package/dist/board/render/stroke.d.ts +12 -0
- package/dist/board/render/stroke.js +90 -0
- package/dist/board/render/text-measurement.d.ts +6 -26
- package/dist/board/render/text-measurement.js +11 -30
- package/dist/board/replay.d.ts +6 -31
- package/dist/board/replay.js +45 -203
- package/dist/board/runtime/board-player.d.ts +24 -0
- package/dist/board/runtime/board-player.js +161 -0
- package/dist/board/task.d.ts +2 -10
- package/dist/board/task.js +1 -10
- package/dist/chunks/environment.d.ts +2291 -3864
- package/dist/chunks/host-bridge.d.ts +253 -0
- package/dist/chunks/http.d.ts +233 -58
- package/dist/chunks/http.js +1046 -1028
- package/dist/chunks/transport.js +113 -59
- package/dist/chunks/websocket.d.ts +1 -1
- package/dist/chunks/websocket.js +1 -1
- package/dist/host-bridge.d.ts +54 -0
- package/dist/host-bridge.js +322 -0
- package/dist/http.d.ts +3 -3
- package/dist/index.d.ts +74 -191
- package/dist/index.js +2032 -1186
- package/dist/protocol/dist/board-constants.d.ts +1 -29
- package/dist/protocol/dist/board-constants.js +2 -115
- package/dist/protocol/dist/board-layout.d.ts +59 -0
- package/dist/protocol/dist/board-layout.js +482 -0
- package/dist/protocol/dist/board-model.d.ts +2052 -0
- package/dist/protocol/dist/board-model.js +592 -0
- package/dist/protocol/dist/board-patch.d.ts +86 -0
- package/dist/protocol/dist/board-patch.js +734 -0
- package/dist/protocol/dist/board-schema.d.ts +33 -0
- package/dist/protocol/dist/board-schema.js +59 -0
- package/dist/protocol/dist/board-upgrade.d.ts +1 -0
- package/dist/protocol/dist/board-url.d.ts +1 -3
- package/dist/protocol/dist/board-url.js +2 -2
- package/dist/protocol/dist/board.d.ts +37 -232
- package/dist/protocol/dist/board.js +62 -160
- package/dist/protocol/dist/display/actions.d.ts +1 -0
- package/dist/protocol/dist/display/index.d.ts +2 -0
- package/dist/protocol/dist/index.d.ts +11 -12
- package/dist/protocol/dist/model/metrics.d.ts +2 -0
- package/dist/protocol/dist/model/session.d.ts +2 -1
- package/dist/protocol/dist/realtime/types.d.ts +2 -2
- package/dist/protocol/dist/runtime/index.d.ts +1 -0
- package/dist/space-picker.d.ts +1 -0
- package/dist/space-picker.js +1 -0
- package/dist/types.d.ts +2 -5
- package/package.json +9 -1
- package/dist/board/core/connections.d.ts +0 -108
- package/dist/board/core/connections.js +0 -455
- package/dist/board/mutation.d.ts +0 -6
- package/dist/board/mutation.js +0 -14
- package/dist/board/render/connection-layer.d.ts +0 -53
- package/dist/board/render/connection-layer.js +0 -375
- package/dist/board/render/renderers/geo-card-renderer.d.ts +0 -5
- package/dist/board/render/renderers/geo-card-renderer.js +0 -127
- package/dist/board/semantic-document.d.ts +0 -37
- package/dist/board/semantic-document.js +0 -288
- package/dist/board/semantic-mutation.d.ts +0 -10
- package/dist/board/semantic-mutation.js +0 -209
- package/dist/protocol/dist/board-animation.js +0 -34
- package/dist/protocol/dist/board-authoring.d.ts +0 -1326
- package/dist/protocol/dist/board-authoring.js +0 -302
- package/dist/protocol/dist/board-capability-registry.d.ts +0 -2
- package/dist/protocol/dist/board-capability-registry.js +0 -123
- package/dist/protocol/dist/board-codec.d.ts +0 -3
- package/dist/protocol/dist/board-codec.js +0 -383
- package/dist/protocol/dist/board-composition.d.ts +0 -383
- package/dist/protocol/dist/board-composition.js +0 -310
- package/dist/protocol/dist/board-connection.d.ts +0 -317
- package/dist/protocol/dist/board-connection.js +0 -219
- package/dist/protocol/dist/board-document.d.ts +0 -1566
- package/dist/protocol/dist/board-document.js +0 -456
- package/dist/protocol/dist/board-effect.d.ts +0 -96
- package/dist/protocol/dist/board-effect.js +0 -54
- package/dist/protocol/dist/board-geometry.d.ts +0 -15
- package/dist/protocol/dist/board-geometry.js +0 -137
- package/dist/protocol/dist/board-node.d.ts +0 -8
- package/dist/protocol/dist/board-node.js +0 -252
- /package/dist/protocol/dist/{board-animation.d.ts → host-bridge.d.ts} +0 -0
package/dist/board/animation.js
CHANGED
|
@@ -1,249 +1,403 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { estimateBuiltinBoardClipCost, estimateBuiltinBoardEffectCost, validateBuiltinBoardClip, validateBuiltinBoardEffect } from "../protocol/dist/board-capability-registry.js";
|
|
1
|
+
import { BOARD_CAMERA_TARGET } from "../protocol/dist/board-model.js";
|
|
2
|
+
import { resolveBoardProperty } from "../protocol/dist/board-patch.js";
|
|
4
3
|
//#region src/board/animation.ts
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const linear = (x) => x;
|
|
5
|
+
function cubicBezier(x1, y1, x2, y2) {
|
|
6
|
+
const cx = 3 * x1;
|
|
7
|
+
const bx = 3 * (x2 - x1) - cx;
|
|
8
|
+
const ax = 1 - cx - bx;
|
|
9
|
+
const cy = 3 * y1;
|
|
10
|
+
const by = 3 * (y2 - y1) - cy;
|
|
11
|
+
const ay = 1 - cy - by;
|
|
12
|
+
const sampleX = (t) => ((ax * t + bx) * t + cx) * t;
|
|
13
|
+
const sampleY = (t) => ((ay * t + by) * t + cy) * t;
|
|
14
|
+
const slopeX = (t) => (3 * ax * t + 2 * bx) * t + cx;
|
|
15
|
+
return (x) => {
|
|
16
|
+
if (x <= 0) return 0;
|
|
17
|
+
if (x >= 1) return 1;
|
|
18
|
+
let t = x;
|
|
19
|
+
for (let index = 0; index < 8; index += 1) {
|
|
20
|
+
const error = sampleX(t) - x;
|
|
21
|
+
if (Math.abs(error) < 1e-6) return sampleY(t);
|
|
22
|
+
const slope = slopeX(t);
|
|
23
|
+
if (Math.abs(slope) < 1e-6) break;
|
|
24
|
+
t -= error / slope;
|
|
25
|
+
}
|
|
26
|
+
let low = 0;
|
|
27
|
+
let high = 1;
|
|
28
|
+
t = x;
|
|
29
|
+
for (let index = 0; index < 32; index += 1) {
|
|
30
|
+
const value = sampleX(t);
|
|
31
|
+
if (Math.abs(value - x) < 1e-6) break;
|
|
32
|
+
if (value < x) low = t;
|
|
33
|
+
else high = t;
|
|
34
|
+
t = (low + high) / 2;
|
|
35
|
+
}
|
|
36
|
+
return sampleY(t);
|
|
37
|
+
};
|
|
7
38
|
}
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
39
|
+
function steps(count, position) {
|
|
40
|
+
const jumps = position === "jump-none" ? count - 1 : position === "jump-both" ? count + 1 : count;
|
|
41
|
+
const start = position === "start" || position === "jump-start" || position === "jump-both";
|
|
42
|
+
return (x) => {
|
|
43
|
+
if (x >= 1) return 1;
|
|
44
|
+
const step = Math.floor(x * count) + (start ? 1 : 0);
|
|
45
|
+
return Math.min(1, Math.max(0, step / Math.max(1, jumps)));
|
|
46
|
+
};
|
|
13
47
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
48
|
+
const KEYWORD_EASES = {
|
|
49
|
+
linear,
|
|
50
|
+
ease: cubicBezier(.25, .1, .25, 1),
|
|
51
|
+
"ease-in": cubicBezier(.42, 0, 1, 1),
|
|
52
|
+
"ease-out": cubicBezier(0, 0, .58, 1),
|
|
53
|
+
"ease-in-out": cubicBezier(.42, 0, .58, 1),
|
|
54
|
+
"step-start": steps(1, "start"),
|
|
55
|
+
"step-end": steps(1, "end")
|
|
56
|
+
};
|
|
57
|
+
const easeCache = /* @__PURE__ */ new Map();
|
|
58
|
+
function boardEase(ease) {
|
|
59
|
+
if (!ease) return linear;
|
|
60
|
+
const key = ease.trim();
|
|
61
|
+
const keyword = KEYWORD_EASES[key];
|
|
62
|
+
if (keyword) return keyword;
|
|
63
|
+
const cached = easeCache.get(key);
|
|
64
|
+
if (cached) return cached;
|
|
65
|
+
let fn = linear;
|
|
66
|
+
const bezier = /^cubic-bezier\(([^)]+)\)$/.exec(key);
|
|
67
|
+
const stepped = /^steps\(\s*(\d+)\s*(?:,\s*([a-z-]+)\s*)?\)$/.exec(key);
|
|
68
|
+
if (bezier?.[1]) {
|
|
69
|
+
const [x1 = 0, y1 = 0, x2 = 1, y2 = 1] = bezier[1].split(",").map(Number);
|
|
70
|
+
fn = cubicBezier(x1, y1, x2, y2);
|
|
71
|
+
} else if (stepped?.[1]) fn = steps(Number(stepped[1]), stepped[2] ?? "end");
|
|
72
|
+
if (easeCache.size > 512) easeCache.clear();
|
|
73
|
+
easeCache.set(key, fn);
|
|
74
|
+
return fn;
|
|
75
|
+
}
|
|
76
|
+
function boardAnimationTime(header, elapsed) {
|
|
77
|
+
const local = Math.max(0, elapsed - header.delay);
|
|
78
|
+
if (header.loop || header.play === "always") return header.duration > 0 ? local % header.duration : 0;
|
|
79
|
+
if (local <= header.duration) return local;
|
|
80
|
+
return header.end === "reset" ? null : header.duration;
|
|
81
|
+
}
|
|
82
|
+
function compileTrack(animationId, id, track, targetType) {
|
|
83
|
+
const resolved = resolveBoardProperty(targetType, track.property);
|
|
84
|
+
if (!resolved.ok) return null;
|
|
85
|
+
const { spec } = resolved;
|
|
86
|
+
const times = new Float64Array(track.keyframes.length);
|
|
87
|
+
const values = [];
|
|
88
|
+
const eases = [];
|
|
89
|
+
track.keyframes.forEach((keyframe, index) => {
|
|
90
|
+
times[index] = keyframe.at;
|
|
91
|
+
values.push(keyframe.value);
|
|
92
|
+
eases.push(boardEase(keyframe.ease));
|
|
34
93
|
});
|
|
94
|
+
return {
|
|
95
|
+
id,
|
|
96
|
+
animationId,
|
|
97
|
+
target: track.target,
|
|
98
|
+
property: track.property,
|
|
99
|
+
path: track.property.split("."),
|
|
100
|
+
kind: spec.kind,
|
|
101
|
+
multiplicative: Boolean(spec.multiplicative),
|
|
102
|
+
composite: track.composite,
|
|
103
|
+
spline: track.interpolation === "spline" && spec.kind === "vec2",
|
|
104
|
+
step: track.interpolation === "step" || spec.kind === "discrete",
|
|
105
|
+
orient: Boolean(track.orient) && spec.kind === "vec2" && track.property === "position",
|
|
106
|
+
times,
|
|
107
|
+
values,
|
|
108
|
+
eases,
|
|
109
|
+
start: times[0] ?? 0
|
|
110
|
+
};
|
|
35
111
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
112
|
+
function compileBoardAnimations(document) {
|
|
113
|
+
const animations = /* @__PURE__ */ new Map();
|
|
114
|
+
for (const [animationId, animation] of Object.entries(document.animations)) animations.set(animationId, compileAnimation(animationId, animation, document));
|
|
115
|
+
const incoming = new Map([...animations.keys()].map((id) => [id, 0]));
|
|
116
|
+
for (const animation of animations.values()) for (const track of animation.children) incoming.set(track.target, (incoming.get(track.target) ?? 0) + 1);
|
|
117
|
+
const order = [...animations.keys()].filter((id) => incoming.get(id) === 0).sort();
|
|
118
|
+
for (let index = 0; index < order.length; index += 1) {
|
|
119
|
+
const animation = animations.get(order[index]);
|
|
120
|
+
for (const track of animation?.children ?? []) {
|
|
121
|
+
const count = (incoming.get(track.target) ?? 1) - 1;
|
|
122
|
+
incoming.set(track.target, count);
|
|
123
|
+
if (count === 0) order.push(track.target);
|
|
124
|
+
}
|
|
49
125
|
}
|
|
126
|
+
if (order.length !== animations.size) throw new Error("Animation graph contains a cycle");
|
|
127
|
+
return {
|
|
128
|
+
animations,
|
|
129
|
+
document,
|
|
130
|
+
order
|
|
131
|
+
};
|
|
50
132
|
}
|
|
51
|
-
function
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
/** Deterministically sample one validated Track without touching scene state. */
|
|
63
|
-
function sampleTrack(trackValue, time) {
|
|
64
|
-
const frames = trackValue.keyframes;
|
|
65
|
-
const first = frames[0];
|
|
66
|
-
const last = frames.at(-1);
|
|
67
|
-
if (!first || !last) return null;
|
|
68
|
-
if (time < first.time) {
|
|
69
|
-
if (trackValue.fill !== "backwards" && trackValue.fill !== "both") return null;
|
|
70
|
-
return {
|
|
71
|
-
target: trackValue.target,
|
|
72
|
-
channel: trackValue.channel,
|
|
73
|
-
value: first.value
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
if (time > last.time) {
|
|
77
|
-
if (trackValue.fill !== "forwards" && trackValue.fill !== "both") return null;
|
|
78
|
-
return {
|
|
79
|
-
target: trackValue.target,
|
|
80
|
-
channel: trackValue.channel,
|
|
81
|
-
value: last.value
|
|
82
|
-
};
|
|
133
|
+
function compileAnimation(animationId, animation, document) {
|
|
134
|
+
const { tracks, ...header } = animation;
|
|
135
|
+
const compiled = [];
|
|
136
|
+
const children = [];
|
|
137
|
+
for (const [id, track] of Object.entries(tracks).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
|
|
138
|
+
const targetType = track.target === "camera" ? BOARD_CAMERA_TARGET : document.animations[track.target] ? "animation" : document.items[track.target]?.type;
|
|
139
|
+
if (!targetType) continue;
|
|
140
|
+
const entry = compileTrack(animationId, id, track, targetType);
|
|
141
|
+
if (!entry) continue;
|
|
142
|
+
(targetType === "animation" ? children : compiled).push(entry);
|
|
83
143
|
}
|
|
144
|
+
return {
|
|
145
|
+
id: animationId,
|
|
146
|
+
header,
|
|
147
|
+
tracks: compiled,
|
|
148
|
+
children
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function keyframeIndex(times, time) {
|
|
84
152
|
let low = 0;
|
|
85
|
-
let high =
|
|
153
|
+
let high = times.length - 1;
|
|
154
|
+
if (time < times[0]) return -1;
|
|
155
|
+
if (time >= times[high]) return high;
|
|
86
156
|
while (low < high) {
|
|
87
|
-
const
|
|
88
|
-
if (
|
|
89
|
-
else high =
|
|
157
|
+
const mid = low + high + 1 >> 1;
|
|
158
|
+
if (times[mid] <= time) low = mid;
|
|
159
|
+
else high = mid - 1;
|
|
90
160
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
161
|
+
return low;
|
|
162
|
+
}
|
|
163
|
+
function isVec(value) {
|
|
164
|
+
return Boolean(value) && typeof value === "object" && typeof value.x === "number" && typeof value.y === "number";
|
|
165
|
+
}
|
|
166
|
+
function toVec(value) {
|
|
167
|
+
if (typeof value === "number") return {
|
|
168
|
+
x: value,
|
|
169
|
+
y: value
|
|
97
170
|
};
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
target: trackValue.target,
|
|
102
|
-
channel: trackValue.channel,
|
|
103
|
-
value: interpolate(left.value, right.value, progress)
|
|
171
|
+
return isVec(value) ? value : {
|
|
172
|
+
x: 0,
|
|
173
|
+
y: 0
|
|
104
174
|
};
|
|
105
175
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
});
|
|
176
|
+
const lerp = (a, b, t) => a + (b - a) * t;
|
|
177
|
+
function catmullRom(p0, p1, p2, p3, t) {
|
|
178
|
+
const t2 = t * t;
|
|
179
|
+
const t3 = t2 * t;
|
|
180
|
+
return .5 * (2 * p1 + (-p0 + p2) * t + (2 * p0 - 5 * p1 + 4 * p2 - p3) * t2 + (-p0 + 3 * p1 - 3 * p2 + p3) * t3);
|
|
112
181
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
vertices: 0,
|
|
116
|
-
dynamicVertices: 0,
|
|
117
|
-
drawCalls: 0,
|
|
118
|
-
filterPasses: 0,
|
|
119
|
-
renderTexturePixels: 0,
|
|
120
|
-
textureBytes: 0,
|
|
121
|
-
bufferBytes: 0,
|
|
122
|
-
simulationSteps: 0
|
|
123
|
-
};
|
|
124
|
-
const DEFAULT_BOARD_LIMITS = DEFAULT_BOARD_RENDER_LIMITS;
|
|
125
|
-
function builtinDefinition(capability) {
|
|
126
|
-
return {
|
|
127
|
-
...capability,
|
|
128
|
-
validate() {
|
|
129
|
-
return [];
|
|
130
|
-
},
|
|
131
|
-
estimateCost(params) {
|
|
132
|
-
return estimateBuiltinBoardClipCost({
|
|
133
|
-
kind: capability.id,
|
|
134
|
-
params
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
};
|
|
182
|
+
function hex(color) {
|
|
183
|
+
return `#${Math.max(0, Math.min(16777215, Math.round(color))).toString(16).padStart(6, "0")}`;
|
|
138
184
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
185
|
+
function mixColor(a, b, t, resolve) {
|
|
186
|
+
const from = resolve(a);
|
|
187
|
+
const to = resolve(b);
|
|
188
|
+
if (from === null || to === null) return t < 1 ? a : b;
|
|
189
|
+
const channel = (shift) => Math.round(lerp(from >> shift & 255, to >> shift & 255, t));
|
|
190
|
+
return hex(channel(16) << 16 | channel(8) << 8 | channel(0));
|
|
191
|
+
}
|
|
192
|
+
function parseHexColor(color) {
|
|
193
|
+
if (typeof color !== "string") return null;
|
|
194
|
+
const match = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(color.trim());
|
|
195
|
+
if (!match?.[1]) return null;
|
|
196
|
+
const digits = match[1].length === 3 ? [...match[1]].map((digit) => digit + digit).join("") : match[1];
|
|
197
|
+
return Number.parseInt(digits, 16);
|
|
198
|
+
}
|
|
199
|
+
function blend(track, index, time, resolveColor) {
|
|
200
|
+
const { times, values } = track;
|
|
201
|
+
const from = values[index];
|
|
202
|
+
const to = values[index + 1];
|
|
203
|
+
const t0 = times[index];
|
|
204
|
+
const t1 = times[index + 1];
|
|
205
|
+
if (to === void 0 || t1 <= t0) return from;
|
|
206
|
+
const progress = track.eases[index + 1]((time - t0) / (t1 - t0));
|
|
207
|
+
if (track.step) return progress >= 1 ? to : from;
|
|
208
|
+
switch (track.kind) {
|
|
209
|
+
case "number": return typeof from === "number" && typeof to === "number" ? lerp(from, to, progress) : from;
|
|
210
|
+
case "vec2":
|
|
211
|
+
case "scale": {
|
|
212
|
+
if (track.kind === "scale" && typeof from === "number" && typeof to === "number") return lerp(from, to, progress);
|
|
213
|
+
const a = toVec(from);
|
|
214
|
+
const b = toVec(to);
|
|
215
|
+
if (track.spline) {
|
|
216
|
+
const before = toVec(values[index - 1] ?? from);
|
|
217
|
+
const after = toVec(values[index + 2] ?? to);
|
|
218
|
+
return {
|
|
219
|
+
x: catmullRom(before.x, a.x, b.x, after.x, progress),
|
|
220
|
+
y: catmullRom(before.y, a.y, b.y, after.y, progress)
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
x: lerp(a.x, b.x, progress),
|
|
225
|
+
y: lerp(a.y, b.y, progress)
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
case "color": return mixColor(from, to, progress, resolveColor);
|
|
229
|
+
default: return progress >= 1 ? to : from;
|
|
151
230
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
231
|
+
}
|
|
232
|
+
function sampleBoardTrack(track, time, resolveColor = parseHexColor) {
|
|
233
|
+
const index = keyframeIndex(track.times, time);
|
|
234
|
+
if (index < 0) return track.values[0];
|
|
235
|
+
return blend(track, index, time, resolveColor);
|
|
236
|
+
}
|
|
237
|
+
function orientation(track, time, resolveColor) {
|
|
238
|
+
const span = Math.max(1, (track.times[track.times.length - 1] - track.start) / 1e3);
|
|
239
|
+
const a = toVec(sampleBoardTrack(track, Math.max(track.start, time - span), resolveColor));
|
|
240
|
+
const b = toVec(sampleBoardTrack(track, time + span, resolveColor));
|
|
241
|
+
if (Math.hypot(b.x - a.x, b.y - a.y) < 1e-6) return null;
|
|
242
|
+
return Math.atan2(b.y - a.y, b.x - a.x) * 180 / Math.PI;
|
|
243
|
+
}
|
|
244
|
+
function readPath(value, path) {
|
|
245
|
+
let current = value;
|
|
246
|
+
for (const segment of path) {
|
|
247
|
+
if (typeof current === "number" && (segment === "x" || segment === "y")) return current;
|
|
248
|
+
if (!current || typeof current !== "object") return void 0;
|
|
249
|
+
current = current[segment];
|
|
162
250
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
251
|
+
return current;
|
|
252
|
+
}
|
|
253
|
+
function writePath(value, path, next, depth = 0) {
|
|
254
|
+
const key = path[depth];
|
|
255
|
+
if (depth === path.length - 1) return {
|
|
256
|
+
...value,
|
|
257
|
+
[key]: next
|
|
258
|
+
};
|
|
259
|
+
let child = value[key];
|
|
260
|
+
if (typeof child === "number") child = {
|
|
261
|
+
x: child,
|
|
262
|
+
y: child
|
|
263
|
+
};
|
|
264
|
+
const base = child && typeof child === "object" ? child : {};
|
|
265
|
+
return {
|
|
266
|
+
...value,
|
|
267
|
+
[key]: writePath(base, path, next, depth + 1)
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function combine(track, base, value) {
|
|
271
|
+
if (track.composite !== "add") return value;
|
|
272
|
+
if (track.kind === "number") {
|
|
273
|
+
if (typeof base !== "number" || typeof value !== "number") return value;
|
|
274
|
+
return track.multiplicative ? base * value : base + value;
|
|
167
275
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
276
|
+
if (track.kind === "vec2" || track.kind === "scale") {
|
|
277
|
+
if (track.multiplicative) {
|
|
278
|
+
if (typeof base === "number" && typeof value === "number") return base * value;
|
|
279
|
+
const a = toVec(base ?? 1);
|
|
280
|
+
const b = toVec(value);
|
|
281
|
+
return {
|
|
282
|
+
x: a.x * b.x,
|
|
283
|
+
y: a.y * b.y
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
const a = toVec(base);
|
|
287
|
+
const b = toVec(value);
|
|
288
|
+
return {
|
|
289
|
+
x: a.x + b.x,
|
|
290
|
+
y: a.y + b.y
|
|
179
291
|
};
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
292
|
+
}
|
|
293
|
+
return value;
|
|
294
|
+
}
|
|
295
|
+
function outranks(track, time, other, otherTime) {
|
|
296
|
+
const elapsed = time - track.start;
|
|
297
|
+
const otherElapsed = otherTime - other.start;
|
|
298
|
+
if (elapsed >= 0 !== otherElapsed >= 0) return elapsed >= 0;
|
|
299
|
+
const distance = Math.abs(elapsed);
|
|
300
|
+
const otherDistance = Math.abs(otherElapsed);
|
|
301
|
+
if (distance !== otherDistance) return distance < otherDistance;
|
|
302
|
+
return track.id > other.id;
|
|
303
|
+
}
|
|
304
|
+
function evaluateBoardAnimations(compiled, times, options = {}) {
|
|
305
|
+
const resolveColor = options.resolveColor ?? parseHexColor;
|
|
306
|
+
const local = new Map(times instanceof Map ? times : Object.entries(times));
|
|
307
|
+
for (const id of compiled.order) {
|
|
308
|
+
const animation = compiled.animations.get(id);
|
|
309
|
+
const time = local.get(id);
|
|
310
|
+
if (!animation || time === void 0) continue;
|
|
311
|
+
for (const track of animation.children) {
|
|
312
|
+
const value = sampleBoardTrack(track, time, resolveColor);
|
|
313
|
+
if (typeof value === "number") local.set(track.target, Math.max(0, value));
|
|
191
314
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
315
|
+
}
|
|
316
|
+
const groups = /* @__PURE__ */ new Map();
|
|
317
|
+
for (const [id, time] of local) {
|
|
318
|
+
const animation = compiled.animations.get(id);
|
|
319
|
+
if (!animation) continue;
|
|
320
|
+
for (const track of animation.tracks) {
|
|
321
|
+
const key = `${track.target}\u0000${track.property}`;
|
|
322
|
+
let group = groups.get(key);
|
|
323
|
+
if (!group) {
|
|
324
|
+
group = {
|
|
325
|
+
target: track.target,
|
|
326
|
+
path: track.path,
|
|
327
|
+
winnerTime: 0,
|
|
328
|
+
adds: []
|
|
329
|
+
};
|
|
330
|
+
groups.set(key, group);
|
|
331
|
+
}
|
|
332
|
+
if (track.composite === "add") {
|
|
333
|
+
group.adds.push([track, time]);
|
|
201
334
|
continue;
|
|
202
335
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
for (const key of Object.keys(clipCost)) clipCost[key] = estimate[key] ?? 0;
|
|
208
|
-
events.push({
|
|
209
|
-
at: clip.start,
|
|
210
|
-
direction: 1,
|
|
211
|
-
cost: clipCost
|
|
212
|
-
});
|
|
213
|
-
events.push({
|
|
214
|
-
at: clip.start + clip.duration,
|
|
215
|
-
direction: -1,
|
|
216
|
-
cost: clipCost
|
|
217
|
-
});
|
|
336
|
+
if (!group.winner || outranks(track, time, group.winner, group.winnerTime)) {
|
|
337
|
+
group.winner = track;
|
|
338
|
+
group.winnerTime = time;
|
|
339
|
+
}
|
|
218
340
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
341
|
+
}
|
|
342
|
+
const items = /* @__PURE__ */ new Map();
|
|
343
|
+
const camera = {};
|
|
344
|
+
const ordered = [...groups.values()].sort((a, b) => a.path.length - b.path.length);
|
|
345
|
+
for (const group of ordered) {
|
|
346
|
+
const isCamera = group.target === BOARD_CAMERA_TARGET;
|
|
347
|
+
const base = isCamera ? void 0 : items.get(group.target) ?? compiled.document.items[group.target];
|
|
348
|
+
if (!isCamera && !base) continue;
|
|
349
|
+
let value = isCamera ? camera[group.path[0]] : readPath(base, group.path);
|
|
350
|
+
let orientTrack = null;
|
|
351
|
+
if (group.winner) {
|
|
352
|
+
value = sampleBoardTrack(group.winner, group.winnerTime, resolveColor);
|
|
353
|
+
if (group.winner.orient) orientTrack = [group.winner, group.winnerTime];
|
|
224
354
|
}
|
|
225
|
-
for (const
|
|
226
|
-
|
|
227
|
-
|
|
355
|
+
for (const [track, time] of group.adds) {
|
|
356
|
+
value = combine(track, value, sampleBoardTrack(track, time, resolveColor));
|
|
357
|
+
if (track.orient && !orientTrack) orientTrack = [track, time];
|
|
228
358
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
359
|
+
if (isCamera) {
|
|
360
|
+
camera[group.path[0]] = value;
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
let next = writePath(base, group.path, value);
|
|
364
|
+
if (orientTrack) {
|
|
365
|
+
const angle = orientation(orientTrack[0], orientTrack[1], resolveColor);
|
|
366
|
+
if (angle !== null) next = {
|
|
367
|
+
...next,
|
|
368
|
+
rotation: base.rotation + angle
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
items.set(group.target, next);
|
|
242
372
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
373
|
+
return {
|
|
374
|
+
items,
|
|
375
|
+
camera,
|
|
376
|
+
times: local
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
function applyBoardEvaluation(document, evaluation) {
|
|
380
|
+
if (evaluation.items.size === 0) return document;
|
|
381
|
+
const items = { ...document.items };
|
|
382
|
+
for (const [id, item] of evaluation.items) items[id] = item;
|
|
383
|
+
return {
|
|
384
|
+
...document,
|
|
385
|
+
items
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function boardDocumentAt(document, animationId, time, options = {}) {
|
|
389
|
+
const compiled = compileBoardAnimations(document);
|
|
390
|
+
const times = /* @__PURE__ */ new Map();
|
|
391
|
+
for (const [id, animation] of compiled.animations) if (animation.header.play === "always") times.set(id, boardAnimationTime(animation.header, time) ?? 0);
|
|
392
|
+
if (animationId) {
|
|
393
|
+
const animation = compiled.animations.get(animationId);
|
|
394
|
+
if (animation) times.set(animationId, Math.min(Math.max(0, time), animation.header.duration));
|
|
395
|
+
}
|
|
396
|
+
const evaluation = evaluateBoardAnimations(compiled, times, options);
|
|
397
|
+
return {
|
|
398
|
+
document: applyBoardEvaluation(document, evaluation),
|
|
399
|
+
evaluation
|
|
400
|
+
};
|
|
246
401
|
}
|
|
247
|
-
const BOARD_CHANNELS = BOARD_ANIMATION_CHANNELS;
|
|
248
402
|
//#endregion
|
|
249
|
-
export {
|
|
403
|
+
export { applyBoardEvaluation, boardAnimationTime, boardDocumentAt, boardEase, compileBoardAnimations, evaluateBoardAnimations, parseHexColor, sampleBoardTrack };
|