Skip to content

Commit a3996ab

Browse files
committed
Implemented and tested functional parameters
1 parent ea12baa commit a3996ab

File tree

9 files changed

+359
-55
lines changed

9 files changed

+359
-55
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@diffusionstudio/core",
33
"private": false,
4-
"version": "1.0.0-rc.1",
4+
"version": "1.0.0-rc.2",
55
"type": "module",
66
"description": "Build bleeding edge video processing applications",
77
"files": [

playground/main.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,26 @@ await composition.add(
106106
}]
107107
})
108108
);
109+
110+
await composition.add(
111+
new core.ImageClip(
112+
await core.ImageSource.from('/dvd_logo.svg'),
113+
{
114+
stop: composition.duration,
115+
x(this: core.TextClip, time: core.Timestamp) {
116+
const width = typeof this.width == 'number' ? this.width : 0;
117+
const range = composition.width - width;
118+
const x = (time.seconds * 500) % (range * 2);
119+
120+
return x > range ? range * 2 - x : x;
121+
},
122+
y(this: core.TextClip, time: core.Timestamp) {
123+
const height = typeof this.height == 'number' ? this.height : 0;
124+
const range = composition.height - height;
125+
const y = (time.seconds * 200) % (range * 2);
126+
127+
return y > range ? range * 2 - y : y;
128+
},
129+
}
130+
)
131+
);

public/dvd_logo.svg

Lines changed: 1 addition & 0 deletions
Loading

src/clips/mixins/visual.decorator.spec.ts

Lines changed: 221 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ describe('The visualize decorator', () => {
6161
expect(renderSpy).toHaveBeenCalledTimes(3);
6262
});
6363

