@revideo/2d 0.5.10 → 0.5.11-alpha.1100
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/editor/editor/NodeInspectorConfig.d.ts +3 -0
- package/editor/editor/NodeInspectorConfig.d.ts.map +1 -0
- package/editor/editor/PreviewOverlayConfig.d.ts +3 -0
- package/editor/editor/PreviewOverlayConfig.d.ts.map +1 -0
- package/editor/editor/Provider.d.ts +17 -0
- package/editor/editor/Provider.d.ts.map +1 -0
- package/editor/editor/SceneGraphTabConfig.d.ts +3 -0
- package/editor/editor/SceneGraphTabConfig.d.ts.map +1 -0
- package/editor/editor/icons/CircleIcon.d.ts +2 -0
- package/editor/editor/icons/CircleIcon.d.ts.map +1 -0
- package/editor/editor/icons/CodeBlockIcon.d.ts +2 -0
- package/editor/editor/icons/CodeBlockIcon.d.ts.map +1 -0
- package/editor/editor/icons/CurveIcon.d.ts +2 -0
- package/editor/editor/icons/CurveIcon.d.ts.map +1 -0
- package/editor/editor/icons/GridIcon.d.ts +2 -0
- package/editor/editor/icons/GridIcon.d.ts.map +1 -0
- package/editor/editor/icons/IconMap.d.ts +3 -0
- package/editor/editor/icons/IconMap.d.ts.map +1 -0
- package/editor/editor/icons/ImgIcon.d.ts +2 -0
- package/editor/editor/icons/ImgIcon.d.ts.map +1 -0
- package/editor/editor/icons/LayoutIcon.d.ts +2 -0
- package/editor/editor/icons/LayoutIcon.d.ts.map +1 -0
- package/editor/editor/icons/LineIcon.d.ts +2 -0
- package/editor/editor/icons/LineIcon.d.ts.map +1 -0
- package/editor/editor/icons/NodeIcon.d.ts +2 -0
- package/editor/editor/icons/NodeIcon.d.ts.map +1 -0
- package/editor/editor/icons/RayIcon.d.ts +2 -0
- package/editor/editor/icons/RayIcon.d.ts.map +1 -0
- package/editor/editor/icons/RectIcon.d.ts +2 -0
- package/editor/editor/icons/RectIcon.d.ts.map +1 -0
- package/editor/editor/icons/ShapeIcon.d.ts +2 -0
- package/editor/editor/icons/ShapeIcon.d.ts.map +1 -0
- package/editor/editor/icons/TxtIcon.d.ts +2 -0
- package/editor/editor/icons/TxtIcon.d.ts.map +1 -0
- package/editor/editor/icons/VideoIcon.d.ts +2 -0
- package/editor/editor/icons/VideoIcon.d.ts.map +1 -0
- package/editor/editor/icons/View2DIcon.d.ts +2 -0
- package/editor/editor/icons/View2DIcon.d.ts.map +1 -0
- package/editor/editor/index.d.ts +4 -0
- package/editor/editor/index.d.ts.map +1 -0
- package/editor/editor/tree/DetachedRoot.d.ts +2 -0
- package/editor/editor/tree/DetachedRoot.d.ts.map +1 -0
- package/editor/editor/tree/NodeElement.d.ts +8 -0
- package/editor/editor/tree/NodeElement.d.ts.map +1 -0
- package/editor/editor/tree/TreeElement.d.ts +15 -0
- package/editor/editor/tree/TreeElement.d.ts.map +1 -0
- package/editor/editor/tree/TreeRoot.d.ts +3 -0
- package/editor/editor/tree/TreeRoot.d.ts.map +1 -0
- package/editor/editor/tree/ViewRoot.d.ts +2 -0
- package/editor/editor/tree/ViewRoot.d.ts.map +1 -0
- package/editor/editor/tree/index.d.ts +4 -0
- package/editor/editor/tree/index.d.ts.map +1 -0
- package/editor/editor/tsconfig.build.tsbuildinfo +1 -1
- package/lib/code/CodeSignal.d.ts +1 -1
- package/lib/code/CodeSignal.d.ts.map +1 -1
- package/lib/code/index.d.ts +1 -1
- package/lib/code/index.d.ts.map +1 -1
- package/lib/code/index.js +2 -2
- package/lib/components/Audio.js +3 -3
- package/lib/components/Img.d.ts +18 -3
- package/lib/components/Img.d.ts.map +1 -1
- package/lib/components/Img.js +37 -21
- package/lib/components/Layout.js +4 -2
- package/lib/components/Line.d.ts.map +1 -1
- package/lib/components/Line.js +34 -2
- package/lib/components/Media.d.ts +3 -3
- package/lib/components/Media.d.ts.map +1 -1
- package/lib/components/Media.js +32 -6
- package/lib/components/Node.d.ts.map +1 -1
- package/lib/components/Node.js +2 -2
- package/lib/components/Rive.d.ts +3 -3
- package/lib/components/Rive.d.ts.map +1 -1
- package/lib/components/Rive.js +8 -5
- package/lib/components/Spline.d.ts.map +1 -1
- package/lib/components/Spline.js +28 -2
- package/lib/components/TxtLeaf.d.ts +0 -1
- package/lib/components/TxtLeaf.d.ts.map +1 -1
- package/lib/components/TxtLeaf.js +5 -14
- package/lib/components/Video.d.ts.map +1 -1
- package/lib/components/Video.js +4 -4
- package/lib/components/View2D.d.ts.map +1 -1
- package/lib/components/View2D.js +1 -1
- package/lib/components/index.d.ts +2 -2
- package/lib/components/index.d.ts.map +1 -1
- package/lib/components/index.js +3 -3
- package/lib/curves/Polynomial2D.d.ts.map +1 -1
- package/lib/curves/index.d.ts +5 -5
- package/lib/curves/index.d.ts.map +1 -1
- package/lib/curves/index.js +6 -6
- package/lib/partials/Pattern.d.ts.map +1 -1
- package/lib/partials/Pattern.js +1 -1
- package/lib/scenes/Scene2D.d.ts.map +1 -1
- package/lib/scenes/Scene2D.js +3 -4
- package/lib/scenes/index.d.ts +1 -1
- package/lib/scenes/index.d.ts.map +1 -1
- package/lib/scenes/index.js +2 -2
- package/lib/scenes/makeScene2D.d.ts +1 -1
- package/lib/scenes/makeScene2D.d.ts.map +1 -1
- package/lib/scenes/makeScene2D.js +3 -4
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +9 -8
- package/src/lib/code/index.ts +1 -1
- package/src/lib/components/Audio.ts +2 -2
- package/src/lib/components/Img.ts +48 -20
- package/src/lib/components/Layout.ts +3 -3
- package/src/lib/components/Line.ts +33 -1
- package/src/lib/components/Media.ts +30 -6
- package/src/lib/components/Rive.ts +7 -11
- package/src/lib/components/Spline.ts +27 -1
- package/src/lib/components/TxtLeaf.ts +4 -13
- package/src/lib/components/Video.ts +2 -3
- package/src/lib/components/View2D.ts +1 -0
- package/src/lib/components/__tests__/mockScene2D.ts +1 -5
- package/src/lib/components/index.ts +2 -2
- package/src/lib/curves/index.ts +5 -5
- package/src/lib/globals.d.ts +0 -1
- package/src/lib/partials/Pattern.ts +0 -1
- package/src/lib/scenes/Scene2D.ts +2 -3
- package/src/lib/scenes/index.ts +1 -1
- package/src/lib/scenes/makeScene2D.ts +3 -6
- package/src/lib/tsconfig.json +3 -7
- package/lib/components/Asset.d.ts +0 -24
- package/lib/components/Asset.d.ts.map +0 -1
- package/lib/components/Asset.js +0 -40
- package/src/lib/components/Asset.ts +0 -51
- package/src/lib/components/__logs__/image-without-source.md +0 -17
- package/src/lib/components/__logs__/line-without-points.md +0 -30
- package/src/lib/components/__logs__/reactive-playback-rate.md +0 -21
- package/src/lib/components/__logs__/spline-with-insufficient-knots.md +0 -24
package/src/lib/code/index.ts
CHANGED
|
@@ -8,6 +8,6 @@ export * from './CodeSelection';
|
|
|
8
8
|
export * from './CodeSignal';
|
|
9
9
|
export * from './CodeTokenizer';
|
|
10
10
|
export * from './DefaultHighlightStyle';
|
|
11
|
-
export * from './LezerHighlighter';
|
|
12
11
|
export * from './diff';
|
|
13
12
|
export * from './extractRange';
|
|
13
|
+
export * from './LezerHighlighter';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {DependencyContext, PlaybackState
|
|
1
|
+
import {DependencyContext, PlaybackState} from '@revideo/core';
|
|
2
2
|
import {computed, nodeName} from '../decorators';
|
|
3
3
|
import {Media, MediaProps} from './Media';
|
|
4
4
|
|
|
@@ -24,7 +24,7 @@ export class Audio extends Media {
|
|
|
24
24
|
|
|
25
25
|
@computed()
|
|
26
26
|
protected audio(): HTMLAudioElement {
|
|
27
|
-
const src =
|
|
27
|
+
const src = this.src();
|
|
28
28
|
const key = `${this.key}/${src}`;
|
|
29
29
|
let audio = Audio.pool[key];
|
|
30
30
|
if (!audio) {
|
|
@@ -9,14 +9,31 @@ import {
|
|
|
9
9
|
SimpleSignal,
|
|
10
10
|
Vector2,
|
|
11
11
|
useLogger,
|
|
12
|
-
viaProxy,
|
|
13
12
|
} from '@revideo/core';
|
|
14
13
|
import {computed, initial, nodeName, signal} from '../decorators';
|
|
15
14
|
import {DesiredLength} from '../partials';
|
|
16
15
|
import {drawImage} from '../utils';
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
import {Rect, RectProps} from './Rect';
|
|
17
|
+
|
|
18
|
+
const imageWithoutSource = `
|
|
19
|
+
The image won't be visible unless you specify a source:
|
|
20
|
+
|
|
21
|
+
\`\`\`tsx
|
|
22
|
+
import myImage from './example.png';
|
|
23
|
+
// ...
|
|
24
|
+
<Img src={myImage} />;
|
|
25
|
+
\`\`\`
|
|
26
|
+
|
|
27
|
+
If you did this intentionally, and don't want to see this warning, set the \`src\`
|
|
28
|
+
property to \`null\`:
|
|
29
|
+
|
|
30
|
+
\`\`\`tsx
|
|
31
|
+
<Img src={null} />
|
|
32
|
+
\`\`\`
|
|
33
|
+
|
|
34
|
+
[Learn more](https://motioncanvas.io/docs/media#images) about working with
|
|
35
|
+
images.
|
|
36
|
+
`;
|
|
20
37
|
|
|
21
38
|
export interface ImgProps extends RectProps {
|
|
22
39
|
/**
|
|
@@ -67,7 +84,7 @@ export interface ImgProps extends RectProps {
|
|
|
67
84
|
* ```
|
|
68
85
|
*/
|
|
69
86
|
@nodeName('Img')
|
|
70
|
-
export class Img extends
|
|
87
|
+
export class Img extends Rect {
|
|
71
88
|
private static pool: Record<string, HTMLImageElement> = {};
|
|
72
89
|
|
|
73
90
|
static {
|
|
@@ -82,6 +99,24 @@ export class Img extends Asset {
|
|
|
82
99
|
}
|
|
83
100
|
}
|
|
84
101
|
|
|
102
|
+
/**
|
|
103
|
+
* The source of this image.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* Using a local image:
|
|
107
|
+
* ```tsx
|
|
108
|
+
* import image from './example.png';
|
|
109
|
+
* // ...
|
|
110
|
+
* view.add(<Img src={image} />)
|
|
111
|
+
* ```
|
|
112
|
+
* Loading an image from the internet:
|
|
113
|
+
* ```tsx
|
|
114
|
+
* view.add(<Img src="https://example.com/image.png" />)
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
@signal()
|
|
118
|
+
public declare readonly src: SimpleSignal<string, this>;
|
|
119
|
+
|
|
85
120
|
/**
|
|
86
121
|
* The alpha value of this image.
|
|
87
122
|
*
|
|
@@ -132,25 +167,19 @@ export class Img extends Asset {
|
|
|
132
167
|
|
|
133
168
|
@computed()
|
|
134
169
|
protected image(): HTMLImageElement {
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const url = new URL(key, window.location.origin);
|
|
141
|
-
if (url.origin === window.location.origin) {
|
|
142
|
-
const hash = this.view().assetHash();
|
|
143
|
-
url.searchParams.set('asset-hash', hash);
|
|
144
|
-
}
|
|
145
|
-
src = url.toString();
|
|
170
|
+
const src = this.src();
|
|
171
|
+
const url = new URL(src, window.location.origin);
|
|
172
|
+
if (url.origin === window.location.origin) {
|
|
173
|
+
const hash = this.view().assetHash();
|
|
174
|
+
url.searchParams.set('asset-hash', hash);
|
|
146
175
|
}
|
|
147
176
|
|
|
148
|
-
let image = Img.pool[
|
|
177
|
+
let image = Img.pool[src];
|
|
149
178
|
if (!image) {
|
|
150
179
|
image = document.createElement('img');
|
|
151
180
|
image.crossOrigin = 'anonymous';
|
|
152
181
|
image.src = src;
|
|
153
|
-
Img.pool[
|
|
182
|
+
Img.pool[src] = image;
|
|
154
183
|
}
|
|
155
184
|
|
|
156
185
|
if (!image.complete) {
|
|
@@ -158,13 +187,12 @@ export class Img extends Asset {
|
|
|
158
187
|
new Promise((resolve, reject) => {
|
|
159
188
|
image.addEventListener('load', resolve);
|
|
160
189
|
image.addEventListener('error', () =>
|
|
190
|
+
// TODO: example for error handling inside DependencyContext (this shouldn't be UI specific)
|
|
161
191
|
reject(
|
|
162
192
|
new DetailedError({
|
|
163
193
|
message: `Failed to load an image`,
|
|
164
194
|
remarks: `\
|
|
165
195
|
The <code>src</code> property was set to:
|
|
166
|
-
<pre><code>${rawSrc}</code></pre>
|
|
167
|
-
...which resolved to the following url:
|
|
168
196
|
<pre><code>${src}</code></pre>
|
|
169
197
|
Make sure that source is correct and that the image exists.<br/>
|
|
170
198
|
<a target='_blank' href='https://motioncanvas.io/docs/media#images'>Learn more</a>
|
|
@@ -962,9 +962,9 @@ export class Layout extends Node {
|
|
|
962
962
|
|
|
963
963
|
@computed()
|
|
964
964
|
protected applyFont() {
|
|
965
|
-
const loadingFonts =
|
|
966
|
-
font => font.status === 'loading'
|
|
967
|
-
|
|
965
|
+
const loadingFonts = document.fonts
|
|
966
|
+
? Array.from(document.fonts).filter(font => font.status === 'loading')
|
|
967
|
+
: [];
|
|
968
968
|
if (loadingFonts.length > 0) {
|
|
969
969
|
DependencyContext.collectPromise(
|
|
970
970
|
(async () => {
|
|
@@ -20,10 +20,42 @@ import {
|
|
|
20
20
|
} from '../curves/createCurveProfileLerp';
|
|
21
21
|
import {computed, initial, nodeName, signal} from '../decorators';
|
|
22
22
|
import {arc, drawLine, drawPivot, lineTo, moveTo} from '../utils';
|
|
23
|
-
import lineWithoutPoints from './__logs__/line-without-points.md';
|
|
24
23
|
import {Curve, CurveProps} from './Curve';
|
|
25
24
|
import {Layout} from './Layout';
|
|
26
25
|
|
|
26
|
+
const lineWithoutPoints = `
|
|
27
|
+
The line won't be visible unless you specify at least two points:
|
|
28
|
+
|
|
29
|
+
\`\`\`tsx
|
|
30
|
+
<Line
|
|
31
|
+
stroke="#fff"
|
|
32
|
+
lineWidth={8}
|
|
33
|
+
points={[
|
|
34
|
+
[100, 0],
|
|
35
|
+
[0, 0],
|
|
36
|
+
[0, 100],
|
|
37
|
+
]}
|
|
38
|
+
/>
|
|
39
|
+
\`\`\`
|
|
40
|
+
|
|
41
|
+
Alternatively, you can define the points using the children:
|
|
42
|
+
|
|
43
|
+
\`\`\`tsx
|
|
44
|
+
<Line stroke="#fff" lineWidth={8}>
|
|
45
|
+
<Node x={100} />
|
|
46
|
+
<Node />
|
|
47
|
+
<Node y={100} />
|
|
48
|
+
</Line>
|
|
49
|
+
\`\`\`
|
|
50
|
+
|
|
51
|
+
If you did this intentionally, and want to disable this message, set the
|
|
52
|
+
\`points\` property to \`null\`:
|
|
53
|
+
|
|
54
|
+
\`\`\`tsx
|
|
55
|
+
<Line stroke="#fff" lineWidth={8} points={null} />
|
|
56
|
+
\`\`\`
|
|
57
|
+
`;
|
|
58
|
+
|
|
27
59
|
export interface LineProps extends CurveProps {
|
|
28
60
|
/**
|
|
29
61
|
* {@inheritDoc Line.radius}
|
|
@@ -7,12 +7,9 @@ import {
|
|
|
7
7
|
isReactive,
|
|
8
8
|
useLogger,
|
|
9
9
|
useThread,
|
|
10
|
-
viaProxy,
|
|
11
10
|
} from '@revideo/core';
|
|
12
11
|
import {computed, initial, nodeName, signal} from '../decorators';
|
|
13
|
-
import {
|
|
14
|
-
import {RectProps} from './Rect';
|
|
15
|
-
import reactivePlaybackRate from './__logs__/reactive-playback-rate.md';
|
|
12
|
+
import {Rect, RectProps} from './Rect';
|
|
16
13
|
|
|
17
14
|
export interface MediaProps extends RectProps {
|
|
18
15
|
src?: SignalValue<string>;
|
|
@@ -25,8 +22,35 @@ export interface MediaProps extends RectProps {
|
|
|
25
22
|
allowVolumeAmplificationInPreview?: SignalValue<boolean>;
|
|
26
23
|
}
|
|
27
24
|
|
|
25
|
+
const reactivePlaybackRate = `
|
|
26
|
+
The \`playbackRate\` of a \`Video\` cannot be reactive.
|
|
27
|
+
|
|
28
|
+
Make sure to use a concrete value and not a function:
|
|
29
|
+
|
|
30
|
+
\`\`\`ts wrong
|
|
31
|
+
video.playbackRate(() => 7);
|
|
32
|
+
\`\`\`
|
|
33
|
+
|
|
34
|
+
\`\`\`ts correct
|
|
35
|
+
video.playbackRate(7);
|
|
36
|
+
\`\`\`
|
|
37
|
+
|
|
38
|
+
If you're using a signal, extract its value before passing it to the property:
|
|
39
|
+
|
|
40
|
+
\`\`\`ts wrong
|
|
41
|
+
video.playbackRate(mySignal);
|
|
42
|
+
\`\`\`
|
|
43
|
+
|
|
44
|
+
\`\`\`ts correct
|
|
45
|
+
video.playbackRate(mySignal());
|
|
46
|
+
\`\`\`
|
|
47
|
+
`;
|
|
48
|
+
|
|
28
49
|
@nodeName('Media')
|
|
29
|
-
export abstract class Media extends
|
|
50
|
+
export abstract class Media extends Rect {
|
|
51
|
+
@signal()
|
|
52
|
+
public declare readonly src: SimpleSignal<string, this>;
|
|
53
|
+
|
|
30
54
|
@initial(false)
|
|
31
55
|
@signal()
|
|
32
56
|
public declare readonly loop: SimpleSignal<boolean, this>;
|
|
@@ -161,7 +185,7 @@ export abstract class Media extends Asset {
|
|
|
161
185
|
|
|
162
186
|
@computed()
|
|
163
187
|
protected amplify(node: HTMLMediaElement, volume: number) {
|
|
164
|
-
const key = `${
|
|
188
|
+
const key = `${this.src()}/${this.key}`;
|
|
165
189
|
|
|
166
190
|
if (Media.amplificationPool[key]) {
|
|
167
191
|
Media.amplificationPool[key].gainNode.gain.value = volume;
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BBox,
|
|
3
|
-
SignalValue,
|
|
4
|
-
SimpleSignal,
|
|
5
|
-
useThread,
|
|
6
|
-
viaProxy,
|
|
7
|
-
} from '@revideo/core';
|
|
1
|
+
import {BBox, SignalValue, SimpleSignal, useThread} from '@revideo/core';
|
|
8
2
|
import RiveInitializer, {
|
|
9
3
|
Artboard,
|
|
10
4
|
File,
|
|
@@ -13,8 +7,7 @@ import RiveInitializer, {
|
|
|
13
7
|
RiveCanvas,
|
|
14
8
|
} from '@rive-app/canvas-advanced';
|
|
15
9
|
import {computed, initial, nodeName, signal} from '../decorators';
|
|
16
|
-
import {
|
|
17
|
-
import {RectProps} from './Rect';
|
|
10
|
+
import {Rect, RectProps} from './Rect';
|
|
18
11
|
|
|
19
12
|
export interface RiveProps extends RectProps {
|
|
20
13
|
src?: SignalValue<string>;
|
|
@@ -31,7 +24,10 @@ interface RiveInstance {
|
|
|
31
24
|
}
|
|
32
25
|
|
|
33
26
|
@nodeName('Rive')
|
|
34
|
-
export class Rive extends
|
|
27
|
+
export class Rive extends Rect {
|
|
28
|
+
@signal()
|
|
29
|
+
public declare readonly src: SimpleSignal<string, this>;
|
|
30
|
+
|
|
35
31
|
@initial(0)
|
|
36
32
|
@signal()
|
|
37
33
|
public declare readonly artboardId: SimpleSignal<number | string, this>;
|
|
@@ -57,7 +53,7 @@ export class Rive extends Asset {
|
|
|
57
53
|
|
|
58
54
|
@computed()
|
|
59
55
|
private async rive(): Promise<RiveInstance> {
|
|
60
|
-
const src =
|
|
56
|
+
const src = this.src();
|
|
61
57
|
const rive = await RiveInitializer({
|
|
62
58
|
locateFile: () => {
|
|
63
59
|
return '/@rive-wasm';
|
|
@@ -29,7 +29,33 @@ import {
|
|
|
29
29
|
import {Curve, CurveProps} from './Curve';
|
|
30
30
|
import {Knot} from './Knot';
|
|
31
31
|
import {Node} from './Node';
|
|
32
|
-
|
|
32
|
+
|
|
33
|
+
const splineWithInsufficientKnots = `
|
|
34
|
+
The spline won't be visible unless you specify at least two knots:
|
|
35
|
+
|
|
36
|
+
\`\`\`tsx
|
|
37
|
+
<Spline
|
|
38
|
+
stroke="#fff"
|
|
39
|
+
lineWidth={8}
|
|
40
|
+
points={[
|
|
41
|
+
[100, 0],
|
|
42
|
+
[0, 0],
|
|
43
|
+
[0, 100],
|
|
44
|
+
]}
|
|
45
|
+
/>
|
|
46
|
+
\`\`\`
|
|
47
|
+
|
|
48
|
+
For more control over the knot handles, you can alternatively provide the knots
|
|
49
|
+
as children to the spline using the \`Knot\` component:
|
|
50
|
+
|
|
51
|
+
\`\`\`tsx
|
|
52
|
+
<Spline stroke="#fff" lineWidth={8}>
|
|
53
|
+
<Knot x={100} endHandle={[-50, 0]} />
|
|
54
|
+
<Knot />
|
|
55
|
+
<Knot y={100} startHandle={[-100, 50]} />
|
|
56
|
+
</Spline>
|
|
57
|
+
\`\`\`
|
|
58
|
+
`;
|
|
33
59
|
|
|
34
60
|
export interface SplineProps extends CurveProps {
|
|
35
61
|
/**
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
} from '../decorators';
|
|
16
16
|
import {Shape, ShapeProps} from './Shape';
|
|
17
17
|
import {Txt} from './Txt';
|
|
18
|
-
import {View2D} from './View2D';
|
|
19
18
|
|
|
20
19
|
export interface TxtLeafProps extends ShapeProps {
|
|
21
20
|
children?: string;
|
|
@@ -24,13 +23,6 @@ export interface TxtLeafProps extends ShapeProps {
|
|
|
24
23
|
|
|
25
24
|
@nodeName('TxtLeaf')
|
|
26
25
|
export class TxtLeaf extends Shape {
|
|
27
|
-
@lazy(() => {
|
|
28
|
-
const formatter = document.createElement('span');
|
|
29
|
-
View2D.shadowRoot.append(formatter);
|
|
30
|
-
return formatter;
|
|
31
|
-
})
|
|
32
|
-
protected static formatter: HTMLDivElement;
|
|
33
|
-
|
|
34
26
|
@lazy(() => {
|
|
35
27
|
try {
|
|
36
28
|
return new (Intl as any).Segmenter(undefined, {
|
|
@@ -66,9 +58,11 @@ export class TxtLeaf extends Shape {
|
|
|
66
58
|
await document.fonts?.ready;
|
|
67
59
|
this.applyText(context);
|
|
68
60
|
context.font = this.styles.font;
|
|
61
|
+
context.textBaseline = 'bottom';
|
|
69
62
|
if ('letterSpacing' in context) {
|
|
70
63
|
context.letterSpacing = `${this.letterSpacing()}px`;
|
|
71
64
|
}
|
|
65
|
+
const fontOffset = context.measureText('').fontBoundingBoxAscent;
|
|
72
66
|
|
|
73
67
|
const parentRect = this.element.getBoundingClientRect();
|
|
74
68
|
const {width, height} = this.size();
|
|
@@ -84,7 +78,7 @@ export class TxtLeaf extends Shape {
|
|
|
84
78
|
const rangeRect = range.getBoundingClientRect();
|
|
85
79
|
|
|
86
80
|
const x = width / -2 + rangeRect.left - parentRect.left;
|
|
87
|
-
const y = height / -2 + rangeRect.top - parentRect.top;
|
|
81
|
+
const y = height / -2 + rangeRect.top - parentRect.top + fontOffset;
|
|
88
82
|
|
|
89
83
|
if (lineRect.y === y) {
|
|
90
84
|
lineRect.width += rangeRect.width;
|
|
@@ -107,9 +101,7 @@ export class TxtLeaf extends Shape {
|
|
|
107
101
|
text: string,
|
|
108
102
|
box: BBox,
|
|
109
103
|
) {
|
|
110
|
-
const y = box.y
|
|
111
|
-
context.save();
|
|
112
|
-
context.textBaseline = 'middle';
|
|
104
|
+
const y = box.y;
|
|
113
105
|
text = text.replace(/\s+/g, ' ');
|
|
114
106
|
if (this.lineWidth() <= 0) {
|
|
115
107
|
context.fillText(text, box.x, y);
|
|
@@ -120,7 +112,6 @@ export class TxtLeaf extends Shape {
|
|
|
120
112
|
context.fillText(text, box.x, y);
|
|
121
113
|
context.strokeText(text, box.x, y);
|
|
122
114
|
}
|
|
123
|
-
context.restore();
|
|
124
115
|
}
|
|
125
116
|
|
|
126
117
|
protected override getCacheBBox(): BBox {
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
SerializedVector2,
|
|
6
6
|
SignalValue,
|
|
7
7
|
SimpleSignal,
|
|
8
|
-
viaProxy,
|
|
9
8
|
} from '@revideo/core';
|
|
10
9
|
import Hls from 'hls.js';
|
|
11
10
|
import {computed, initial, nodeName, signal} from '../decorators';
|
|
@@ -112,7 +111,7 @@ export class Video extends Media {
|
|
|
112
111
|
|
|
113
112
|
@computed()
|
|
114
113
|
private video(): HTMLVideoElement {
|
|
115
|
-
const src =
|
|
114
|
+
const src = this.src();
|
|
116
115
|
const key = `${this.key}/${src}`;
|
|
117
116
|
let video = Video.pool[key];
|
|
118
117
|
if (!video) {
|
|
@@ -336,7 +335,7 @@ export class Video extends Media {
|
|
|
336
335
|
private detectFileType() {
|
|
337
336
|
return DependencyContext.collectPromise(
|
|
338
337
|
(async () => {
|
|
339
|
-
const src = this.
|
|
338
|
+
const src = this.src();
|
|
340
339
|
const extension = src.split('?')[0].split('.').pop()?.toLowerCase();
|
|
341
340
|
|
|
342
341
|
if (
|
|
@@ -11,6 +11,7 @@ export interface View2DProps extends RectProps {
|
|
|
11
11
|
|
|
12
12
|
@nodeName('View2D')
|
|
13
13
|
export class View2D extends Rect {
|
|
14
|
+
// TODO: scope this to individual player
|
|
14
15
|
@lazy(() => {
|
|
15
16
|
const frameID = 'revideo-2d-frame';
|
|
16
17
|
let frame = document.querySelector<HTMLDivElement>(`#${frameID}`);
|
|
@@ -3,14 +3,12 @@ import {
|
|
|
3
3
|
PlaybackManager,
|
|
4
4
|
PlaybackStatus,
|
|
5
5
|
ThreadGeneratorFactory,
|
|
6
|
-
ValueDispatcher,
|
|
7
6
|
Vector2,
|
|
8
7
|
endPlayback,
|
|
9
8
|
endScene,
|
|
10
9
|
startPlayback,
|
|
11
10
|
startScene,
|
|
12
11
|
} from '@revideo/core';
|
|
13
|
-
import {ReadOnlyTimeEvents} from '@revideo/core/lib/scenes/timeEvents';
|
|
14
12
|
import {afterAll, beforeAll, beforeEach} from 'vitest';
|
|
15
13
|
import {Scene2D, makeScene2D} from '../../scenes';
|
|
16
14
|
import {View2D} from '../View2D';
|
|
@@ -26,16 +24,14 @@ export function mockScene2D() {
|
|
|
26
24
|
const playback = new PlaybackManager();
|
|
27
25
|
const status = new PlaybackStatus(playback);
|
|
28
26
|
const description = {
|
|
29
|
-
...makeScene2D(function* () {
|
|
27
|
+
...makeScene2D('scene 1', function* () {
|
|
30
28
|
// do nothing
|
|
31
29
|
}),
|
|
32
30
|
name: 'test',
|
|
33
31
|
size: new Vector2(1920, 1080),
|
|
34
32
|
resolutionScale: 1,
|
|
35
|
-
timeEventsClass: ReadOnlyTimeEvents,
|
|
36
33
|
playback: status,
|
|
37
34
|
} as unknown as FullSceneDescription<ThreadGeneratorFactory<View2D>>;
|
|
38
|
-
description.onReplaced = new ValueDispatcher(description);
|
|
39
35
|
const scene = new Scene2D(description);
|
|
40
36
|
|
|
41
37
|
beforeAll(() => {
|
|
@@ -19,10 +19,10 @@ export * from './QuadBezier';
|
|
|
19
19
|
export * from './Ray';
|
|
20
20
|
export * from './Rect';
|
|
21
21
|
export * from './Rive';
|
|
22
|
-
export * from './SVG';
|
|
23
22
|
export * from './Shape';
|
|
24
23
|
export * from './Spline';
|
|
24
|
+
export * from './SVG';
|
|
25
25
|
export * from './Txt';
|
|
26
|
+
export * from './types';
|
|
26
27
|
export * from './Video';
|
|
27
28
|
export * from './View2D';
|
|
28
|
-
export * from './types';
|
package/src/lib/curves/index.ts
CHANGED
|
@@ -3,14 +3,14 @@ export * from './CubicBezierSegment';
|
|
|
3
3
|
export * from './CurveDrawingInfo';
|
|
4
4
|
export * from './CurvePoint';
|
|
5
5
|
export * from './CurveProfile';
|
|
6
|
+
export * from './getBezierSplineProfile';
|
|
7
|
+
export * from './getCircleProfile';
|
|
8
|
+
export * from './getPointAtDistance';
|
|
9
|
+
export * from './getPolylineProfile';
|
|
10
|
+
export * from './getRectProfile';
|
|
6
11
|
export * from './KnotInfo';
|
|
7
12
|
export * from './LineSegment';
|
|
8
13
|
export * from './Polynomial';
|
|
9
14
|
export * from './Polynomial2D';
|
|
10
15
|
export * from './QuadBezierSegment';
|
|
11
16
|
export * from './Segment';
|
|
12
|
-
export * from './getBezierSplineProfile';
|
|
13
|
-
export * from './getCircleProfile';
|
|
14
|
-
export * from './getPointAtDistance';
|
|
15
|
-
export * from './getPolylineProfile';
|
|
16
|
-
export * from './getRectProfile';
|
package/src/lib/globals.d.ts
CHANGED
|
@@ -173,7 +173,7 @@ export class Scene2D extends GeneratorScene<View2D> implements Inspectable {
|
|
|
173
173
|
...playingVideos.map(vid => ({
|
|
174
174
|
key: vid.key,
|
|
175
175
|
type: 'video' as const,
|
|
176
|
-
src: vid.
|
|
176
|
+
src: vid.src(),
|
|
177
177
|
decoder: vid.decoder(),
|
|
178
178
|
playbackRate:
|
|
179
179
|
typeof vid.playbackRate === 'function'
|
|
@@ -189,7 +189,7 @@ export class Scene2D extends GeneratorScene<View2D> implements Inspectable {
|
|
|
189
189
|
...playingAudios.map(audio => ({
|
|
190
190
|
key: audio.key,
|
|
191
191
|
type: 'audio' as const,
|
|
192
|
-
src: audio.
|
|
192
|
+
src: audio.src(),
|
|
193
193
|
playbackRate:
|
|
194
194
|
typeof audio.playbackRate === 'function'
|
|
195
195
|
? audio.playbackRate()
|
|
@@ -220,7 +220,6 @@ export class Scene2D extends GeneratorScene<View2D> implements Inspectable {
|
|
|
220
220
|
|
|
221
221
|
for (const media of mediaNodes) {
|
|
222
222
|
media.setVolume(media.getVolume() * volumeScale);
|
|
223
|
-
console.log(media.key);
|
|
224
223
|
}
|
|
225
224
|
}
|
|
226
225
|
|
package/src/lib/scenes/index.ts
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createSceneMetadata,
|
|
3
|
-
DescriptionOf,
|
|
4
|
-
ThreadGeneratorFactory,
|
|
5
|
-
} from '@revideo/core';
|
|
1
|
+
import {DescriptionOf, ThreadGeneratorFactory} from '@revideo/core';
|
|
6
2
|
import type {View2D} from '../components';
|
|
7
3
|
import {Scene2D} from './Scene2D';
|
|
8
4
|
|
|
9
5
|
export function makeScene2D(
|
|
6
|
+
name: string,
|
|
10
7
|
runner: ThreadGeneratorFactory<View2D>,
|
|
11
8
|
): DescriptionOf<Scene2D> {
|
|
12
9
|
return {
|
|
13
10
|
klass: Scene2D,
|
|
11
|
+
name,
|
|
14
12
|
config: runner,
|
|
15
13
|
stack: new Error().stack,
|
|
16
|
-
meta: createSceneMetadata(),
|
|
17
14
|
plugins: ['@revideo/2d/editor'],
|
|
18
15
|
};
|
|
19
16
|
}
|
package/src/lib/tsconfig.json
CHANGED
|
@@ -3,12 +3,8 @@
|
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"types": ["node"],
|
|
5
5
|
"jsx": "react-jsx",
|
|
6
|
-
"jsxImportSource": "@revideo/2d/src/lib"
|
|
7
|
-
"plugins": [
|
|
8
|
-
{
|
|
9
|
-
"transform": "@revideo/internal/transformers/markdown-literals.js"
|
|
10
|
-
}
|
|
11
|
-
]
|
|
6
|
+
"jsxImportSource": "@revideo/2d/src/lib"
|
|
12
7
|
},
|
|
13
|
-
"include": ["**/*"]
|
|
8
|
+
"include": ["**/*"],
|
|
9
|
+
"exclude": []
|
|
14
10
|
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { SimpleSignal } from '@revideo/core';
|
|
2
|
-
import { Rect } from './Rect';
|
|
3
|
-
/**
|
|
4
|
-
* A component that has a source. Used as a base class for `Media` and `Img` components.
|
|
5
|
-
*/
|
|
6
|
-
export declare abstract class Asset extends Rect {
|
|
7
|
-
/**
|
|
8
|
-
* The source of this asset.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* Using a local path, with the resource inside the /public folder:
|
|
12
|
-
* ```tsx
|
|
13
|
-
* view.add(<Img src={'/image.png} />)
|
|
14
|
-
* ```
|
|
15
|
-
* Loading a resource from the internet:
|
|
16
|
-
* ```tsx
|
|
17
|
-
* view.add(<Img src="https://example.com/image.png" />)
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
readonly src: SimpleSignal<string, this>;
|
|
21
|
-
assetRoot?: `${string}/`;
|
|
22
|
-
fullSource(): string;
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=Asset.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Asset.d.ts","sourceRoot":"","sources":["../../src/lib/components/Asset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAe,MAAM,eAAe,CAAC;AAEzD,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAC;AAE5B;;GAEG;AACH,8BACsB,KAAM,SAAQ,IAAI;IACtC;;;;;;;;;;;;OAYG;IACH,SACwB,GAAG,EAAE,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAEjD,SAAS,CAAC,EAAE,GAAG,MAAM,GAAG,CAAC;IAEzB,UAAU,IAAI,MAAM;CAuB5B"}
|
package/lib/components/Asset.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
import { useAssetBase } from '@revideo/core';
|
|
8
|
-
import { nodeName, signal } from '../decorators';
|
|
9
|
-
import { Rect } from './Rect';
|
|
10
|
-
/**
|
|
11
|
-
* A component that has a source. Used as a base class for `Media` and `Img` components.
|
|
12
|
-
*/
|
|
13
|
-
let Asset = class Asset extends Rect {
|
|
14
|
-
fullSource() {
|
|
15
|
-
if (!this.assetRoot) {
|
|
16
|
-
this.assetRoot = useAssetBase();
|
|
17
|
-
}
|
|
18
|
-
let src = this.src();
|
|
19
|
-
const isUrl = src.startsWith('http://') ||
|
|
20
|
-
src.startsWith('https://') ||
|
|
21
|
-
src.startsWith('data:');
|
|
22
|
-
if (isUrl) {
|
|
23
|
-
return src;
|
|
24
|
-
}
|
|
25
|
-
// We remove the trailing slash from the assetRoot
|
|
26
|
-
// and make sure there is a leading slash in the src
|
|
27
|
-
if (src[0] !== '/') {
|
|
28
|
-
src = '/' + src;
|
|
29
|
-
}
|
|
30
|
-
return this.assetRoot.slice(0, -1) + src;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
__decorate([
|
|
34
|
-
signal()
|
|
35
|
-
], Asset.prototype, "src", void 0);
|
|
36
|
-
Asset = __decorate([
|
|
37
|
-
nodeName('Asset')
|
|
38
|
-
], Asset);
|
|
39
|
-
export { Asset };
|
|
40
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXNzZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvQXNzZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsT0FBTyxFQUFlLFlBQVksRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUN6RCxPQUFPLEVBQUMsUUFBUSxFQUFFLE1BQU0sRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUMvQyxPQUFPLEVBQUMsSUFBSSxFQUFDLE1BQU0sUUFBUSxDQUFDO0FBRTVCOztHQUVHO0FBRUksSUFBZSxLQUFLLEdBQXBCLE1BQWUsS0FBTSxTQUFRLElBQUk7SUFtQi9CLFVBQVU7UUFDZixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxTQUFTLEdBQUcsWUFBWSxFQUFFLENBQUM7UUFDbEMsQ0FBQztRQUVELElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNyQixNQUFNLEtBQUssR0FDVCxHQUFHLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQztZQUN6QixHQUFHLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQztZQUMxQixHQUFHLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTFCLElBQUksS0FBSyxFQUFFLENBQUM7WUFDVixPQUFPLEdBQUcsQ0FBQztRQUNiLENBQUM7UUFFRCxrREFBa0Q7UUFDbEQsb0RBQW9EO1FBQ3BELElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO1lBQ25CLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxDQUFDO1FBQ2xCLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQztJQUMzQyxDQUFDO0NBQ0YsQ0FBQTtBQTNCeUI7SUFEdkIsTUFBTSxFQUFFO2tDQUMrQztBQWZwQyxLQUFLO0lBRDFCLFFBQVEsQ0FBQyxPQUFPLENBQUM7R0FDSSxLQUFLLENBMEMxQiJ9
|