@omnimedia/omnitool 1.1.0-104 → 1.1.0-106
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 +13 -0
- package/package.json +1 -1
- package/s/timeline/parts/captions.ts +2 -0
- package/s/timeline/parts/item.ts +18 -12
- package/s/timeline/parts/transitions.ts +2 -2
- package/s/timeline/renderers/parts/handy.ts +3 -3
- package/s/timeline/renderers/parts/samplers/audio/parts/init.ts +2 -0
- package/s/timeline/renderers/parts/samplers/visual/parts/sample.ts +10 -5
- package/s/timeline/renderers/parts/samplers/visual/parts/sequence.ts +3 -0
- package/s/timeline/renderers/renderers.test.ts +15 -0
- package/s/timeline/sugar/helpers.ts +30 -9
- package/s/timeline/sugar/o.ts +38 -9
- package/x/demo/demo.bundle.min.js +1 -1
- package/x/demo/demo.bundle.min.js.map +3 -3
- package/x/index.html +2 -2
- package/x/tests.bundle.min.js +48 -48
- package/x/tests.bundle.min.js.map +3 -3
- package/x/tests.html +1 -1
- package/x/timeline/parts/captions.d.ts +2 -0
- package/x/timeline/parts/captions.js.map +1 -1
- package/x/timeline/parts/item.d.ts +17 -12
- package/x/timeline/parts/transitions.d.ts +2 -2
- package/x/timeline/renderers/parts/handy.js +3 -3
- package/x/timeline/renderers/parts/handy.js.map +1 -1
- package/x/timeline/renderers/parts/samplers/audio/parts/init.js +2 -0
- package/x/timeline/renderers/parts/samplers/audio/parts/init.js.map +1 -1
- package/x/timeline/renderers/parts/samplers/visual/parts/sample.js +9 -5
- package/x/timeline/renderers/parts/samplers/visual/parts/sample.js.map +1 -1
- package/x/timeline/renderers/parts/samplers/visual/parts/sequence.js +2 -0
- package/x/timeline/renderers/parts/samplers/visual/parts/sequence.js.map +1 -1
- package/x/timeline/renderers/renderers.test.d.ts +1 -0
- package/x/timeline/renderers/renderers.test.js +9 -0
- package/x/timeline/renderers/renderers.test.js.map +1 -1
- package/x/timeline/sugar/helpers.d.ts +14 -5
- package/x/timeline/sugar/helpers.js +19 -7
- package/x/timeline/sugar/helpers.js.map +1 -1
- package/x/timeline/sugar/o.d.ts +14 -4
- package/x/timeline/sugar/o.js +27 -8
- package/x/timeline/sugar/o.js.map +1 -1
package/README.md
CHANGED
|
@@ -56,6 +56,19 @@ const timeline = omni.timeline(o => {
|
|
|
56
56
|
})
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
Items can have `label` and `enabled` fields:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
const visual = o.sequence(
|
|
63
|
+
"Main sequence",
|
|
64
|
+
o.video(clip, {label: "Intro"}),
|
|
65
|
+
o.transition.fade(500, {label: "Fade", enabled: false}),
|
|
66
|
+
o.text("Hello world", {label: "Title", enabled: false})
|
|
67
|
+
)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Disabled items do not render or play audio, but still keep their timeline duration and occupy space.
|
|
71
|
+
|
|
59
72
|
Declarative helper style (no explicit `o` in timeline declarations):
|
|
60
73
|
|
|
61
74
|
```ts
|
package/package.json
CHANGED
|
@@ -5,6 +5,8 @@ import {TransformOptions, Vec2} from "../types.js"
|
|
|
5
5
|
import {Transcription, TranscriptSegment} from "../../features/speech/transcribe/types.js"
|
|
6
6
|
|
|
7
7
|
export type CaptionOptions = {
|
|
8
|
+
label?: string
|
|
9
|
+
enabled?: boolean
|
|
8
10
|
itemId?: Item.Caption["itemId"]
|
|
9
11
|
start?: number
|
|
10
12
|
duration?: number
|
package/s/timeline/parts/item.ts
CHANGED
|
@@ -26,11 +26,17 @@ export enum Kind {
|
|
|
26
26
|
Image
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
export type ItemBase = {
|
|
30
|
+
label?: string
|
|
31
|
+
enabled?: boolean
|
|
32
|
+
}
|
|
33
|
+
|
|
29
34
|
export namespace Item {
|
|
30
35
|
export type TextStyle = {
|
|
31
36
|
id: Id
|
|
32
37
|
kind: Kind.TextStyle
|
|
33
38
|
style: TextStyleOptions
|
|
39
|
+
enabled?: boolean
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
export type Spatial = {
|
|
@@ -38,14 +44,14 @@ export namespace Item {
|
|
|
38
44
|
kind: Kind.Spatial
|
|
39
45
|
transform: Transform
|
|
40
46
|
crop?: Crop
|
|
41
|
-
enabled
|
|
47
|
+
enabled?: boolean
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
export type Animation = {
|
|
45
51
|
id: Id
|
|
46
52
|
kind: Kind.Animation
|
|
47
53
|
anims: VisualAnimations
|
|
48
|
-
enabled
|
|
54
|
+
enabled?: boolean
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
export type Filter<T extends FilterType = FilterType> = {
|
|
@@ -53,14 +59,14 @@ export namespace Item {
|
|
|
53
59
|
kind: Kind.Filter
|
|
54
60
|
type: T
|
|
55
61
|
params?: FilterParams<T>
|
|
56
|
-
enabled
|
|
62
|
+
enabled?: boolean
|
|
57
63
|
}
|
|
58
64
|
|
|
59
65
|
export type Gap = {
|
|
60
66
|
id: Id
|
|
61
67
|
kind: Kind.Gap
|
|
62
68
|
duration: number
|
|
63
|
-
}
|
|
69
|
+
} & ItemBase
|
|
64
70
|
|
|
65
71
|
export type Sequence = {
|
|
66
72
|
id: Id
|
|
@@ -68,7 +74,7 @@ export namespace Item {
|
|
|
68
74
|
childrenIds: Id[]
|
|
69
75
|
spatialId?: Id
|
|
70
76
|
filterIds?: Id[]
|
|
71
|
-
}
|
|
77
|
+
} & ItemBase
|
|
72
78
|
|
|
73
79
|
export type Stack = {
|
|
74
80
|
id: Id
|
|
@@ -76,7 +82,7 @@ export namespace Item {
|
|
|
76
82
|
childrenIds: Id[]
|
|
77
83
|
spatialId?: Id
|
|
78
84
|
filterIds?: Id[]
|
|
79
|
-
}
|
|
85
|
+
} & ItemBase
|
|
80
86
|
|
|
81
87
|
export type Video = {
|
|
82
88
|
id: Id
|
|
@@ -87,7 +93,7 @@ export namespace Item {
|
|
|
87
93
|
spatialId?: Id
|
|
88
94
|
animationIds?: Id[]
|
|
89
95
|
filterIds?: Id[]
|
|
90
|
-
}
|
|
96
|
+
} & ItemBase
|
|
91
97
|
|
|
92
98
|
export type Image = {
|
|
93
99
|
id: Id
|
|
@@ -97,7 +103,7 @@ export namespace Item {
|
|
|
97
103
|
spatialId?: Id
|
|
98
104
|
animationIds?: Id[]
|
|
99
105
|
filterIds?: Id[]
|
|
100
|
-
}
|
|
106
|
+
} & ItemBase
|
|
101
107
|
|
|
102
108
|
export type Audio = {
|
|
103
109
|
id: Id
|
|
@@ -106,7 +112,7 @@ export namespace Item {
|
|
|
106
112
|
start: number
|
|
107
113
|
duration: number
|
|
108
114
|
gain?: number
|
|
109
|
-
}
|
|
115
|
+
} & ItemBase
|
|
110
116
|
|
|
111
117
|
export type Text = {
|
|
112
118
|
id: Id
|
|
@@ -117,7 +123,7 @@ export namespace Item {
|
|
|
117
123
|
animationIds?: Id[]
|
|
118
124
|
styleId?: Id
|
|
119
125
|
filterIds?: Id[]
|
|
120
|
-
}
|
|
126
|
+
} & ItemBase
|
|
121
127
|
|
|
122
128
|
|
|
123
129
|
export type Caption = {
|
|
@@ -134,14 +140,14 @@ export namespace Item {
|
|
|
134
140
|
animationIds?: Id[]
|
|
135
141
|
styleId?: Id
|
|
136
142
|
filterIds?: Id[]
|
|
137
|
-
}
|
|
143
|
+
} & ItemBase
|
|
138
144
|
|
|
139
145
|
export type Transition = {
|
|
140
146
|
id: Id
|
|
141
147
|
kind: Kind.Transition
|
|
142
148
|
name: TransitionName
|
|
143
149
|
duration: number
|
|
144
|
-
}
|
|
150
|
+
} & ItemBase
|
|
145
151
|
|
|
146
152
|
export type Any = (
|
|
147
153
|
| Sequence
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {Item} from "./item.js"
|
|
1
|
+
import type {Item, ItemBase} from "./item.js"
|
|
2
2
|
|
|
3
3
|
export const transitionNames = [
|
|
4
4
|
"Bounce",
|
|
@@ -78,7 +78,7 @@ export type Transition = {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
export interface TransitionAction {
|
|
81
|
-
(duration: number): Item.Transition
|
|
81
|
+
(duration: number, options?: ItemBase): Item.Transition
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
export type TransitionActions = {
|
|
@@ -110,7 +110,7 @@ function applySpatialIfAny(
|
|
|
110
110
|
let matrix = parentMatrix
|
|
111
111
|
if ("spatialId" in item && item.spatialId) {
|
|
112
112
|
const spatial = items.get(item.spatialId) as Item.Spatial | undefined
|
|
113
|
-
if (spatial
|
|
113
|
+
if (spatial && spatial.enabled !== false) {
|
|
114
114
|
const local = transformToMat6(spatial.transform)
|
|
115
115
|
matrix = mul6(local, matrix)
|
|
116
116
|
}
|
|
@@ -120,7 +120,7 @@ function applySpatialIfAny(
|
|
|
120
120
|
for (const id of item.animationIds) {
|
|
121
121
|
const animation = items.get(id) as Item.Animation | undefined
|
|
122
122
|
const anim = animation?.anims.transform
|
|
123
|
-
if (animation?.enabled && anim && transformActiveAt(anim, time)) {
|
|
123
|
+
if (animation?.enabled !== false && anim && transformActiveAt(anim, time)) {
|
|
124
124
|
const local = transformToMat6(resolveTransformAnimation(time, anim))
|
|
125
125
|
matrix = mul6(local, matrix)
|
|
126
126
|
}
|
|
@@ -410,7 +410,7 @@ export function computeOpacity(
|
|
|
410
410
|
for (const id of item.animationIds) {
|
|
411
411
|
const animation = ctx.items.get(id) as Item.Animation | undefined
|
|
412
412
|
const anim = animation?.anims.opacity
|
|
413
|
-
if (animation?.enabled && anim && keyframesActiveAt(anim.track, time))
|
|
413
|
+
if (animation?.enabled !== false && anim && keyframesActiveAt(anim.track, time))
|
|
414
414
|
opacity = resolveScalarAnimation(time, anim)
|
|
415
415
|
}
|
|
416
416
|
return opacity
|
|
@@ -17,6 +17,9 @@ export async function sampleVisual(
|
|
|
17
17
|
allowHandles?: boolean
|
|
18
18
|
} = {}
|
|
19
19
|
): Promise<Layer[]> {
|
|
20
|
+
if ("enabled" in item && item.enabled === false)
|
|
21
|
+
return item.kind === Kind.Gap ? [{id: item.id, kind: "gap"}] : []
|
|
22
|
+
|
|
20
23
|
const matrix = computeWorldMatrix(ctx.items, ancestors, item, time)
|
|
21
24
|
const alpha = computeOpacity(ctx, item, time)
|
|
22
25
|
const crop = "spatialId" in item && item.spatialId
|
|
@@ -25,7 +28,7 @@ export async function sampleVisual(
|
|
|
25
28
|
const filters = "filterIds" in item && item.filterIds
|
|
26
29
|
? item.filterIds
|
|
27
30
|
.map(id => ctx.items.get(id) as Item.Filter | undefined)
|
|
28
|
-
.filter((filter): filter is Item.Filter => !!filter
|
|
31
|
+
.filter((filter): filter is Item.Filter => !!filter && filter.enabled !== false)
|
|
29
32
|
.map(filter => ({type: filter.type, params: filter.params}) as FilterSpec)
|
|
30
33
|
: undefined
|
|
31
34
|
|
|
@@ -63,9 +66,10 @@ export async function sampleVisual(
|
|
|
63
66
|
case Kind.Text: {
|
|
64
67
|
if (!options.allowHandles && (time < 0 || time >= item.duration)) return []
|
|
65
68
|
|
|
66
|
-
const
|
|
67
|
-
?
|
|
69
|
+
const textStyle = item.styleId
|
|
70
|
+
? ctx.items.get(item.styleId) as Item.TextStyle | undefined
|
|
68
71
|
: undefined
|
|
72
|
+
const style = textStyle?.enabled !== false ? textStyle?.style : undefined
|
|
69
73
|
|
|
70
74
|
return [{id: item.id, kind: "text", content: item.content, style, matrix, alpha, crop, filters}]
|
|
71
75
|
}
|
|
@@ -81,9 +85,10 @@ export async function sampleVisual(
|
|
|
81
85
|
if (!segment)
|
|
82
86
|
return []
|
|
83
87
|
|
|
84
|
-
const
|
|
85
|
-
?
|
|
88
|
+
const textStyle = item.styleId
|
|
89
|
+
? ctx.items.get(item.styleId) as Item.TextStyle | undefined
|
|
86
90
|
: undefined
|
|
91
|
+
const style = textStyle?.enabled !== false ? textStyle?.style : undefined
|
|
87
92
|
|
|
88
93
|
return [{id: item.id, kind: "text", content: segment.text, style, matrix, alpha, crop, filters}]
|
|
89
94
|
}
|
|
@@ -53,6 +53,9 @@ function sampleSequenceAt(ctx: SampleContext, seq: Item.Sequence, time: Ms) {
|
|
|
53
53
|
|
|
54
54
|
const localTime = ms(time - cursor)
|
|
55
55
|
|
|
56
|
+
if (child.enabled === false)
|
|
57
|
+
return {isTransitioning: false, item: child, localTime} as const
|
|
58
|
+
|
|
56
59
|
if (child.kind !== Kind.Transition)
|
|
57
60
|
return {isTransitioning: false, item: child, localTime} as const
|
|
58
61
|
|
|
@@ -92,6 +92,21 @@ export default Science.suite({
|
|
|
92
92
|
expect(textLayer[0].kind).is("text")
|
|
93
93
|
}),
|
|
94
94
|
|
|
95
|
+
"disabled visual item keeps sequence time but does not render": test(async () => {
|
|
96
|
+
const {omni, videoA, resolveMedia} = await setupTest()
|
|
97
|
+
const {timeline} = new O({timeline: omni.timeline(o => o.sequence(
|
|
98
|
+
o.video(videoA, {duration: 2000, enabled: false}),
|
|
99
|
+
o.video(videoA, {duration: 2000}),
|
|
100
|
+
))})
|
|
101
|
+
const sampler = createVisualSampler(resolveMedia)
|
|
102
|
+
|
|
103
|
+
const disabledLayers = await sampler.sample(timeline, ms(1000))
|
|
104
|
+
expect(disabledLayers.length).is(0)
|
|
105
|
+
|
|
106
|
+
const nextLayers = await sampler.sample(timeline, ms(2500))
|
|
107
|
+
expect(nextLayers[0].kind).is("image")
|
|
108
|
+
}),
|
|
109
|
+
|
|
95
110
|
"audio mix sums overlapping chunks": test(async () => {
|
|
96
111
|
const mixer = new AudioMix({chunkFrames: 4, clamp: false})
|
|
97
112
|
async function *samples() {
|
|
@@ -10,7 +10,7 @@ import {filters, FilterParams, FilterType} from "../parts/filters.js"
|
|
|
10
10
|
import {CaptionOptions, CaptionSourceItem} from "../parts/captions.js"
|
|
11
11
|
import {Transcription} from "../../features/speech/transcribe/types.js"
|
|
12
12
|
import {AnimationPreset, PresetOptions} from "../parts/animations/types.js"
|
|
13
|
-
import {Crop, FilterableItem, Item, VisualAnimatableItem} from "../parts/item.js"
|
|
13
|
+
import {Crop, FilterableItem, Item, ItemBase, VisualAnimatableItem} from "../parts/item.js"
|
|
14
14
|
import {animationPresets, visualAnimations} from "../parts/animations/registry.js"
|
|
15
15
|
import {Anim, AnimateAction, Interpolation, Keyframes, TrackTransform, Transform, Vec2, VisualAnimationInput, VisualAnimations} from "../types.js"
|
|
16
16
|
|
|
@@ -22,8 +22,9 @@ type BuildPresetAnimateActions = {
|
|
|
22
22
|
[TKey in AnimationPreset]: BuildPresetAnimateAction
|
|
23
23
|
}
|
|
24
24
|
type BuildTransitionActions = {
|
|
25
|
-
[TKey in TransitionName]: (duration: number) => Build<Item.Transition>
|
|
25
|
+
[TKey in TransitionName]: (duration: number, options?: ItemBase) => Build<Item.Transition>
|
|
26
26
|
}
|
|
27
|
+
type ContainerInput = [label: string, ...items: Build[]] | Build[]
|
|
27
28
|
|
|
28
29
|
function createTimeline(): TimelineFile {
|
|
29
30
|
return {
|
|
@@ -42,12 +43,24 @@ export function timeline(root: Build): TimelineFile {
|
|
|
42
43
|
return o.timeline
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
export function sequence(...
|
|
46
|
-
|
|
46
|
+
export function sequence(...input: ContainerInput): Build<Item.Sequence> {
|
|
47
|
+
const [first, ...rest] = input
|
|
48
|
+
const label = typeof first === "string" ? first : undefined
|
|
49
|
+
const items = (label ? rest : input) as Build[]
|
|
50
|
+
return o => {
|
|
51
|
+
const built = items.map(item => item(o))
|
|
52
|
+
return label ? o.sequence(label, ...built) : o.sequence(...built)
|
|
53
|
+
}
|
|
47
54
|
}
|
|
48
55
|
|
|
49
|
-
export function stack(...
|
|
50
|
-
|
|
56
|
+
export function stack(...input: ContainerInput): Build<Item.Stack> {
|
|
57
|
+
const [first, ...rest] = input
|
|
58
|
+
const label = typeof first === "string" ? first : undefined
|
|
59
|
+
const items = (label ? rest : input) as Build[]
|
|
60
|
+
return o => {
|
|
61
|
+
const built = items.map(item => item(o))
|
|
62
|
+
return label ? o.stack(label, ...built) : o.stack(...built)
|
|
63
|
+
}
|
|
51
64
|
}
|
|
52
65
|
|
|
53
66
|
export function video(
|
|
@@ -55,6 +68,8 @@ export function video(
|
|
|
55
68
|
options?: {
|
|
56
69
|
start?: number,
|
|
57
70
|
duration?: number
|
|
71
|
+
label?: string
|
|
72
|
+
enabled?: boolean
|
|
58
73
|
}
|
|
59
74
|
): Build<Item.Video> {
|
|
60
75
|
return o => o.video(media, options)
|
|
@@ -64,6 +79,8 @@ export function image(
|
|
|
64
79
|
media: Media,
|
|
65
80
|
options?: {
|
|
66
81
|
duration?: number
|
|
82
|
+
label?: string
|
|
83
|
+
enabled?: boolean
|
|
67
84
|
}
|
|
68
85
|
): Build<Item.Image> {
|
|
69
86
|
return o => o.image(media, options)
|
|
@@ -75,6 +92,8 @@ export function audio(
|
|
|
75
92
|
start?: number,
|
|
76
93
|
duration?: number,
|
|
77
94
|
gain?: number
|
|
95
|
+
label?: string
|
|
96
|
+
enabled?: boolean
|
|
78
97
|
}
|
|
79
98
|
): Build<Item.Audio> {
|
|
80
99
|
return o => o.audio(media, options)
|
|
@@ -85,6 +104,8 @@ export function text(
|
|
|
85
104
|
options?: {
|
|
86
105
|
duration?: number,
|
|
87
106
|
styles?: TextStyleOptions
|
|
107
|
+
label?: string
|
|
108
|
+
enabled?: boolean
|
|
88
109
|
}
|
|
89
110
|
): Build<Item.Text> {
|
|
90
111
|
return o => o.text(content, options)
|
|
@@ -98,8 +119,8 @@ export function captions(
|
|
|
98
119
|
return o => o.captions(item(o), transcript, options)
|
|
99
120
|
}
|
|
100
121
|
|
|
101
|
-
export function gap(duration: number): Build<Item.Gap> {
|
|
102
|
-
return o => o.gap(duration)
|
|
122
|
+
export function gap(duration: number, options?: ItemBase): Build<Item.Gap> {
|
|
123
|
+
return o => o.gap(duration, options)
|
|
103
124
|
}
|
|
104
125
|
|
|
105
126
|
export function spatial(transform?: Transform, crop?: Crop): Build<Item.Spatial> {
|
|
@@ -232,7 +253,7 @@ export function textStyle(style: TextStyleOptions): Build<Item.TextStyle> {
|
|
|
232
253
|
|
|
233
254
|
function makeTransitionActions(): BuildTransitionActions {
|
|
234
255
|
const entries = Object.keys(transitions)
|
|
235
|
-
.map(key => [key, (duration: number) => (o: O) => o.transition[key as TransitionName](duration)])
|
|
256
|
+
.map(key => [key, (duration: number, options?: ItemBase) => (o: O) => o.transition[key as TransitionName](duration, options)])
|
|
236
257
|
return Object.fromEntries(entries) as BuildTransitionActions
|
|
237
258
|
}
|
|
238
259
|
|
package/s/timeline/sugar/o.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {Id, TimelineFile} from "../parts/basics.js"
|
|
|
6
6
|
import {FilterAction, FilterActions} from "../parts/filters.js"
|
|
7
7
|
import {filters, FilterParams, FilterType} from "../parts/filters.js"
|
|
8
8
|
import {Transcription} from "../../features/speech/transcribe/types.js"
|
|
9
|
-
import {Crop, FilterableItem, Item, Kind, VisualAnimatableItem} from "../parts/item.js"
|
|
9
|
+
import {Crop, FilterableItem, Item, ItemBase, Kind, VisualAnimatableItem} from "../parts/item.js"
|
|
10
10
|
import {animationPresets, makeAnimationPresets, visualAnimations} from "../parts/animations/registry.js"
|
|
11
11
|
import {TransitionAction, TransitionActions, transitions, TransitionName} from "../parts/transitions.js"
|
|
12
12
|
import {AnimationPreset, PresetAnimateAction, PresetAnimateActions, PresetAnimation, PresetOptions} from "../parts/animations/types.js"
|
|
@@ -17,6 +17,8 @@ type VisualAnimateActions = {
|
|
|
17
17
|
[TKey in keyof VisualAnimations]-?: AnimateAction<TKey>
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
type ContainerInput = [label: string, ...items: Item.Any[]] | Item.Any[]
|
|
21
|
+
|
|
20
22
|
export class O {
|
|
21
23
|
constructor(public state: {timeline: TimelineFile}) {}
|
|
22
24
|
|
|
@@ -50,7 +52,7 @@ export class O {
|
|
|
50
52
|
const item = {
|
|
51
53
|
id: this.getId(),
|
|
52
54
|
kind: Kind.TextStyle,
|
|
53
|
-
style
|
|
55
|
+
style,
|
|
54
56
|
} as Item.TextStyle
|
|
55
57
|
this.register(item)
|
|
56
58
|
return item
|
|
@@ -62,7 +64,6 @@ export class O {
|
|
|
62
64
|
kind: Kind.Spatial,
|
|
63
65
|
transform: transform ?? this.transform(),
|
|
64
66
|
crop,
|
|
65
|
-
enabled: true
|
|
66
67
|
}
|
|
67
68
|
this.register(item)
|
|
68
69
|
return item
|
|
@@ -73,7 +74,6 @@ export class O {
|
|
|
73
74
|
id: this.getId(),
|
|
74
75
|
kind: Kind.Animation,
|
|
75
76
|
anims,
|
|
76
|
-
enabled: true
|
|
77
77
|
}
|
|
78
78
|
this.register(item)
|
|
79
79
|
return item
|
|
@@ -134,7 +134,6 @@ export class O {
|
|
|
134
134
|
kind: Kind.Filter,
|
|
135
135
|
type,
|
|
136
136
|
params,
|
|
137
|
-
enabled: true
|
|
138
137
|
}
|
|
139
138
|
this.register(item)
|
|
140
139
|
return item
|
|
@@ -229,20 +228,28 @@ export class O {
|
|
|
229
228
|
presets: this.#makePresetAnimateActions(),
|
|
230
229
|
}
|
|
231
230
|
|
|
232
|
-
sequence = (...
|
|
231
|
+
sequence = (...input: ContainerInput): Item.Sequence => {
|
|
232
|
+
const [first, ...rest] = input
|
|
233
|
+
const label = typeof first === "string" ? first : undefined
|
|
234
|
+
const items = (label ? rest : input) as Item.Any[]
|
|
233
235
|
const item = {
|
|
234
236
|
id: this.getId(),
|
|
235
237
|
kind: Kind.Sequence,
|
|
238
|
+
label,
|
|
236
239
|
childrenIds: items.map(item => item.id)
|
|
237
240
|
} as Item.Sequence
|
|
238
241
|
this.register(item)
|
|
239
242
|
return item
|
|
240
243
|
}
|
|
241
244
|
|
|
242
|
-
stack = (...
|
|
245
|
+
stack = (...input: ContainerInput): Item.Stack => {
|
|
246
|
+
const [first, ...rest] = input
|
|
247
|
+
const label = typeof first === "string" ? first : undefined
|
|
248
|
+
const items = (label ? rest : input) as Item.Any[]
|
|
243
249
|
const item = {
|
|
244
250
|
kind: Kind.Stack,
|
|
245
251
|
id: this.getId(),
|
|
252
|
+
label,
|
|
246
253
|
childrenIds: items.map(item => item.id)
|
|
247
254
|
} as Item.Stack
|
|
248
255
|
this.register(item)
|
|
@@ -254,6 +261,8 @@ export class O {
|
|
|
254
261
|
options?: {
|
|
255
262
|
start?: number,
|
|
256
263
|
duration?: number
|
|
264
|
+
label?: string
|
|
265
|
+
enabled?: boolean
|
|
257
266
|
}): Item.Video => {
|
|
258
267
|
|
|
259
268
|
if(!media.hasVideo)
|
|
@@ -262,6 +271,8 @@ export class O {
|
|
|
262
271
|
const item: Item.Video = {
|
|
263
272
|
kind: Kind.Video,
|
|
264
273
|
id: this.getId(),
|
|
274
|
+
label: options?.label,
|
|
275
|
+
enabled: options?.enabled,
|
|
265
276
|
mediaHash: media.datafile.checksum.hash,
|
|
266
277
|
start: options?.start ?? 0,
|
|
267
278
|
duration: options?.duration ?? media.duration
|
|
@@ -274,6 +285,8 @@ export class O {
|
|
|
274
285
|
media: Media,
|
|
275
286
|
options?: {
|
|
276
287
|
duration?: number
|
|
288
|
+
label?: string
|
|
289
|
+
enabled?: boolean
|
|
277
290
|
}): Item.Image => {
|
|
278
291
|
|
|
279
292
|
if(!media.isImage)
|
|
@@ -282,6 +295,8 @@ export class O {
|
|
|
282
295
|
const item: Item.Image = {
|
|
283
296
|
kind: Kind.Image,
|
|
284
297
|
id: this.getId(),
|
|
298
|
+
label: options?.label,
|
|
299
|
+
enabled: options?.enabled,
|
|
285
300
|
mediaHash: media.datafile.checksum.hash,
|
|
286
301
|
duration: options?.duration ?? 2000
|
|
287
302
|
}
|
|
@@ -295,6 +310,8 @@ export class O {
|
|
|
295
310
|
start?: number,
|
|
296
311
|
duration?: number,
|
|
297
312
|
gain?: number
|
|
313
|
+
label?: string
|
|
314
|
+
enabled?: boolean
|
|
298
315
|
}): Item.Audio => {
|
|
299
316
|
|
|
300
317
|
if(!media.hasAudio)
|
|
@@ -303,6 +320,8 @@ export class O {
|
|
|
303
320
|
const item: Item.Audio = {
|
|
304
321
|
kind: Kind.Audio,
|
|
305
322
|
id: this.getId(),
|
|
323
|
+
label: options?.label,
|
|
324
|
+
enabled: options?.enabled,
|
|
306
325
|
mediaHash: media.datafile.checksum.hash,
|
|
307
326
|
start: options?.start ?? 0,
|
|
308
327
|
duration: options?.duration ?? media.duration,
|
|
@@ -315,10 +334,14 @@ export class O {
|
|
|
315
334
|
text = (content: string, options?: {
|
|
316
335
|
duration?: number,
|
|
317
336
|
styles?: TextStyleOptions
|
|
337
|
+
label?: string
|
|
338
|
+
enabled?: boolean
|
|
318
339
|
}): Item.Text => {
|
|
319
340
|
|
|
320
341
|
const item = {
|
|
321
342
|
id: this.getId(),
|
|
343
|
+
label: options?.label,
|
|
344
|
+
enabled: options?.enabled,
|
|
322
345
|
content,
|
|
323
346
|
kind: Kind.Text,
|
|
324
347
|
duration: options?.duration ?? 2000
|
|
@@ -341,6 +364,8 @@ export class O {
|
|
|
341
364
|
const item: Item.Caption = {
|
|
342
365
|
id: this.getId(),
|
|
343
366
|
kind: Kind.Caption,
|
|
367
|
+
label: options?.label,
|
|
368
|
+
enabled: options?.enabled,
|
|
344
369
|
transcript,
|
|
345
370
|
itemId: options?.itemId,
|
|
346
371
|
start,
|
|
@@ -386,10 +411,12 @@ export class O {
|
|
|
386
411
|
{presets: this.#makeCaptionPresetActions()}
|
|
387
412
|
) as CaptionActions
|
|
388
413
|
|
|
389
|
-
gap = (duration: number): Item.Gap => {
|
|
414
|
+
gap = (duration: number, options?: ItemBase): Item.Gap => {
|
|
390
415
|
const item = {
|
|
391
416
|
id: this.getId(),
|
|
392
417
|
kind: Kind.Gap,
|
|
418
|
+
label: options?.label,
|
|
419
|
+
enabled: options?.enabled,
|
|
393
420
|
duration
|
|
394
421
|
} as Item.Gap
|
|
395
422
|
this.register(item)
|
|
@@ -397,10 +424,12 @@ export class O {
|
|
|
397
424
|
}
|
|
398
425
|
|
|
399
426
|
#makeTransition = (key: TransitionName): TransitionAction => {
|
|
400
|
-
return (duration: number): Item.Transition => {
|
|
427
|
+
return (duration: number, options?: ItemBase): Item.Transition => {
|
|
401
428
|
const item: Item.Transition = {
|
|
402
429
|
id: this.getId(),
|
|
403
430
|
kind: Kind.Transition,
|
|
431
|
+
label: options?.label,
|
|
432
|
+
enabled: options?.enabled,
|
|
404
433
|
name: transitions[key].name,
|
|
405
434
|
duration,
|
|
406
435
|
}
|