64-
it('should center the clip when position center is set', async () => {
64+
it("should center the clip when position 'center' is set", async () => {
6565
const clip = new TestClip();
6666
clip.container.addChild(new Sprite());
6767
const renderer = new WebGPURenderer();
@@ -83,7 +83,7 @@ describe('The visualize decorator', () => {
8383
expect(posSpy).toHaveBeenCalledOnce();
8484
});
8585

86-
it('should set the position on render', async () => {
86+
it('should set the position on render - number', async () => {
8787
const clip = new TestClip();
8888
const renderer = new WebGPURenderer();
8989

@@ -101,6 +101,48 @@ describe('The visualize decorator', () => {
101101
expect(clip.container.x).toBe(5);
102102
expect(clip.container.y).toBe(7);
103103
expect(posSpy).toHaveBeenCalledOnce();
104+
});
105+
106+
it('should set the position on render - function', async () => {
107+
const clip = new TestClip();
108+
const renderer = new WebGPURenderer();
109+
110+
await new Composition({ width: 1000, height: 2000 })
111+
.createTrack('base')
112+
.add(clip);
113+
114+
const posSpy = vi.spyOn(clip.container.position, 'set');
115+
116+
clip.position = {
117+
x(this: TestClip, time: Timestamp) {
118+
expect(this).instanceOf(TestClip);
119+
120+
return time.millis;
121+
},
122+
y(this: TestClip, time: Timestamp) {
123+
expect(this).instanceOf(TestClip);
124+
125+
return time.millis * 2;
126+
},
127+
};
128+
129+
posSpy.mockClear()
130+
clip.render(renderer, new Timestamp(1000));
131+
132+
expect(clip.container.x).toBe(1000);
133+
expect(clip.container.y).toBe(2000);
134+
expect(posSpy).toHaveBeenCalledOnce();
135+
});
136+
137+
it('should set the position on render - keyframe', async () => {
138+
const clip = new TestClip();
139+
const renderer = new WebGPURenderer();
140+
141+
await new Composition({ width: 1000, height: 2000 })
142+
.createTrack('base')
143+
.add(clip);
144+
145+
const posSpy = vi.spyOn(clip.container.position, 'set');
104146

105147
clip.position = {
106148
x: new Keyframe([0, 60], [100, 200]),
@@ -113,8 +155,24 @@ describe('The visualize decorator', () => {
113155
expect(clip.container.x).toBe(150);
114156
expect(clip.container.y).toBe(50);
115157
expect(posSpy).toHaveBeenCalledOnce();
158+
});
159+
160+
it('should set the position on render - keyframe relative', async () => {
161+
const clip = new TestClip();
162+
const renderer = new WebGPURenderer();
116163

117-
// offset start
164+
await new Composition({ width: 1000, height: 2000 })
165+
.createTrack('base')
166+
.add(clip);
167+
168+
const posSpy = vi.spyOn(clip.container.position, 'set');
169+
170+
clip.position = {
171+
x: new Keyframe([0, 60], [100, 200]),
172+
y: new Keyframe([0, 60], [0, 100])
173+
};
174+
175+
// Make sure the relative time is used
118176
clip.stop = 100;
119177
clip.start = 30;
120178

@@ -124,12 +182,27 @@ describe('The visualize decorator', () => {
124182
expect(clip.container.x).toBe(100);
125183
expect(clip.container.y).toBe(0);
126184
expect(posSpy).toHaveBeenCalledOnce();
185+
});
186+
187+
it('should set the position on render - number relative', async () => {
188+
const clip = new TestClip();
189+
const renderer = new WebGPURenderer();
190+
191+
await new Composition({ width: 1000, height: 2000 })
192+
.createTrack('base')
193+
.add(clip);
194+
195+
const posSpy = vi.spyOn(clip.container.position, 'set');
127196

128197
clip.position = {
129198
x: '20%',
130199
y: '30%',
131200
}
132201

202+
// Make sure the relative time is used
203+
clip.stop = 100;
204+
clip.start = 30;
205+
133206
posSpy.mockClear();
134207
clip.render(renderer, new Timestamp(1000));
135208

@@ -138,6 +211,32 @@ describe('The visualize decorator', () => {
138211
expect(posSpy).toHaveBeenCalledOnce();
139212
});
140213

214+
it('should set the position on render - function relative', async () => {
215+
const clip = new TestClip();
216+
const renderer = new WebGPURenderer();
217+
218+
await new Composition({ width: 1000, height: 2000 })
219+
.createTrack('base')
220+
.add(clip);
221+
222+
const posSpy = vi.spyOn(clip.container.position, 'set');
223+
224+
225+
clip.position = {
226+
x: (time: Timestamp) => time.millis,
227+
y: (time: Timestamp) => time.millis * 2,
228+
};
229+
230+
// Make sure the relative time is used
231+
clip.start = 30;
232+
233+
posSpy.mockClear();
234+
clip.render(renderer, new Timestamp(2000));
235+
236+
expect(clip.container.x).toBe(1000);
237+
expect(clip.container.y).toBe(2000);
238+
});
239+
141240
it('should add the translate values on render', () => {
142241
const clip = new TestClip();
143242
const renderer = new WebGPURenderer();
@@ -162,6 +261,25 @@ describe('The visualize decorator', () => {
162261
expect(clip.container.x).toBe(150 + 20);
163262
expect(clip.container.y).toBe(50 + 60);
164263
expect(posSpy).toHaveBeenCalledTimes(2);
264+
265+
clip.position = { x: 50, y: 70 };
266+
clip.translate = {
267+
x(this: TestClip, time: Timestamp) {
268+
expect(this).instanceOf(TestClip);
269+
270+
return time.millis;
271+
},
272+
y(this: TestClip, time: Timestamp) {
273+
expect(this).instanceOf(TestClip);
274+
275+
return time.millis;
276+
},
277+
};
278+
279+
clip.render(renderer, new Timestamp(80));
280+
expect(clip.container.x).toBe(130);
281+
expect(clip.container.y).toBe(150);
282+
expect(posSpy).toHaveBeenCalledTimes(3);
165283
});
166284

167285
it('should set the height on render', async () => {
@@ -210,6 +328,22 @@ describe('The visualize decorator', () => {
210328
expect(clip.container.scale.y).toBe(0.25);
211329
expect(clip.container.scale.x).toBe(0.25);
212330

331+
clip.height = function(this: TestClip, time: Timestamp) {
332+
expect(this).instanceOf(TestClip);
333+
334+
return time.millis;
335+
}
336+
337+
vi.clearAllMocks();
338+
clip.render(renderer, new Timestamp(200));
339+
340+
expect(heightSpy).toHaveBeenCalledOnce();
341+
expect(scaleSpy).toHaveBeenCalledOnce();
342+
343+
expect(clip.container.height).toBe(200);
344+
expect(clip.container.width).toBe(250);
345+
expect(clip.container.scale.y).toBe(0.5);
346+
expect(clip.container.scale.x).toBe(0.5);
213347

214348
clip.height = 800;
215349

@@ -258,6 +392,23 @@ describe('The visualize decorator', () => {
258392
expect(clip.container.scale.y).toBe(2);
259393
expect(clip.container.scale.x).toBe(2);
260394

395+
clip.width = function(this: TestClip, time: Timestamp) {
396+
expect(this).instanceOf(TestClip);
397+
398+
return time.millis;
399+
}
400+
401+
vi.clearAllMocks();
402+
clip.render(renderer, new Timestamp(250));
403+
404+
expect(widthSpy).toHaveBeenCalledOnce();
405+
expect(scaleSpy).toHaveBeenCalledOnce();
406+
407+
expect(clip.container.height).toBe(200);
408+
expect(clip.container.width).toBe(250);
409+
expect(clip.container.scale.y).toBe(0.5);
410+
expect(clip.container.scale.x).toBe(0.5);
411+
261412
clip.width = new Keyframe([0, 12], [0, 200]);
262413

263414
vi.clearAllMocks();
@@ -342,6 +493,53 @@ describe('The visualize decorator', () => {
342493
expect(scaleSpy).toHaveBeenCalledOnce();
343494
});
344495

496+
it('should be able to scale as a Function', () => {
497+
const clip = new TestClip();
498+
const renderer = new WebGPURenderer();
499+
const scaleSpy = vi.spyOn(clip.container.scale, 'set');
500+
501+
clip.scale = function (this: TestClip, time: Timestamp) {
502+
expect(this).instanceOf(TestClip);
503+
504+
return time.millis;
505+
}
506+
507+
clip.render(renderer, new Timestamp(50));
508+
509+
expect(clip.scale.x).toBeTypeOf('function');
510+
expect(clip.scale.y).toBeTypeOf('function');
511+
expect(clip.container.scale._x).toBe(50);
512+
expect(clip.container.scale._y).toBe(50);
513+
expect(scaleSpy.mock.calls[0][0]).toBe(50);
514+
});
515+
516+
it('should be able to scale x and y as a Function', () => {
517+
const clip = new TestClip();
518+
const renderer = new WebGPURenderer();
519+
const scaleSpy = vi.spyOn(clip.container.scale, 'set');
520+
521+
clip.scale = {
522+
x(this: TestClip, time: Timestamp) {
523+
expect(this).instanceOf(TestClip);
524+
525+
return time.millis;
526+
},
527+
y(this: TestClip, time: Timestamp) {
528+
expect(this).instanceOf(TestClip);
529+
530+
return time.millis;
531+
},
532+
};
533+
534+
clip.render(renderer, new Timestamp(50));
535+
536+
expect(clip.scale.x).toBeTypeOf('function');
537+
expect(clip.scale.y).toBeTypeOf('function');
538+
expect(clip.container.scale._x).toBe(50);
539+
expect(clip.container.scale._y).toBe(50);
540+
expect(scaleSpy.mock.calls[0][0]).toBe(50);
541+
});
542+
345543
it('should set scale x any y independently on render', () => {
346544
const clip = new TestClip();
347545
const renderer = new WebGPURenderer();
@@ -414,6 +612,16 @@ describe('The visualize decorator', () => {
414612
clip.render(renderer, new Timestamp(1000));
415613
expect(clip.container.angle).toBe(90);
416614
expect(angleSpy).toHaveBeenCalledTimes(2);
615+
616+
clip.rotation = function(this: TestClip, time: Timestamp) {
617+
expect(this).instanceOf(TestClip);
618+
619+
return time.millis;
620+
}
621+
622+
clip.render(renderer, new Timestamp(6));
623+
expect(Math.round(clip.container.angle)).toBe(6);
624+
expect(angleSpy).toHaveBeenCalledTimes(3);
417625
});
418626

419627
it('should set the opacity on render', () => {
@@ -433,5 +641,15 @@ describe('The visualize decorator', () => {
433641
clip.render(renderer, new Timestamp(1000));
434642
expect(clip.container.alpha).toBe(0.3);
435643
expect(alphaSpy).toHaveBeenCalledTimes(2);
644+
645+
clip.alpha = function(this: TestClip, time: Timestamp) {
646+
expect(this).instanceOf(TestClip);
647+
648+
return time.millis / 2;
649+
}
650+
651+
clip.render(renderer, new Timestamp(1));
652+
expect(clip.container.alpha).toBe(0.5);
653+
expect(alphaSpy).toHaveBeenCalledTimes(3);
436654
});
437655
});

0 commit comments

Comments
 (0)