diff options
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_sequence_types.h | 13 | ||||
-rw-r--r-- | source/blender/src/drawseq.c | 23 | ||||
-rw-r--r-- | source/blender/src/editseq.c | 23 | ||||
-rw-r--r-- | source/blender/src/header_seq.c | 4 | ||||
-rw-r--r-- | source/blender/src/seqeffects.c | 292 |
6 files changed, 352 insertions, 6 deletions
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 7ced7f74c7a..96c1b2ceb9b 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1234,6 +1234,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase) case SEQ_GLOW: writestruct(wd, DATA, "GlowVars", 1, seq->effectdata); break; + case SEQ_TRANSFORM: + writestruct(wd, DATA, "TransformVars", 1, seq->effectdata); + break; } } diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 6762279559c..0213b8263ff 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -160,6 +160,18 @@ typedef struct GlowVars { int bNoComp; /* SHOW/HIDE glow buffer */ } GlowVars; +typedef struct TransformVars { + float ScalexIni; + float ScaleyIni; + float ScalexFin; + float ScaleyFin; + float xIni; + float xFin; + float yIni; + float yFin; + float rotIni; + float rotFin; +} TransformVars; /* ***************** SEQUENCE ****************** */ @@ -195,6 +207,7 @@ typedef struct GlowVars { #define SEQ_PLUGIN 24 #define SEQ_WIPE 25 #define SEQ_GLOW 26 +#define SEQ_TRANSFORM 27 #endif diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index f42fb786d3d..5492dd40ff5 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -116,6 +116,7 @@ static char *give_seqname(Sequence *seq) else if(seq->type==SEQ_OVERDROP) return "Over Drop"; else if(seq->type==SEQ_WIPE) return "Wipe"; else if(seq->type==SEQ_GLOW) return "Glow"; + else if(seq->type==SEQ_TRANSFORM) return "Transform"; else if(seq->type==SEQ_PLUGIN) { if(!(seq->flag & SEQ_EFFECT_NOT_LOADED) && seq->plugin && seq->plugin->doit) return seq->plugin->pname; @@ -178,6 +179,7 @@ static void get_seq_color3ubv(Sequence *seq, char *col) break; /* effects */ + case SEQ_TRANSFORM: case SEQ_ADD: case SEQ_SUB: case SEQ_MUL: @@ -198,7 +200,8 @@ static void get_seq_color3ubv(Sequence *seq, char *col) if (seq->type == SEQ_ALPHAUNDER) hsv[0]+= 0.20; if (seq->type == SEQ_OVERDROP) hsv[0]+= 0.24; if (seq->type == SEQ_GLOW) hsv[0]+= 0.28; - + if (seq->type == SEQ_TRANSFORM) hsv[0]+= 0.36; + if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0; hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2); col[0] = (char)(rgb[0]*255); col[1] = (char)(rgb[1]*255); col[2] = (char)(rgb[2]*255); @@ -1149,7 +1152,6 @@ static void seq_panel_properties(short cntrl) // SEQ_HANDLER_PROPERTIES else if(last_seq->type==SEQ_GLOW){ GlowVars *glow = (GlowVars *)last_seq->effectdata; - uiBlockBeginAlign(block); uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Threshold:", 10,70,150,19, &glow->fMini, 0.0, 1.0, 0, 0, "Trigger Intensity"); uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Clamp:", 10,50,150,19, &glow->fClamp, 0.0, 1.0, 0, 0, "Brightness limit of intensity"); uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Boost factor:", 10,30,150,19, &glow->fBoost, 0.0, 10.0, 0, 0, "Brightness multiplier"); @@ -1157,6 +1159,23 @@ static void seq_panel_properties(short cntrl) // SEQ_HANDLER_PROPERTIES uiDefButI(block, NUM, B_NOP, "Quality:", 10,-5,150,19, &glow->dQuality, 1.0, 5.0, 0, 0, "Accuracy of the blur effect"); uiDefButI(block, TOG, B_NOP, "Only boost", 10,-25,150,19, &glow->bNoComp, 0.0, 0.0, 0, 0, "Show the glow buffer only"); } + else if(last_seq->type==SEQ_TRANSFORM){ + TransformVars *transform = (TransformVars *)last_seq->effectdata; + + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "xScale Start:", 10,70,150,19, &transform->ScalexIni, 0.0, 10.0, 0, 0, "X Scale Start"); + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "xScale End:", 160,70,150,19, &transform->ScalexFin, 0.0, 10.0, 0, 0, "X Scale End"); + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "yScale Start:", 10,50,150,19, &transform->ScaleyIni, 0.0, 10.0, 0, 0, "Y Scale Start"); + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "yScale End:", 160,50,150,19, &transform->ScaleyFin, 0.0, 10.0, 0, 0, "Y Scale End"); + + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "x Start:", 10,30,150,19, &transform->xIni, -1000.0, 1000.0, 0, 0, "X Position Start"); + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "x End:", 160,30,150,19, &transform->xFin, -1000.0, 1000.0, 0, 0, "X Position End"); + + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "y Start:", 10,10,150,19, &transform->yIni, -1000.0, 1000.0, 0, 0, "Y Position Start"); + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "y End:", 160,10,150,19, &transform->yFin, -1000.0, 1000.0, 0, 0, "Y Position End"); + + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "rot Start:",10,-10,150,19, &transform->rotIni, 0.0, 360.0, 0, 0, "Rotation Start"); + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "rot End:",160,-10,150,19, &transform->rotFin, 0.0, 360.0, 0, 0, "Rotation End"); + } uiBlockEndAlign(block); } } diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index eb5c64dbd5d..848f6bc41dd 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -1036,6 +1036,7 @@ static int event_to_efftype(int event) if(event==10) return SEQ_PLUGIN; if(event==13) return SEQ_WIPE; if(event==14) return SEQ_GLOW; + if(event==15) return SEQ_TRANSFORM; return 0; } @@ -1075,8 +1076,16 @@ static int add_seq_effect(int type) } seq= seq->next; } + + /* make sequence selection a little bit more intuitive + for 3 strips: the last-strip should be sequence3 */ + if (seq3 != 0 && seq2 != 0) { + seq2 = seq3; + seq3 = last_seq; + } - if(type==10 || type==13 || type==14) { /* plugin: minimal 1 select */ + + if(type==10 || type==13 || type==14 || type==15) { /* plugin: minimal 1 select */ if(seq2==0) { error("Need at least one selected sequence strip"); return 0; @@ -1214,6 +1223,9 @@ void add_sequence(int type) case SEQ_GLOW: event = 14; break; + case SEQ_TRANSFORM: + event = 15; + break; default: event = 0; break; @@ -1241,7 +1253,8 @@ void add_sequence(int type) "|Alpha Under%x8" "|Alpha Over Drop%x9" "|Wipe%x13" - "|Glow%x14"); + "|Glow%x14" + "|Transforms%x15"); } if(event<1) return; @@ -1295,6 +1308,8 @@ void add_sequence(int type) seq->len= sce->r.efra - sce->r.sfra + 1; seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + strncpy(seq->name + 2, sce->id.name + 2, + sizeof(seq->name) - 2); strip->len= seq->len; strip->us= 1; if(seq->len>0) strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); @@ -1317,6 +1332,7 @@ void add_sequence(int type) case 10: case 13: case 14: + case 15: if(last_seq==0) error("Need at least one active sequence strip"); else if(event==10) { @@ -1360,7 +1376,8 @@ void change_sequence(void) "|Alpha Under%x8" "|Alpha Over Drop%x9" "|Wipe%x13" - "|Glow%x14"); + "|Glow%x14" + "|Transform%x15"); if(event > 0) { if(event==1) { SWAP(Sequence *,last_seq->seq1,last_seq->seq2); diff --git a/source/blender/src/header_seq.c b/source/blender/src/header_seq.c index a596076a133..c0fe272dc6c 100644 --- a/source/blender/src/header_seq.c +++ b/source/blender/src/header_seq.c @@ -231,6 +231,9 @@ static void do_seq_addmenu_effectmenu(void *arg, int event) case 10: add_sequence(SEQ_GLOW); break; + case 11: + add_sequence(SEQ_TRANSFORM); + break; } } @@ -252,6 +255,7 @@ static uiBlock *seq_addmenu_effectmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Alpha Over Drop", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Wipe", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Glow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Transform", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Plugin...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); diff --git a/source/blender/src/seqeffects.c b/source/blender/src/seqeffects.c index 41f8f4cb846..02ad7f44a4a 100644 --- a/source/blender/src/seqeffects.c +++ b/source/blender/src/seqeffects.c @@ -1383,7 +1383,8 @@ static void do_mul_effect_byte(float facf0, float facf1, int x, int y, fac3= (int)(256.0*facf1); /* formula: - * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+a + * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+axaux= c*px + py*s ;//+centx + yaux= -s*px + c*py;//+centy */ while(y--) { @@ -1890,6 +1891,289 @@ static void do_wipe_effect(Sequence * seq,int cfra, (char*) out->rect); } } +/* ********************************************************************** + transform + ********************************************************************** */ +static void init_transform_effect(Sequence *seq) +{ + TransformVars *scale; + + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = MEM_callocN(sizeof(struct TransformVars), "transformvars"); + + scale = (TransformVars *)seq->effectdata; + scale->ScalexIni = 1; + scale->ScaleyIni = 1; + scale->ScalexFin = 1; + scale->ScaleyFin = 1; + + scale->xIni=0; + scale->xFin=0; + scale->yIni=0; + scale->yFin=0; + + scale->rotIni=0; + scale->rotFin=0; + +} + +static void free_transform_effect(Sequence *seq) +{ + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = 0; +} + +static void copy_transform_effect(Sequence *dst, Sequence *src) +{ + dst->effectdata = MEM_dupallocN(src->effectdata); +} + +/* function assumes out to be zero'ed, only does RGBA */ +static void bilinear_interpolation_transform_float(ImBuf *in, float *out, float u, float v) +{ + float *row1, *row2, *row3, *row4, a, b; + float a_b, ma_b, a_mb, ma_mb; + float empty[4]= {0.0f, 0.0f, 0.0f, 0.0f}; + int y1, y2, x1, x2; + + x1= (int)floor(u); + x2= (int)ceil(u); + y1= (int)floor(v); + y2= (int)ceil(v); + + /* sample area entirely outside image? */ + if(x2<0 || x1>in->x-1 || y2<0 || y1>in->y-1) + return; + + /* sample including outside of edges of image */ + if(x1<0 || y1<0) row1= empty; + else row1= in->rect_float + in->x * y1 * 4 + 4*x1; + + if(x1<0 || y2>in->y-1) row2= empty; + else row2= in->rect_float + in->x * y2 * 4 + 4*x1; + + if(x2>in->x-1 || y1<0) row3= empty; + else row3= in->rect_float + in->x * y1 * 4 + 4*x2; + + if(x2>in->x-1 || y2>in->y-1) row4= empty; + else row4= in->rect_float + in->x * y2 * 4 + 4*x2; + + a= u-floor(u); + b= v-floor(v); + a_b= a*b; ma_b= (1.0f-a)*b; a_mb= a*(1.0f-b); ma_mb= (1.0f-a)*(1.0f-b); + + out[0]= ma_mb*row1[0] + a_mb*row3[0] + ma_b*row2[0]+ a_b*row4[0]; + out[1]= ma_mb*row1[1] + a_mb*row3[1] + ma_b*row2[1]+ a_b*row4[1]; + out[2]= ma_mb*row1[2] + a_mb*row3[2] + ma_b*row2[2]+ a_b*row4[2]; + out[3]= ma_mb*row1[3] + a_mb*row3[3] + ma_b*row2[3]+ a_b*row4[3]; +} + + +static void do_transform_effect_float(Sequence * seq,float facf0, int x, int y, + struct ImBuf *ibuf1,float *out) +{ + int xo, yo, xi, yi; + float xs,ys,factxScale,factyScale,tx,ty,rad,s,c,xaux,yaux,factRot,px,py; + TransformVars *scale; + + scale = (TransformVars *)seq->effectdata; + xo = x; + yo = y; + + /*factor scale*/ + factxScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0; + factyScale = scale->ScaleyIni + (scale->ScaleyFin - scale->ScaleyIni) * facf0; + + /*Factor translate*/ + tx = scale->xIni+(xo / 2.0f) + (scale->xFin-(xo / 2.0f) - scale->xIni+(xo / 2.0f)) * facf0; + ty = scale->yIni+(yo / 2.0f) + (scale->yFin-(yo / 2.0f) - scale->yIni+(yo / 2.0f)) * facf0; + + /*factor Rotate*/ + factRot = scale->rotIni + (scale->rotFin - scale->rotIni) * facf0; + rad = (M_PI * factRot) / 180.0f; + s= sin(rad); + c= cos(rad); + + for (yi = 0; yi < yo; yi++) { + for (xi = 0; xi < xo; xi++) { + /*tranlate point*/ + px = xi-tx; + py = yi-ty; + + /*rotate point with center ref*/ + xaux = c*px + py*s ; + yaux = -s*px + c*py; + + /*scale point with center ref*/ + xs = xaux / factxScale; + ys = yaux / factyScale; + + /*undo reference center point */ + xs += (xo / 2.0f); + ys += (yo / 2.0f); + + /*interpolate*/ + bilinear_interpolation_transform_float(ibuf1,out, xs,ys); + + out+=4; + } + } + +} + +/* function assumes out to be zero'ed, only does RGBA */ +static void bilinear_interpolation_transform_byte(unsigned char *in, unsigned char *out, float u, float v,int x,int y) +{ + float a, b; + float a_b, ma_b, a_mb, ma_mb; + int y1, y2, x1, x2; + + int row1R,row1G,row1B,row1A; + int row2R,row2G,row2B,row2A; + int row3R,row3G,row3B,row3A; + int row4R,row4G,row4B,row4A; + + x1= (int)floor(u); + x2= (int)ceil(u); + y1= (int)floor(v); + y2= (int)ceil(v); + + /* sample area entirely outside image? */ + if(x2<0 || x1>x-1 || y2<0 || y1>y-1) + return; + + /* sample including outside of edges of image */ + if(x1<0 || y1<0){ + row1R = 0; + row1G = 0; + row1B = 0; + row1A = 0; + } + else{ + row1R= in[x * y1 * 4 + 4 * x1]; + row1G= in[x * y1 * 4 + 4 * x1 + 1]; + row1B= in[x * y1 * 4 + 4 * x1 + 2]; + row1A= in[x * y1 * 4 + 4 * x1 + 3]; + } + + if(x1<0 || y2>y-1){ + row2R = 0; + row2G = 0; + row2B = 0; + row2A = 0; + } + else{ + row2R= in[x * y2 * 4 + 4 * x1]; + row2G= in[x * y2 * 4 + 4 * x1 + 1]; + row2B= in[x * y2 * 4 + 4 * x1 + 2]; + row2A= in[x * y2 * 4 + 4 * x1 + 3]; + } + + if(x2>x-1 || y1<0){ + row3R = 0; + row3G = 0; + row3B = 0; + row3A = 0; + } + else{ + row3R= in[x * y1 * 4 + 4 * x2]; + row3G= in[x * y1 * 4 + 4 * x2 + 1]; + row3B= in[x * y1 * 4 + 4 * x2 + 2]; + row3A= in[x * y1 * 4 + 4 * x2 + 3]; + } + + if(x2>x-1 || y2>y-1){ + row4R = 0; + row4G = 0; + row4B = 0; + row4A = 0; + } + else{ + row4R= in[x * y2 * 4 + 4 * x2]; + row4G= in[x * y2 * 4 + 4 * x2 + 1]; + row4B= in[x * y2 * 4 + 4 * x2 + 2]; + row4A= in[x * y2 * 4 + 4 * x2 + 3]; + } + + a= u-floor(u); + b= v-floor(v); + a_b= a*b; ma_b= (1-a)*b; a_mb= a*(1-b); ma_mb= (1-a)*(1-b); + + out[0]= (int)(ma_mb*row1R + a_mb*row3R + ma_b*row2R + a_b*row4R); + out[1]= (int)(ma_mb*row1G + a_mb*row3G + ma_b*row2G + a_b*row4G); + out[2]= (int)(ma_mb*row1B + a_mb*row3B + ma_b*row2B + a_b*row4B); + out[3]= (int)(ma_mb*row1A + a_mb*row3A + ma_b*row2A + a_b*row4A); +} + +static void do_transform_effect_byte(Sequence * seq,float facf0, int x, int y, + unsigned char *ibuf1,unsigned char *out) +{ + int xo, yo, xi, yi; + float xs,ys,factxScale,factyScale,tx,ty,rad,s,c,xaux,yaux,factRot,px,py; + TransformVars *scale; + + scale = (TransformVars *)seq->effectdata; + xo = x; + yo = y; + + /*factor scale*/ + factxScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0; + factyScale = scale->ScaleyIni + (scale->ScaleyFin - scale->ScaleyIni) * facf0; + + /*Factor translate*/ + tx = scale->xIni+(xo / 2.0f) + (scale->xFin-(xo / 2.0f) - scale->xIni+(xo / 2.0f)) * facf0; + ty = scale->yIni+(yo / 2.0f) + (scale->yFin-(yo / 2.0f) - scale->yIni+(yo / 2.0f)) * facf0; + + /*factor Rotate*/ + factRot = scale->rotIni + (scale->rotFin - scale->rotIni) * facf0; + rad = (M_PI * factRot) / 180.0f; + s= sin(rad); + c= cos(rad); + + for (yi = 0; yi < yo; yi++) { + for (xi = 0; xi < xo; xi++) { + /*tranlate point*/ + px = xi-tx; + py = yi-ty; + + /*rotate point with center ref*/ + xaux = c*px + py*s ; + yaux = -s*px + c*py; + + /*scale point with center ref*/ + xs = xaux / factxScale; + ys = yaux / factyScale; + + /*undo reference center point */ + xs += (xo / 2.0f); + ys += (yo / 2.0f); + + /*interpolate*/ + bilinear_interpolation_transform_byte(ibuf1,out, xs,ys,x,y); + + out+=4; + } + } + +} +static void do_transform_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_transform_effect_float(seq, + facf0,x, y, + ibuf1, + out->rect_float); + } else { + do_transform_effect_byte(seq, + facf0,x, y, + (unsigned char*) ibuf1->rect, + (unsigned char*) out->rect); + } +} + /* ********************************************************************** GLOW @@ -2552,6 +2836,12 @@ struct SeqEffectHandle get_sequence_effect(Sequence * seq) rval.copy = copy_glow_effect; rval.execute = do_glow_effect; break; + case SEQ_TRANSFORM: + rval.init = init_transform_effect; + rval.free = free_transform_effect; + rval.copy = copy_transform_effect; + rval.execute = do_transform_effect; + break; case SEQ_PLUGIN: rval.init_plugin = init_plugin; rval.load = load_plugin; |