@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.
Files changed (129) hide show
  1. package/editor/editor/NodeInspectorConfig.d.ts +3 -0
  2. package/editor/editor/NodeInspectorConfig.d.ts.map +1 -0
  3. package/editor/editor/PreviewOverlayConfig.d.ts +3 -0
  4. package/editor/editor/PreviewOverlayConfig.d.ts.map +1 -0
  5. package/editor/editor/Provider.d.ts +17 -0
  6. package/editor/editor/Provider.d.ts.map +1 -0
  7. package/editor/editor/SceneGraphTabConfig.d.ts +3 -0
  8. package/editor/editor/SceneGraphTabConfig.d.ts.map +1 -0
  9. package/editor/editor/icons/CircleIcon.d.ts +2 -0
  10. package/editor/editor/icons/CircleIcon.d.ts.map +1 -0
  11. package/editor/editor/icons/CodeBlockIcon.d.ts +2 -0
  12. package/editor/editor/icons/CodeBlockIcon.d.ts.map +1 -0
  13. package/editor/editor/icons/CurveIcon.d.ts +2 -0
  14. package/editor/editor/icons/CurveIcon.d.ts.map +1 -0
  15. package/editor/editor/icons/GridIcon.d.ts +2 -0
  16. package/editor/editor/icons/GridIcon.d.ts.map +1 -0
  17. package/editor/editor/icons/IconMap.d.ts +3 -0
  18. package/editor/editor/icons/IconMap.d.ts.map +1 -0
  19. package/editor/editor/icons/ImgIcon.d.ts +2 -0
  20. package/editor/editor/icons/ImgIcon.d.ts.map +1 -0
  21. package/editor/editor/icons/LayoutIcon.d.ts +2 -0
  22. package/editor/editor/icons/LayoutIcon.d.ts.map +1 -0
  23. package/editor/editor/icons/LineIcon.d.ts +2 -0
  24. package/editor/editor/icons/LineIcon.d.ts.map +1 -0
  25. package/editor/editor/icons/NodeIcon.d.ts +2 -0
  26. package/editor/editor/icons/NodeIcon.d.ts.map +1 -0
  27. package/editor/editor/icons/RayIcon.d.ts +2 -0
  28. package/editor/editor/icons/RayIcon.d.ts.map +1 -0
  29. package/editor/editor/icons/RectIcon.d.ts +2 -0
  30. package/editor/editor/icons/RectIcon.d.ts.map +1 -0
  31. package/editor/editor/icons/ShapeIcon.d.ts +2 -0
  32. package/editor/editor/icons/ShapeIcon.d.ts.map +1 -0
  33. package/editor/editor/icons/TxtIcon.d.ts +2 -0
  34. package/editor/editor/icons/TxtIcon.d.ts.map +1 -0
  35. package/editor/editor/icons/VideoIcon.d.ts +2 -0
  36. package/editor/editor/icons/VideoIcon.d.ts.map +1 -0
  37. package/editor/editor/icons/View2DIcon.d.ts +2 -0
  38. package/editor/editor/icons/View2DIcon.d.ts.map +1 -0
  39. package/editor/editor/index.d.ts +4 -0
  40. package/editor/editor/index.d.ts.map +1 -0
  41. package/editor/editor/tree/DetachedRoot.d.ts +2 -0
  42. package/editor/editor/tree/DetachedRoot.d.ts.map +1 -0
  43. package/editor/editor/tree/NodeElement.d.ts +8 -0
  44. package/editor/editor/tree/NodeElement.d.ts.map +1 -0
  45. package/editor/editor/tree/TreeElement.d.ts +15 -0
  46. package/editor/editor/tree/TreeElement.d.ts.map +1 -0
  47. package/editor/editor/tree/TreeRoot.d.ts +3 -0
  48. package/editor/editor/tree/TreeRoot.d.ts.map +1 -0
  49. package/editor/editor/tree/ViewRoot.d.ts +2 -0
  50. package/editor/editor/tree/ViewRoot.d.ts.map +1 -0
  51. package/editor/editor/tree/index.d.ts +4 -0
  52. package/editor/editor/tree/index.d.ts.map +1 -0
  53. package/editor/editor/tsconfig.build.tsbuildinfo +1 -1
  54. package/lib/code/CodeSignal.d.ts +1 -1
  55. package/lib/code/CodeSignal.d.ts.map +1 -1
  56. package/lib/code/index.d.ts +1 -1
  57. package/lib/code/index.d.ts.map +1 -1
  58. package/lib/code/index.js +2 -2
  59. package/lib/components/Audio.js +3 -3
  60. package/lib/components/Img.d.ts +18 -3
  61. package/lib/components/Img.d.ts.map +1 -1
  62. package/lib/components/Img.js +37 -21
  63. package/lib/components/Layout.js +4 -2
  64. package/lib/components/Line.d.ts.map +1 -1
  65. package/lib/components/Line.js +34 -2
  66. package/lib/components/Media.d.ts +3 -3
  67. package/lib/components/Media.d.ts.map +1 -1
  68. package/lib/components/Media.js +32 -6
  69. package/lib/components/Node.d.ts.map +1 -1
  70. package/lib/components/Node.js +2 -2
  71. package/lib/components/Rive.d.ts +3 -3
  72. package/lib/components/Rive.d.ts.map +1 -1
  73. package/lib/components/Rive.js +8 -5
  74. package/lib/components/Spline.d.ts.map +1 -1
  75. package/lib/components/Spline.js +28 -2
  76. package/lib/components/TxtLeaf.d.ts +0 -1
  77. package/lib/components/TxtLeaf.d.ts.map +1 -1
  78. package/lib/components/TxtLeaf.js +5 -14
  79. package/lib/components/Video.d.ts.map +1 -1
  80. package/lib/components/Video.js +4 -4
  81. package/lib/components/View2D.d.ts.map +1 -1
  82. package/lib/components/View2D.js +1 -1
  83. package/lib/components/index.d.ts +2 -2
  84. package/lib/components/index.d.ts.map +1 -1
  85. package/lib/components/index.js +3 -3
  86. package/lib/curves/Polynomial2D.d.ts.map +1 -1
  87. package/lib/curves/index.d.ts +5 -5
  88. package/lib/curves/index.d.ts.map +1 -1
  89. package/lib/curves/index.js +6 -6
  90. package/lib/partials/Pattern.d.ts.map +1 -1
  91. package/lib/partials/Pattern.js +1 -1
  92. package/lib/scenes/Scene2D.d.ts.map +1 -1
  93. package/lib/scenes/Scene2D.js +3 -4
  94. package/lib/scenes/index.d.ts +1 -1
  95. package/lib/scenes/index.d.ts.map +1 -1
  96. package/lib/scenes/index.js +2 -2
  97. package/lib/scenes/makeScene2D.d.ts +1 -1
  98. package/lib/scenes/makeScene2D.d.ts.map +1 -1
  99. package/lib/scenes/makeScene2D.js +3 -4
  100. package/lib/tsconfig.build.tsbuildinfo +1 -1
  101. package/package.json +9 -8
  102. package/src/lib/code/index.ts +1 -1
  103. package/src/lib/components/Audio.ts +2 -2
  104. package/src/lib/components/Img.ts +48 -20
  105. package/src/lib/components/Layout.ts +3 -3
  106. package/src/lib/components/Line.ts +33 -1
  107. package/src/lib/components/Media.ts +30 -6
  108. package/src/lib/components/Rive.ts +7 -11
  109. package/src/lib/components/Spline.ts +27 -1
  110. package/src/lib/components/TxtLeaf.ts +4 -13
  111. package/src/lib/components/Video.ts +2 -3
  112. package/src/lib/components/View2D.ts +1 -0
  113. package/src/lib/components/__tests__/mockScene2D.ts +1 -5
  114. package/src/lib/components/index.ts +2 -2
  115. package/src/lib/curves/index.ts +5 -5
  116. package/src/lib/globals.d.ts +0 -1
  117. package/src/lib/partials/Pattern.ts +0 -1
  118. package/src/lib/scenes/Scene2D.ts +2 -3
  119. package/src/lib/scenes/index.ts +1 -1
  120. package/src/lib/scenes/makeScene2D.ts +3 -6
  121. package/src/lib/tsconfig.json +3 -7
  122. package/lib/components/Asset.d.ts +0 -24
  123. package/lib/components/Asset.d.ts.map +0 -1
  124. package/lib/components/Asset.js +0 -40
  125. package/src/lib/components/Asset.ts +0 -51
  126. package/src/lib/components/__logs__/image-without-source.md +0 -17
  127. package/src/lib/components/__logs__/line-without-points.md +0 -30
  128. package/src/lib/components/__logs__/reactive-playback-rate.md +0 -21
  129. package/src/lib/components/__logs__/spline-with-insufficient-knots.md +0 -24
