blob: ff40d41fafc7f81c7a51d913cfd9d9174ffbd806 [file] [edit]
export const description = "Video swipe";
export const help = "This transition performs simple 2D affine transformations for source videos transitions, with configurable effect origin";
export const options = [
{name:"from", value: "left", desc: `direction of video 2 entry. Possible values are:
- left: from left to right edges
- right: from right to left edges
- top: from top to bottom edges
- bottom: from bottom to top edges
- topleft: from top-left to bottom-right corners
- topright: from top-right to bottom-left corners
- bottomleft: from bottom-left to top-right corners
- bottomright: from bottom-right to top-left corners
`},
{name:"mode", value: "slide", desc: `how video 2 entry impacts video 1. Possible values are:
- slide: video 1 position is not modified
- push: video 2 pushes video 1 away
- squeeze: video 2 squeezes video 1 along opposite edge
- grow: video 2 size increases, video 1 not modified
- swap: video 2 size increases, video 1 size decreases
`},
{}
];
export function load() { return {
h_mode: 0,
v_mode: 0,
mod: 0,
setup: function()
{
if (this.mode == "push") this.mod = 1;
else if (this.mode == "squeeze") this.mod = 2;
else if (this.mode == "grow") this.mod = 3;
else if (this.mode == "swap") this.mod = 4;
else this.mod = 0;
this.h_mode = 0;
this.v_mode = 0;
if (this.from == "left") this.h_mode = 1;
else if (this.from == "right") this.h_mode = 2;
else if (this.from == "top") this.v_mode = 1;
else if (this.from == "bottom") this.v_mode = 2;
else if (this.from == "topleft") {
this.h_mode = 1;
this.v_mode = 1;
}
else if (this.from == "topright") {
this.h_mode = 2;
this.v_mode = 1;
}
else if (this.from == "bottomleft") {
this.h_mode = 1;
this.v_mode = 2;
}
else if (this.from == "bottomright") {
this.h_mode = 2;
this.v_mode = 2;
}
},
apply: function(canvas, ratio, path, pids)
{
if (use_gpu) {
this.apply_gl(canvas, ratio, path, pids);
return;
}
let rc = path.bounds;
if (typeof rc == 'undefined') return;
let new_w = rc.w;
let new_h = rc.h;
let new_x = 0;
let new_y = 0;
//left
if (this.h_mode == 1) {
new_x = -rc.w/2 + rc.w*ratio/2;
new_w = rc.w*ratio;
}
//right
else if (this.h_mode == 2) {
new_x = rc.w/2 - rc.w*ratio/2;
new_w = rc.w*ratio;
}
//top
if (this.v_mode==1) {
new_y = rc.h/2 - rc.h*ratio/2;
new_h = rc.h*ratio;
}
//bottom
else if (this.v_mode==2) {
new_y = -rc.h/2 + rc.h*ratio/2;
new_h = rc.h*ratio;
}
let new_path = path.clone();
//add rectangle to path
new_path.rectangle(new_x, new_y, new_w, new_h, true);
//use zero-nonzero fill
new_path.zero_fill = true;
if (! this.mod) {
canvas.path = new_path;
canvas.fill(GF_EVG_OPERAND_ODD_FILL, ratio, pids[0].texture, pids[1].texture);
return;
}
let mx1_bck = pids[0].texture.mx;
let mx2_bck = pids[1].texture.mx;
let mx1 = mx1_bck.copy();
let mx2 = mx2_bck.copy();
let t_x1 = 0;
let t_y1 = 0;
let t_x2 = 0;
let t_y2 = 0;
let c_x1 = 0.5;
let c_y1 = 0.5;
let c_x2 = 0.5;
let c_y2 = 0.5;
//left
if (this.h_mode==1) {
t_x1 = ratio;
c_x1 -= 0.5;
t_x2 = (ratio-1);
c_x2 += 0.5;
}
//right
else if (this.h_mode==2) {
t_x1 = -ratio;
c_x1 += 0.5;
t_x2 = -(ratio-1);
c_x2 -= 0.5;
}
//top
if (this.v_mode==1) {
t_y1 = -ratio;
c_y1 -= 0.5;
t_y2 = -(ratio-1);
c_y2 += 0.5;
}
//bottom
else if (this.v_mode==2) {
t_y1 = ratio;
c_y1 += 0.5;
t_y2 = (ratio-1);
c_y2 -= 0.5;
}
mx1.translate(-t_x1, t_y1);
mx2.translate(-t_x2, t_y2);
if ((this.mod == 2) || (this.mod == 4)) {
mx1.translate(-c_x1, -c_y1);
mx1.scale( 1 / (1-ratio), 1/(1-ratio) );
mx1.translate(c_x1, c_y1);
}
if ((this.mod == 3) || (this.mod == 4)) {
mx2.translate(-c_x2, -c_y2);
mx2.scale(1/ratio, 1/ratio);
mx2.translate(c_x2, c_y2);
}
let pad1_bck = pids[0].texture.get_pad_color();
let pad2_bck = pids[1].texture.get_pad_color();
let pad_col = pad1_bck || pad2_bck || 'black';
//pad with the same color !
pids[0].texture.set_pad_color(pad_col);
pids[1].texture.set_pad_color(pad_col);
pids[0].texture.mx = mx1;
pids[1].texture.mx = mx2;
canvas.path = new_path;
canvas.fill(GF_EVG_OPERAND_ODD_FILL, ratio, pids[0].texture, pids[1].texture);
pids[0].texture.set_pad_color(pad1_bck);
pids[1].texture.set_pad_color(pad2_bck);
pids[0].texture.mx = mx1_bck;
pids[1].texture.mx = mx2_bck;
},
pad_col_uni: null,
pad_col: null,
setup_gl: function(webgl, program, first_available_texture_unit)
{
this.pad_col_uni = webgl.getUniformLocation(program, 'swipe_pad_color');
this.pad_col = null;
},
apply_gl: function(webgl, ratio, path, pids)
{
if (!this.pad_col_uni) return;
let pad1_bck = pids[0].texture.get_pad_color() || 'black';
if (this.pad_col !== pad1_bck) {
let a = sys.color_component(pad1_bck, 0);
let r = sys.color_component(pad1_bck, 1);
let g = sys.color_component(pad1_bck, 2);
let b = sys.color_component(pad1_bck, 3);
webgl.uniform4f(this.pad_col_uni, r, g, b, a);
this.pad_col = pad1_bck;
}
},
get_shader_src: function()
{
this.setup();
let frag_src = `vec4 gf_apply_effect() {
vec2 p = txcoord_from.xy;
vec2 p_to = txcoord_to.xy;
`;
if (this.mod==0) {
frag_src += `
vec2 txcf = p;
vec2 txct = p_to;
`;
}
let use_pad = false;
if (this.h_mode == 1) {
//topleft
if (this.v_mode == 1) {
frag_src += 'float myratio = step(0.0 + p.x, ratio) * step(0.0 + p.y, ratio);';
if (this.mod) {
use_pad = true;
frag_src += `
vec2 txcf = vec2(p.x - ratio, p.y - ratio);
vec2 txct = vec2(1.0 + p_to.x - ratio, 1.0 + p_to.y - ratio);
float is_in = (myratio==0.0) ? step(1.0, txct.x) * step(1.0, txct.y) : 1.0;
`;
}
if ((this.mod==2) || (this.mod==4)) {
frag_src += `
txcf /= (1.0-ratio);
is_in *= (myratio==0.0) ? step(txcf.y, 1.0) * step(0.0, txcf.y) : 1.0;
`;
}
if ((this.mod==3) || (this.mod==4)) {
frag_src += `
txct.x -= 1.0;
txct.y -= 1.0;
txct /= ratio;
txct.x += 1.0;
txct.y += 1.0;
is_in *= (myratio>0.0) ? step(0.0, txct.y) * step(txct.y, 1.0) : 1.0;
`;
}
}
//bottomleft
else if (this.v_mode == 2) {
frag_src += 'float myratio = step(0.0 + p.x, ratio) * step(1.0 - p.y, ratio);';
if (this.mod) {
use_pad = true;
frag_src += `
vec2 txcf = vec2(p.x - ratio, p.y + ratio);
vec2 txct = vec2(1.0 + p_to.x - ratio, p_to.y + ratio - 1.0);
float is_in = (myratio==0.0) ? step(1.0, txct.x) * step(txct.y, 0.0) : 1.0;
`;
}
if ((this.mod==2) || (this.mod==4)) {
frag_src += `
txcf.y -= 1.0;
txcf /= (1.0-ratio);
txcf.y += 1.0;
is_in *= (myratio==0.0) ? step(txcf.y, 1.0) * step(0.0, txcf.y) : 1.0;
`;
}
if ((this.mod==3) || (this.mod==4)) {
frag_src += `
txct.x -= 1.0;
txct /= ratio;
txct.x += 1.0;
is_in *= (myratio>0.0) ? step(0.0, txct.y) * step(txct.y, 1.0) : 1.0;
`;
}
}
//left
else {
frag_src += 'float myratio = step(0.0 + p.x, ratio);';
if (this.mod) {
frag_src += `
vec2 txcf = vec2(p.x - ratio, p.y);
vec2 txct = vec2(1.0 + p_to.x - ratio, p_to.y);
`;
}
if (this.mod>1) {
frag_src += `
float is_in;
`;
use_pad = true;
}
if ((this.mod==2) || (this.mod==4)) {
frag_src += `
txcf.y -= 0.5;
txcf /= (1.0-ratio);
txcf.y += 0.5;
is_in = (myratio==0.0) ? step(txcf.y, 1.0) * step(0.0, txcf.y) : 1.0;
`;
}
if ((this.mod==3) || (this.mod==4)) {
let op = (this.mod==4) ? '*=' : '=';
frag_src += `
txct.x -= 1.0;
txct.y -= 0.5;
txct /= ratio;
txct.x += 1.0;
txct.y += 0.5;
is_in `+ op + ` (myratio>0.0) ? step(0.0, txct.y) * step(txct.y, 1.0) : 1.0;
`;
}
}
}
else if (this.h_mode == 2) {
//topright
if (this.v_mode == 1) {
frag_src += 'float myratio = step(1.0 - p.x, ratio) * step(0.0 + p.y, ratio);';
if (this.mod) {
use_pad = true;
frag_src += `
vec2 txcf = vec2(p.x + ratio, p.y - ratio);
vec2 txct = vec2(p_to.x + ratio - 1.0, 1.0 + p_to.y - ratio);
float is_in = (myratio==0.0) ? step(txct.x, 0.0) * step(1.0, txct.y) : 1.0;
`;
}
if ((this.mod==2) || (this.mod==4)) {
frag_src += `
txcf.x -= 1.0;
txcf /= (1.0-ratio);
txcf.x += 1.0;
is_in *= (myratio==0.0) ? step(txcf.y, 1.0) * step(0.0, txcf.y) : 1.0;
`;
}
if ((this.mod==3) || (this.mod==4)) {
frag_src += `
txct.y -= 1.0;
txct /= ratio;
txct.y += 1.0;
is_in *= (myratio>0.0) ? step(0.0, txct.y) * step(txct.y, 1.0) : 1.0;
`;
}
}
//bottomright
else if (this.v_mode == 2) {
frag_src += 'float myratio = step(1.0 - p.x, ratio) * step(1.0 - p.y, ratio);';
if (this.mod) {
use_pad = true;
frag_src += `
vec2 txcf = vec2(p.x + ratio, p.y + ratio);
vec2 txct = vec2(p_to.x + ratio - 1.0, p_to.y + ratio - 1.0);
float is_in = (myratio==0.0) ? step(txct.x, 0.0) * step(txct.y, 0.0) : 1.0;
`;
}
if (this.mod==2) {
frag_src += `
txcf.x -= 1.0;
txcf.y -= 1.0;
txcf /= (1.0-ratio);
txcf.x += 1.0;
txcf.y += 1.0;
is_in *= (myratio==0.0) ? step(txcf.y, 1.0) * step(0.0, txcf.y) : 1.0;
`;
}
if (this.mod==3) {
frag_src += `
txct /= ratio;
is_in *= (myratio>0.0) ? step(0.0, txct.y) * step(txct.y, 1.0) : 1.0;
`;
}
if (this.mod==4) {
frag_src += `
txcf.x -= 1.0;
txcf.y -= 1.0;
txcf /= (1.0-ratio);
txcf.x += 1.0;
txcf.y += 1.0;
is_in *= (myratio==0.0) ? step(txcf.y, 1.0) * step(0.0, txcf.y) : 1.0;
txct /= ratio;
is_in *= (myratio>0.0) ? step(0.0, txct.y) * step(txct.y, 1.0) : 1.0;
`;
}
}
//right
else {
frag_src += 'float myratio = step(1.0 - p.x, ratio);';
if (this.mod) {
frag_src += `
vec2 txcf = vec2(p.x + ratio, p.y);
vec2 txct = vec2(p_to.x + ratio - 1.0, p_to.y);
`;
}
if (this.mod>1) {
frag_src += `
float is_in;
`;
use_pad = true;
}
if ((this.mod==2) || (this.mod==4)) {
frag_src += `
txcf.x -= 1.0;
txcf.y -= 0.5;
txcf /= (1.0-ratio);
txcf.x += 1.0;
txcf.y += 0.5;
is_in = (myratio==0.0) ? step(txcf.y, 1.0) * step(0.0, txcf.y) : 1.0;
`;
}
if ((this.mod==3) || (this.mod==4)) {
let op = (this.mod==4) ? '*=' : '=';
frag_src += `
txct.y -= 0.5;
txct /= ratio;
txct.y += 0.5;
is_in `+ op + ` (myratio>0.0) ? step(0.0, txct.y) * step(txct.y, 1.0) : 1.0;
`;
}
}
}
//top
else if (this.v_mode == 1) {
frag_src += 'float myratio = step(0.0 + p.y, ratio);';
if (this.mod) {
frag_src += `
vec2 txcf = vec2(p.x, p.y - ratio);
vec2 txct = vec2(p_to.x, 1.0 + p_to.y - ratio);
`;
}
if (this.mod>1) {
frag_src += `
float is_in;
`;
use_pad = true;
}
if ((this.mod==2) || (this.mod==4)) {
frag_src += `
txcf.x -= 0.5;
txcf /= (1.0-ratio);
txcf.x += 0.5;
is_in = (myratio==0.0) ? step(0.0, txcf.x) * step(txcf.x, 1.0) : 1.0;
`;
}
if ((this.mod==3) || (this.mod==4)) {
let op = (this.mod==4) ? '*=' : '=';
frag_src += `
txct.x -= 0.5;
txct.y -= 1.0;
txct /= ratio;
txct.x += 0.5;
txct.y += 1.0;
is_in ` + op +` (myratio>0.0) ? step( 0.0, txct.x) * step(txct.x, 1.0) : 1.0;
`;
}
}
//bottom
else if (this.v_mode == 2) {
frag_src += 'float myratio = step(1.0 - p.y, ratio);';
if (this.mod) {
frag_src += `
vec2 txcf = vec2(p.x, p.y + ratio);
vec2 txct = vec2(p_to.x, p_to.y + ratio - 1.0);
`;
}
if (this.mod>1) {
frag_src += `
float is_in;
`;
use_pad = true;
}
if ((this.mod==2) || (this.mod==4)) {
frag_src += `
txcf.x -= 0.5;
txcf.y -= 1.0;
txcf /= (1.0-ratio);
txcf.x += 0.5;
txcf.y += 1.0;
is_in = (myratio==0.0) ? step(0.0, txcf.x) * step(txcf.x, 1.0) : 1.0;
`;
}
if ((this.mod==3) || (this.mod==4)) {
let op = (this.mod==4) ? '*=' : '=';
frag_src += `
txct.x -= 0.5;
txct /= ratio;
txct.x += 0.5;
is_in `+ op + `(myratio>0.0) ? step( 0.0, txct.x) * step(txct.x, 1.0) : 1.0;
`;
}
} else {
frag_src += 'float myratio = ratio;';
}
frag_src += `
vec4 col_from = get_pixel_from(txcf.xy);
vec4 col_to = get_pixel_to(txct.xy);`;
if (use_pad) {
frag_src += `
is_in = (is_in==0.0) ? 0.0 : 1.0;
return mix(swipe_pad_color, mix(col_from, col_to, myratio), is_in);
}`;
} else {
frag_src += `
return mix(col_from, col_to, myratio);
}`;
}
if (use_pad) {
frag_src = 'uniform vec4 swipe_pad_color;\n' + frag_src;
}
return frag_src;
}
}; }