@omnimedia/omnitool 1.1.0-84 → 1.1.0-86
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/README.md +26 -26
- package/package.json +1 -1
- package/s/demo/routines/timeline-setup.ts +4 -5
- package/s/timeline/parts/animations/properties.ts +1 -5
- package/s/timeline/parts/animations/types.ts +14 -3
- package/s/timeline/parts/item.ts +3 -14
- package/s/timeline/renderers/parts/handy.ts +52 -11
- package/s/timeline/renderers/parts/samplers/visual/parts/sample.ts +2 -2
- package/s/timeline/sugar/helpers.ts +59 -48
- package/s/timeline/sugar/o.ts +79 -48
- package/s/timeline/types.ts +11 -3
- package/s/timeline/utils/anim.ts +0 -9
- package/x/demo/demo.bundle.min.js +100 -100
- package/x/demo/demo.bundle.min.js.map +3 -3
- package/x/demo/routines/timeline-setup.js +4 -3
- package/x/demo/routines/timeline-setup.js.map +1 -1
- package/x/index.html +2 -2
- package/x/tests.bundle.min.js +58 -58
- package/x/tests.bundle.min.js.map +4 -4
- package/x/tests.html +1 -1
- package/x/timeline/parts/animations/properties.d.ts +11 -13
- package/x/timeline/parts/animations/properties.js +1 -4
- package/x/timeline/parts/animations/properties.js.map +1 -1
- package/x/timeline/parts/animations/registry.d.ts +10 -10
- package/x/timeline/parts/animations/types.d.ts +12 -3
- package/x/timeline/parts/item.d.ts +8 -17
- package/x/timeline/parts/item.js +4 -5
- package/x/timeline/parts/item.js.map +1 -1
- package/x/timeline/renderers/parts/handy.js +42 -9
- package/x/timeline/renderers/parts/handy.js.map +1 -1
- package/x/timeline/renderers/parts/samplers/visual/parts/sample.js.map +1 -1
- package/x/timeline/sugar/helpers.d.ts +16 -9
- package/x/timeline/sugar/helpers.js +30 -27
- package/x/timeline/sugar/helpers.js.map +1 -1
- package/x/timeline/sugar/o.d.ts +7 -8
- package/x/timeline/sugar/o.js +52 -35
- package/x/timeline/sugar/o.js.map +1 -1
- package/x/timeline/types.d.ts +6 -3
- package/x/timeline/utils/anim.d.ts +0 -2
- package/x/timeline/utils/anim.js +0 -4
- package/x/timeline/utils/anim.js.map +1 -1
package/README.md
CHANGED
|
@@ -146,22 +146,24 @@ const timeline = omni.timeline(o => {
|
|
|
146
146
|
})
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
-
|
|
149
|
+
Animations:
|
|
150
150
|
|
|
151
151
|
```ts
|
|
152
152
|
const timeline = omni.timeline(o => {
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
const fadeIn = o.animate.opacity.make("easeIn", [
|
|
154
|
+
[0, 0],
|
|
155
|
+
[700, 1],
|
|
156
|
+
])
|
|
157
|
+
const slideOut = o.animate.transform.make("linear", [
|
|
158
|
+
[0, o.transform({position: [0, 0]})],
|
|
159
|
+
[1000, o.transform({position: [400, 0]})],
|
|
160
|
+
])
|
|
159
161
|
|
|
160
162
|
const title = o.text("Lower third", {
|
|
161
163
|
duration: 2000,
|
|
162
164
|
styles: {fill: "white", fontSize: 36}
|
|
163
165
|
})
|
|
164
|
-
o.set(title.id, {
|
|
166
|
+
o.set(title.id, {animationIds: [fadeIn.id, slideOut.id]})
|
|
165
167
|
|
|
166
168
|
return o.stack(
|
|
167
169
|
o.video(clip, {duration: 4000}),
|
|
@@ -170,31 +172,28 @@ const timeline = omni.timeline(o => {
|
|
|
170
172
|
})
|
|
171
173
|
```
|
|
172
174
|
|
|
173
|
-
Built-in
|
|
175
|
+
Built-in transform animations:
|
|
174
176
|
|
|
175
177
|
```ts
|
|
176
178
|
const animOut = {
|
|
177
179
|
duration: 500,
|
|
178
180
|
offset: item.duration - 500,
|
|
179
181
|
}
|
|
180
|
-
const slideIn = o.
|
|
181
|
-
const slideOut = o.
|
|
182
|
-
const spinIn = o.
|
|
183
|
-
const spinOut = o.
|
|
184
|
-
const zoomIn = o.
|
|
185
|
-
const zoomOut = o.
|
|
186
|
-
const bounceIn = o.
|
|
187
|
-
const bounceOut = o.
|
|
182
|
+
const slideIn = o.animate.presets.slideIn.make()
|
|
183
|
+
const slideOut = o.animate.presets.slideOut.make(animOut)
|
|
184
|
+
const spinIn = o.animate.presets.spinIn.make()
|
|
185
|
+
const spinOut = o.animate.presets.spinOut.make(animOut)
|
|
186
|
+
const zoomIn = o.animate.presets.zoomIn.make()
|
|
187
|
+
const zoomOut = o.animate.presets.zoomOut.make(animOut)
|
|
188
|
+
const bounceIn = o.animate.presets.bounceIn.make()
|
|
189
|
+
const bounceOut = o.animate.presets.bounceOut.make(animOut)
|
|
188
190
|
```
|
|
189
191
|
|
|
190
192
|
Built-in scalar animations:
|
|
191
193
|
|
|
192
194
|
```ts
|
|
193
|
-
const
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
const fadeOutPreset = o.anim.presets.fadeOut({duration: 500})
|
|
197
|
-
const fadeOut = o.animate.opacity.make(fadeOutPreset.terp, fadeOutPreset.track)
|
|
195
|
+
const fadeIn = o.animate.presets.fadeIn.make()
|
|
196
|
+
const fadeOut = o.animate.presets.fadeOut.make(animOut)
|
|
198
197
|
```
|
|
199
198
|
|
|
200
199
|
Animation application:
|
|
@@ -233,7 +232,7 @@ const timeline = omni.timeline(o => {
|
|
|
233
232
|
duration: 2000,
|
|
234
233
|
styles: {fill: "white", fontSize: 36},
|
|
235
234
|
})
|
|
236
|
-
o.set(title.id, {
|
|
235
|
+
o.set(title.id, {animationIds: [fadeIn.id]})
|
|
237
236
|
|
|
238
237
|
return o.stack(
|
|
239
238
|
o.video(clip, {duration: 4000}),
|
|
@@ -269,8 +268,9 @@ Object.entries(animationPresets).forEach(([preset, meta]) => {
|
|
|
269
268
|
```
|
|
270
269
|
|
|
271
270
|
Animatable properties describe what can be keyframed, such as `transform` and `opacity`.
|
|
272
|
-
Animation presets describe built-in recipes, such as `slideIn` and `fadeIn
|
|
273
|
-
Use `animationPresets` to list available recipes, and `o.
|
|
271
|
+
Animation presets describe built-in recipes, such as `slideIn` and `fadeIn`.
|
|
272
|
+
Use `animationPresets` to list available recipes, and `o.animate.presets` to create animation items.
|
|
273
|
+
Use `o.animate` to create or apply animation items.
|
|
274
274
|
|
|
275
275
|
Preset options:
|
|
276
276
|
- `duration` sets the animation duration, defaulting to `700`.
|
|
@@ -285,7 +285,7 @@ Utils:
|
|
|
285
285
|
```ts
|
|
286
286
|
import {resolveScalarAnimation, resolveTransformAnimation} from "@omnimedia/omnitool"
|
|
287
287
|
|
|
288
|
-
const transform = resolveTransformAnimation(localTime,
|
|
288
|
+
const transform = resolveTransformAnimation(localTime, transformAnimation)
|
|
289
289
|
const opacity = resolveScalarAnimation(localTime, opacityAnimation)
|
|
290
290
|
```
|
|
291
291
|
|
package/package.json
CHANGED
|
@@ -22,17 +22,16 @@ export async function TimelineSchemaTest(driver: Driver, file: File) {
|
|
|
22
22
|
}),
|
|
23
23
|
[0.15, 0.1, 0.05, 0.2],
|
|
24
24
|
)
|
|
25
|
-
const textSpatial = o.
|
|
26
|
-
|
|
25
|
+
const textSpatial = o.spatial()
|
|
26
|
+
const textMotion = o.animate.transform.make("linear", [
|
|
27
27
|
[0, o.transform({position: [-320, 80], scale: [0.7, 0.7]})],
|
|
28
28
|
[1000, o.transform({position: [120, 80], scale: [1, 1]})],
|
|
29
29
|
[2000, o.transform({position: [200, 40], scale: [1.35, 1.35], rotation: 8})],
|
|
30
30
|
[3000, o.transform({position: [320, 0], scale: [1.15, 1.15], rotation: 0})],
|
|
31
|
-
|
|
32
|
-
)
|
|
31
|
+
])
|
|
33
32
|
|
|
34
33
|
const video = o.video(videoA, {duration: 3000, start: 1000})
|
|
35
|
-
o.set<Item.Text>(text.id, {styleId: style.id, spatialId: textSpatial.id,
|
|
34
|
+
o.set<Item.Text>(text.id, {styleId: style.id, spatialId: textSpatial.id, animationIds: [fade.id, textMotion.id]})
|
|
36
35
|
o.set<Item.Video>(video.id, {spatialId: videoSpatial.id})
|
|
37
36
|
|
|
38
37
|
return o.sequence(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import type {AnimationDefinition} from "./types.js"
|
|
3
3
|
|
|
4
|
-
export const
|
|
4
|
+
export const visualAnimations = {
|
|
5
5
|
transform: {
|
|
6
6
|
type: "transform",
|
|
7
7
|
defaultTerp: "linear",
|
|
@@ -13,9 +13,6 @@ export const spatialAnimations = {
|
|
|
13
13
|
{path: "rotation", type: "number", default: 0, unit: "radian"},
|
|
14
14
|
],
|
|
15
15
|
},
|
|
16
|
-
} as const satisfies Record<string, AnimationDefinition>
|
|
17
|
-
|
|
18
|
-
export const visualAnimations = {
|
|
19
16
|
opacity: {
|
|
20
17
|
type: "scalar",
|
|
21
18
|
defaultTerp: "linear",
|
|
@@ -28,7 +25,6 @@ export const visualAnimations = {
|
|
|
28
25
|
// const audioAnimations = {}
|
|
29
26
|
|
|
30
27
|
export const animatableProperties = {
|
|
31
|
-
...spatialAnimations,
|
|
32
28
|
...visualAnimations,
|
|
33
29
|
} as const
|
|
34
30
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
import {animationPresets} from "./presets.js"
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import type {Item, VisualAnimatableItem} from "../item.js"
|
|
4
|
+
import {visualAnimations, animatableProperties} from "./properties.js"
|
|
5
|
+
import type {Anim, Interpolation, Keyframes, ScalarAnimation, TrackTransform, TransformAnimation, TransformOptions, Vec2} from "../../types.js"
|
|
5
6
|
|
|
6
7
|
export type AnimationType = "scalar" | "transform"
|
|
7
8
|
export type AnimationChannelType = "number"
|
|
@@ -41,7 +42,6 @@ export type AnimationPresetDefinition =
|
|
|
41
42
|
| MotionAnimationPresetDefinition
|
|
42
43
|
| ScalarAnimationPresetDefinition
|
|
43
44
|
|
|
44
|
-
export type SpatialAnimationProperty = keyof typeof spatialAnimations
|
|
45
45
|
export type VisualAnimationProperty = keyof typeof visualAnimations
|
|
46
46
|
export type AnimationProperty = keyof typeof animatableProperties
|
|
47
47
|
export type AnimationPreset = keyof typeof animationPresets
|
|
@@ -67,3 +67,14 @@ export type AnimationPresetOptions<Value> = {
|
|
|
67
67
|
|
|
68
68
|
export type MotionAnimationOptions = AnimationPresetOptions<Vec2>
|
|
69
69
|
export type ScalarAnimationOptions = AnimationPresetOptions<number>
|
|
70
|
+
export type PresetAnimation = ScalarAnimation | TransformAnimation
|
|
71
|
+
export type PresetOptions = MotionAnimationOptions | ScalarAnimationOptions
|
|
72
|
+
|
|
73
|
+
export interface PresetAnimateAction {
|
|
74
|
+
<T extends VisualAnimatableItem>(item: T, options?: PresetOptions): T
|
|
75
|
+
make(options?: PresetOptions): Item.Animation
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type PresetAnimateActions = {
|
|
79
|
+
[TKey in AnimationPreset]: PresetAnimateAction
|
|
80
|
+
}
|
package/s/timeline/parts/item.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {TextStyleOptions} from "pixi.js"
|
|
|
4
4
|
import {Id, Hash} from "./basics.js"
|
|
5
5
|
import {Ms} from "../../units/ms.js"
|
|
6
6
|
import type {FilterParams, FilterType} from "./filters.js"
|
|
7
|
-
import {
|
|
7
|
+
import {Transform, VisualAnimations} from "../types.js"
|
|
8
8
|
|
|
9
9
|
export type Crop = [top: number, right: number, bottom: number, left: number]
|
|
10
10
|
|
|
@@ -16,7 +16,6 @@ export enum Kind {
|
|
|
16
16
|
Text,
|
|
17
17
|
Gap,
|
|
18
18
|
Spatial,
|
|
19
|
-
AnimatedSpatial,
|
|
20
19
|
Animation,
|
|
21
20
|
Transition,
|
|
22
21
|
TextStyle,
|
|
@@ -42,14 +41,6 @@ export namespace Item {
|
|
|
42
41
|
enabled: boolean
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
export type AnimatedSpatial = {
|
|
46
|
-
id: Id
|
|
47
|
-
kind: Kind.AnimatedSpatial
|
|
48
|
-
anim: Anim<TrackTransform>
|
|
49
|
-
crop?: Crop
|
|
50
|
-
enabled: boolean
|
|
51
|
-
}
|
|
52
|
-
|
|
53
44
|
export type Animation = {
|
|
54
45
|
id: Id
|
|
55
46
|
kind: Kind.Animation
|
|
@@ -94,7 +85,7 @@ export namespace Item {
|
|
|
94
85
|
start: number
|
|
95
86
|
duration: number
|
|
96
87
|
spatialId?: Id
|
|
97
|
-
|
|
88
|
+
animationIds?: Id[]
|
|
98
89
|
filterIds?: Id[]
|
|
99
90
|
}
|
|
100
91
|
|
|
@@ -113,7 +104,7 @@ export namespace Item {
|
|
|
113
104
|
content: string
|
|
114
105
|
duration: number
|
|
115
106
|
spatialId?: Id
|
|
116
|
-
|
|
107
|
+
animationIds?: Id[]
|
|
117
108
|
styleId?: Id
|
|
118
109
|
filterIds?: Id[]
|
|
119
110
|
}
|
|
@@ -134,7 +125,6 @@ export namespace Item {
|
|
|
134
125
|
| Gap
|
|
135
126
|
| Transition
|
|
136
127
|
| Spatial
|
|
137
|
-
| AnimatedSpatial
|
|
138
128
|
| Animation
|
|
139
129
|
| TextStyle
|
|
140
130
|
| Filter
|
|
@@ -144,7 +134,6 @@ export namespace Item {
|
|
|
144
134
|
export type ContainerItem = Item.Sequence | Item.Stack
|
|
145
135
|
export type NonContainerItem = Exclude<Item.Any, ContainerItem>
|
|
146
136
|
export type FilterableItem = Item.Sequence | Item.Stack | Item.Video | Item.Text
|
|
147
|
-
export type SpatialItem = Item.Spatial | Item.AnimatedSpatial
|
|
148
137
|
export type VisualAnimatableItem = Item.Video | Item.Text
|
|
149
138
|
|
|
150
139
|
export type PlayableItem = Item.Any & {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import {ms, Ms} from '../../../units/ms.js'
|
|
3
3
|
import {Id, TimelineFile} from '../../parts/basics.js'
|
|
4
|
+
import {Keyframes, TransformAnimation} from '../../types.js'
|
|
4
5
|
import { SampleContext } from './samplers/visual/parts/types.js'
|
|
5
6
|
import {I6, Mat6, mul6, transformToMat6} from '../../utils/matrix.js'
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
7
|
+
import {ContainerItem, Item, Kind, PlayableItem} from '../../parts/item.js'
|
|
8
|
+
import {resolveScalarAnimation, resolveTransformAnimation} from '../../utils/anim.js'
|
|
8
9
|
|
|
9
10
|
function isPlayableItem(item: Item.Any): item is PlayableItem {
|
|
10
11
|
return 'duration' in item
|
|
@@ -98,14 +99,27 @@ function applySpatialIfAny(
|
|
|
98
99
|
parentMatrix: Mat6,
|
|
99
100
|
time: Ms,
|
|
100
101
|
) {
|
|
102
|
+
let matrix = parentMatrix
|
|
101
103
|
if ("spatialId" in item && item.spatialId) {
|
|
102
|
-
const spatial = items.get(item.spatialId) as
|
|
104
|
+
const spatial = items.get(item.spatialId) as Item.Spatial | undefined
|
|
103
105
|
if (spatial?.enabled) {
|
|
104
|
-
const local = transformToMat6(
|
|
105
|
-
|
|
106
|
+
const local = transformToMat6(spatial.transform)
|
|
107
|
+
matrix = mul6(local, matrix)
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
|
-
|
|
110
|
+
|
|
111
|
+
if ("animationIds" in item && item.animationIds) {
|
|
112
|
+
for (const id of item.animationIds) {
|
|
113
|
+
const animation = items.get(id) as Item.Animation | undefined
|
|
114
|
+
const anim = animation?.anims.transform
|
|
115
|
+
if (animation?.enabled && anim && transformActiveAt(anim, time)) {
|
|
116
|
+
const local = transformToMat6(resolveTransformAnimation(time, anim))
|
|
117
|
+
matrix = mul6(local, matrix)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return matrix
|
|
109
123
|
}
|
|
110
124
|
|
|
111
125
|
export function walk(
|
|
@@ -366,12 +380,39 @@ export function computeOpacity(
|
|
|
366
380
|
item: Item.Any,
|
|
367
381
|
time: Ms,
|
|
368
382
|
) {
|
|
369
|
-
if (!("
|
|
383
|
+
if (!("animationIds" in item) || item.animationIds === undefined)
|
|
370
384
|
return 1
|
|
371
385
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
386
|
+
let opacity = 1
|
|
387
|
+
for (const id of item.animationIds) {
|
|
388
|
+
const animation = ctx.items.get(id) as Item.Animation | undefined
|
|
389
|
+
const anim = animation?.anims.opacity
|
|
390
|
+
if (animation?.enabled && anim && keyframesActiveAt(anim.track, time))
|
|
391
|
+
opacity = resolveScalarAnimation(time, anim)
|
|
392
|
+
}
|
|
393
|
+
return opacity
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function keyframesActiveAt(keys: Keyframes, time: Ms) {
|
|
397
|
+
if (keys.length === 0)
|
|
398
|
+
return false
|
|
399
|
+
|
|
400
|
+
let start = keys[0][0]
|
|
401
|
+
let end = keys[0][0]
|
|
402
|
+
for (const [keyTime] of keys) {
|
|
403
|
+
start = Math.min(start, keyTime)
|
|
404
|
+
end = Math.max(end, keyTime)
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return time >= start && time <= end
|
|
376
408
|
}
|
|
377
409
|
|
|
410
|
+
function transformActiveAt(anim: TransformAnimation, time: Ms) {
|
|
411
|
+
return (
|
|
412
|
+
keyframesActiveAt(anim.track.position.x, time) ||
|
|
413
|
+
keyframesActiveAt(anim.track.position.y, time) ||
|
|
414
|
+
keyframesActiveAt(anim.track.scale.x, time) ||
|
|
415
|
+
keyframesActiveAt(anim.track.scale.y, time) ||
|
|
416
|
+
keyframesActiveAt(anim.track.rotation, time)
|
|
417
|
+
)
|
|
418
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {SampleContext} from "./types.js"
|
|
3
3
|
import {sampleSequence} from "./sequence.js"
|
|
4
4
|
import {Ms} from "../../../../../../units/ms.js"
|
|
5
|
-
import {Item, Kind
|
|
5
|
+
import {Item, Kind} from "../../../../../parts/item.js"
|
|
6
6
|
import {FilterSpec, Layer} from "../../../../../../driver/fns/schematic.js"
|
|
7
7
|
import {AncestorAt, computeOpacity, computeWorldMatrix} from "../../../handy.js"
|
|
8
8
|
|
|
@@ -15,7 +15,7 @@ export async function sampleVisual(
|
|
|
15
15
|
const matrix = computeWorldMatrix(ctx.items, ancestors, item, time)
|
|
16
16
|
const alpha = computeOpacity(ctx, item, time)
|
|
17
17
|
const crop = "spatialId" in item && item.spatialId
|
|
18
|
-
? (ctx.items.get(item.spatialId) as
|
|
18
|
+
? (ctx.items.get(item.spatialId) as Item.Spatial | undefined)?.crop
|
|
19
19
|
: undefined
|
|
20
20
|
const filters = "filterIds" in item && item.filterIds
|
|
21
21
|
? item.filterIds
|
|
@@ -6,37 +6,17 @@ import {Media} from "../parts/media.js"
|
|
|
6
6
|
import {TimelineFile} from "../parts/basics.js"
|
|
7
7
|
import {FilterAction} from "../parts/filters.js"
|
|
8
8
|
import {filters, FilterParams, FilterType} from "../parts/filters.js"
|
|
9
|
+
import {AnimationPreset, PresetOptions} from "../parts/animations/types.js"
|
|
9
10
|
import {Crop, FilterableItem, Item, VisualAnimatableItem} from "../parts/item.js"
|
|
10
|
-
import {
|
|
11
|
-
import {Anim, AnimateAction, Interpolation, Keyframes, TrackTransform, Transform,
|
|
12
|
-
|
|
13
|
-
const transformFrom = (options: TransformOptions): Transform => [
|
|
14
|
-
options.position ?? [0, 0],
|
|
15
|
-
options.scale ?? [1, 1],
|
|
16
|
-
options.rotation ?? 0,
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
const transformAnimation = (terp: Interpolation, source: Keyframes<Transform>): Anim<TrackTransform> => {
|
|
20
|
-
const track: TrackTransform = {
|
|
21
|
-
position: {x: [], y: []},
|
|
22
|
-
scale: {x: [], y: []},
|
|
23
|
-
rotation: [],
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
for (const [time, [position, scale, rotation]] of source) {
|
|
27
|
-
track.position.x.push([time, position[0]])
|
|
28
|
-
track.position.y.push([time, position[1]])
|
|
29
|
-
track.scale.x.push([time, scale[0]])
|
|
30
|
-
track.scale.y.push([time, scale[1]])
|
|
31
|
-
track.rotation.push([time, rotation])
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return {terp, track}
|
|
35
|
-
}
|
|
11
|
+
import {animationPresets, visualAnimations} from "../parts/animations/registry.js"
|
|
12
|
+
import {Anim, AnimateAction, Interpolation, Keyframes, TrackTransform, Transform, Vec2, VisualAnimationInput, VisualAnimations} from "../types.js"
|
|
36
13
|
|
|
37
14
|
export type Build<T extends Item.Any = Item.Any> = (o: O) => T
|
|
38
15
|
type BuildVisualAnimateActions = {
|
|
39
|
-
[TKey in keyof VisualAnimations]-?: BuildAnimateAction
|
|
16
|
+
[TKey in keyof VisualAnimations]-?: BuildAnimateAction<TKey>
|
|
17
|
+
}
|
|
18
|
+
type BuildPresetAnimateActions = {
|
|
19
|
+
[TKey in AnimationPreset]: BuildPresetAnimateAction
|
|
40
20
|
}
|
|
41
21
|
|
|
42
22
|
function createTimeline(): TimelineFile {
|
|
@@ -103,10 +83,6 @@ export function spatial(transform?: Transform, crop?: Crop): Build<Item.Spatial>
|
|
|
103
83
|
return o => o.spatial(transform, crop)
|
|
104
84
|
}
|
|
105
85
|
|
|
106
|
-
export function animatedSpatial(anim: Anim<TrackTransform>, crop?: Crop): Build<Item.AnimatedSpatial> {
|
|
107
|
-
return o => o.animatedSpatial(anim, crop)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
86
|
export const anim = {
|
|
111
87
|
scalar(terp: Interpolation, track: Keyframes): Anim<Keyframes> {
|
|
112
88
|
return {terp, track}
|
|
@@ -123,13 +99,23 @@ export const anim = {
|
|
|
123
99
|
return {terp, track}
|
|
124
100
|
},
|
|
125
101
|
|
|
126
|
-
transform:
|
|
102
|
+
transform: (terp: Interpolation, source: Keyframes<Transform>): Anim<TrackTransform> => {
|
|
103
|
+
const track: TrackTransform = {
|
|
104
|
+
position: {x: [], y: []},
|
|
105
|
+
scale: {x: [], y: []},
|
|
106
|
+
rotation: [],
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for (const [time, [position, scale, rotation]] of source) {
|
|
110
|
+
track.position.x.push([time, position[0]])
|
|
111
|
+
track.position.y.push([time, position[1]])
|
|
112
|
+
track.scale.x.push([time, scale[0]])
|
|
113
|
+
track.scale.y.push([time, scale[1]])
|
|
114
|
+
track.rotation.push([time, rotation])
|
|
115
|
+
}
|
|
127
116
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
transformAnimation,
|
|
131
|
-
transformFrom,
|
|
132
|
-
),
|
|
117
|
+
return {terp, track}
|
|
118
|
+
}
|
|
133
119
|
}
|
|
134
120
|
|
|
135
121
|
interface BuildFilterAction<TFilter extends FilterType> {
|
|
@@ -137,13 +123,18 @@ interface BuildFilterAction<TFilter extends FilterType> {
|
|
|
137
123
|
make(params?: FilterParams<TFilter>): Build<Item.Filter<TFilter>>
|
|
138
124
|
}
|
|
139
125
|
|
|
140
|
-
interface BuildAnimateAction {
|
|
126
|
+
interface BuildAnimateAction<TKey extends keyof VisualAnimations = keyof VisualAnimations> {
|
|
141
127
|
<T extends VisualAnimatableItem>(
|
|
142
128
|
item: Build<T>,
|
|
143
129
|
terp: Interpolation,
|
|
144
|
-
track:
|
|
130
|
+
track: VisualAnimationInput<TKey>
|
|
145
131
|
): Build<T>
|
|
146
|
-
make(terp: Interpolation, track:
|
|
132
|
+
make(terp: Interpolation, track: VisualAnimationInput<TKey>): Build<Item.Animation>
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
interface BuildPresetAnimateAction {
|
|
136
|
+
<T extends VisualAnimatableItem>(item: Build<T>, options?: PresetOptions): Build<T>
|
|
137
|
+
make(options?: PresetOptions): Build<Item.Animation>
|
|
147
138
|
}
|
|
148
139
|
|
|
149
140
|
type BuildFilterActions = {
|
|
@@ -172,25 +163,45 @@ function makeFilters(): BuildFilterActions {
|
|
|
172
163
|
|
|
173
164
|
export const filter = makeFilters()
|
|
174
165
|
|
|
175
|
-
function makeAnimate(
|
|
176
|
-
get: (o: O) => AnimateAction
|
|
177
|
-
): BuildAnimateAction {
|
|
166
|
+
function makeAnimate<TKey extends keyof VisualAnimations>(
|
|
167
|
+
get: (o: O) => AnimateAction<TKey>
|
|
168
|
+
): BuildAnimateAction<TKey> {
|
|
178
169
|
const action = (<T extends VisualAnimatableItem>(
|
|
179
170
|
item: Build<T>,
|
|
180
171
|
terp: Interpolation,
|
|
181
|
-
track:
|
|
182
|
-
): Build<T> => o => get(o)(item(o), terp, track)) as BuildAnimateAction
|
|
183
|
-
action.make = (terp: Interpolation, track:
|
|
172
|
+
track: VisualAnimationInput<TKey>
|
|
173
|
+
): Build<T> => o => get(o)(item(o), terp, track)) as BuildAnimateAction<TKey>
|
|
174
|
+
action.make = (terp: Interpolation, track: VisualAnimationInput<TKey>) => o => get(o).make(terp, track)
|
|
184
175
|
return action
|
|
185
176
|
}
|
|
186
177
|
|
|
187
178
|
function makeAnimateActions(): BuildVisualAnimateActions {
|
|
188
179
|
const entries = Object.keys(visualAnimations)
|
|
189
|
-
.map(key => [key, makeAnimate(o => o.animate[key as keyof VisualAnimations] as AnimateAction)])
|
|
180
|
+
.map(key => [key, makeAnimate(o => o.animate[key as keyof VisualAnimations] as AnimateAction<any>)])
|
|
190
181
|
return Object.fromEntries(entries) as BuildVisualAnimateActions
|
|
191
182
|
}
|
|
192
183
|
|
|
193
|
-
|
|
184
|
+
function makePresetAnimate(
|
|
185
|
+
key: AnimationPreset
|
|
186
|
+
): BuildPresetAnimateAction {
|
|
187
|
+
const action = (<T extends VisualAnimatableItem>(
|
|
188
|
+
item: Build<T>,
|
|
189
|
+
options?: PresetOptions
|
|
190
|
+
): Build<T> => o => o.animate.presets[key](item(o), options)) as BuildPresetAnimateAction
|
|
191
|
+
action.make = (options?: PresetOptions) => o => o.animate.presets[key].make(options)
|
|
192
|
+
return action
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function makePresetAnimateActions(): BuildPresetAnimateActions {
|
|
196
|
+
const entries = Object.keys(animationPresets)
|
|
197
|
+
.map(key => [key, makePresetAnimate(key as AnimationPreset)])
|
|
198
|
+
return Object.fromEntries(entries) as BuildPresetAnimateActions
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export const animate = {
|
|
202
|
+
...makeAnimateActions(),
|
|
203
|
+
presets: makePresetAnimateActions(),
|
|
204
|
+
}
|
|
194
205
|
|
|
195
206
|
export function textStyle(style: TextStyleOptions): Build<Item.TextStyle> {
|
|
196
207
|
return o => o.textStyle(style)
|