@@ -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, viaProxy} from '@revideo/core';
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 = viaProxy(this.fullSource());
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 {Asset} from './Asset';
18
- import {RectProps} from './Rect';
19
- import imageWithoutSource from './__logs__/image-without-source.md';
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 Asset {
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 rawSrc = this.fullSource();
136
- let src = '';
137
- let key = '';
138
- if (rawSrc) {
139
- key = viaProxy(rawSrc);
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[key];
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[key] = image;
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 = Array.from(document.fonts).filter(
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 {Asset} from './Asset';
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 Asset {
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 = `${viaProxy(this.fullSource())}/${this.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 {Asset} from './Asset';
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 Asset {
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 = viaProxy(this.fullSource());
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
- import splineWithInsufficientKnots from './__logs__/spline-with-insufficient-knots.md';
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 + box.height / 2;
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 = viaProxy(this.fullSource());
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.fullSource();
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';
@@ -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';
@@ -1,3 +1,2 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
2
  /// <reference types="@revideo/core/project" />
3
- /// <reference types="@revideo/internal" />
@@ -9,7 +9,6 @@ export type CanvasRepetition =
9
9
  | 'repeat-y'
10
10
  | 'no-repeat';
11
11
 
12
- // TODO Support custom transformation matrices
13
12
  export interface PatternProps {
14
13
  image: CanvasImageSource;
15
14
  repetition?: CanvasRepetition;
@@ -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.getUrl(),
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.fullSource(),
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
 
@@ -1,3 +1,3 @@
1
- export * from './Scene2D';
2
1
  export * from './makeScene2D';
2
+ export * from './Scene2D';
3
3
  export * from './useScene2D';
@@ -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
  }
@@ -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"}
@@ -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