[PATCH] == Sequencer ==

This patch adds adjustment layer tracks to the sequencer and does some cleaning
up of the code.

What's an adjustment layer?

Think of it as an effect track, which takes no explicit input, but alters
the output of everything down the layer stack.

So: you can add several stages of color correction with it.

And: you can even use it with metastrips to group several adjustments together.
This commit is contained in:
2011-05-16 17:14:47 +00:00
parent b434e7f933
commit 70b832589a
10 changed files with 164 additions and 79 deletions

View File

@@ -213,6 +213,7 @@ class SEQUENCER_MT_add_effect(bpy.types.Menu):
layout.operator("sequencer.effect_strip_add", text="Color").type = 'COLOR'
layout.operator("sequencer.effect_strip_add", text="Speed Control").type = 'SPEED'
layout.operator("sequencer.effect_strip_add", text="Multicam Selector").type = 'MULTICAM'
layout.operator("sequencer.effect_strip_add", text="Adjustment Layer").type = 'ADJUSTMENT'
class SEQUENCER_MT_strip(bpy.types.Menu):
@@ -391,7 +392,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, bpy.types.Panel):
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'PLUGIN',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED',
'MULTICAM'}
'MULTICAM', 'ADJUSTMENT'}
def draw(self, context):
layout = self.layout
@@ -530,7 +531,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, bpy.types.Panel):
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'PLUGIN',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
'MULTICAM', 'SPEED'}
'MULTICAM', 'SPEED', 'ADJUSTMENT'}
def draw(self, context):
layout = self.layout
@@ -680,7 +681,7 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, bpy.types.Panel):
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'PLUGIN',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
'MULTICAM', 'SPEED'}
'MULTICAM', 'SPEED', 'ADJUSTMENT'}
def draw(self, context):
layout = self.layout

View File

@@ -268,6 +268,10 @@ void seq_translate(struct Scene *scene, struct Sequence *seq, int delta);
void seq_sound_init(struct Scene *scene, struct Sequence *seq);
struct Sequence *seq_foreground_frame_get(struct Scene *scene, int frame);
struct ListBase *seq_seqbase(struct ListBase *seqbase, struct Sequence *seq);
struct Sequence *seq_metastrip(
ListBase * seqbase /* = ed->seqbase */,
struct Sequence * meta /* = NULL */, struct Sequence *seq);
void seq_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs);
void seq_dupe_animdata(struct Scene *scene, char *name_from, char *name_to);
int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test, struct Scene *evil_scene);

View File

@@ -2858,6 +2858,83 @@ static struct ImBuf * do_multicam(
return out;
}
/* **********************************************************************
ADJUSTMENT
********************************************************************** */
/* no effect inputs for adjustment, we use give_ibuf_seq */
static int num_inputs_adjustment(void)
{
return 0;
}
static int early_out_adjustment(struct Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
{
return -1;
}
static struct ImBuf * do_adjustment_impl(SeqRenderData context, Sequence * seq,
float cfra)
{
Editing * ed;
ListBase * seqbasep;
struct ImBuf * i = 0;
ed = context.scene->ed;
seqbasep = seq_seqbase(&ed->seqbase, seq);
if (seq->machine > 0) {
i = give_ibuf_seqbase(context, cfra,
seq->machine - 1, seqbasep);
}
/* found nothing? so let's work the way up the metastrip stack, so
that it is possible to group a bunch of adjustment strips into
a metastrip and have that work on everything below the metastrip
*/
if (!i) {
Sequence * meta;
meta = seq_metastrip(&ed->seqbase, NULL, seq);
if (meta) {
i = do_adjustment_impl(context, meta, cfra);
}
}
return i;
}
static struct ImBuf * do_adjustment(
SeqRenderData context, Sequence *seq, float cfra,
float UNUSED(facf0), float UNUSED(facf1),
struct ImBuf *UNUSED(ibuf1), struct ImBuf *UNUSED(ibuf2),
struct ImBuf *UNUSED(ibuf3))
{
struct ImBuf * i = 0;
struct ImBuf * out;
Editing * ed;
ed = context.scene->ed;
if (!ed) {
return NULL;
}
i = do_adjustment_impl(context, seq, cfra);
if (input_have_to_preprocess(context, seq, cfra)) {
out = IMB_dupImBuf(i);
IMB_freeImBuf(i);
} else {
out = i;
}
return out;
}
/* **********************************************************************
SPEED
********************************************************************** */
@@ -3256,6 +3333,11 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
rval.early_out = early_out_multicam;
rval.execute = do_multicam;
break;
case SEQ_ADJUSTMENT:
rval.num_inputs = num_inputs_adjustment;
rval.early_out = early_out_adjustment;
rval.execute = do_adjustment;
break;
}
return rval;

View File

@@ -79,9 +79,15 @@
#define snprintf _snprintf
#endif
/* **** XXX ******** */
//static void waitcursor(int val) {}
//static int blender_test_break() {return 0;}
static ImBuf* seq_render_strip_stack(
SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown);
static ImBuf * seq_render_strip(
SeqRenderData context, Sequence * seq, float cfra);
static void seq_free_animdata(Scene *scene, Sequence *seq);
/* **** XXX ******** */
#define SELECT 1
@@ -177,8 +183,6 @@ void seq_free_strip(Strip *strip)
MEM_freeN(strip);
}
static void seq_free_animdata(Scene *scene, Sequence *seq);
void seq_free_sequence(Scene *scene, Sequence *seq)
{
if(seq->strip) seq_free_strip(seq->strip);
@@ -191,6 +195,10 @@ void seq_free_sequence(Scene *scene, Sequence *seq)
sh.free(seq);
}
if(seq->sound) {
((ID *)seq->sound)->us--;
}
/* clipboard has no scene and will never have a sound handle or be active */
if(scene) {
Editing *ed = scene->ed;
@@ -446,51 +454,6 @@ void seq_end(SeqIterator *iter)
* in metastrips!)
**********************************************************************
*/
#if 0 /* UNUSED */
static void do_seq_count(ListBase *seqbase, int *totseq)
{
Sequence *seq;
seq= seqbase->first;
while(seq) {
(*totseq)++;
if(seq->seqbase.first) do_seq_count(&seq->seqbase, totseq);
seq= seq->next;
}
}
static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth)
{
Sequence *seq;
seq= seqbase->first;
while(seq) {
seq->depth= depth;
if(seq->seqbase.first) do_build_seqar(&seq->seqbase, seqar, depth+1);
**seqar= seq;
(*seqar)++;
seq= seq->next;
}
}
static void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq)
{
Sequence **tseqar;
*totseq= 0;
do_seq_count(seqbase, totseq);
if(*totseq==0) {
*seqar= NULL;
return;
}
*seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
tseqar= *seqar;
do_build_seqar(seqbase, seqar, 0);
*seqar= tseqar;
}
#endif /* UNUSED */
static void do_seq_count_cb(ListBase *seqbase, int *totseq,
int (*test_func)(Sequence * seq))
@@ -916,6 +879,7 @@ static const char *give_seqname_by_type(int type)
case SEQ_TRANSFORM: return "Transform";
case SEQ_COLOR: return "Color";
case SEQ_MULTICAM: return "Multicam";
case SEQ_ADJUSTMENT: return "Adjustment";
case SEQ_SPEED: return "Speed";
default:
return NULL;
@@ -1093,15 +1057,12 @@ static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Se
}
if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) {
if (b > 0) {
if (seq_arr[b] == NULL) {
return 0;
}
} else {
for (b = MAXSEQ; b > 0; b--) {
if (video_seq_is_rendered(seq_arr[b])) {
break;
}
if (b == 0) {
b = MAXSEQ;
}
for (; b > 0; b--) {
if (video_seq_is_rendered(seq_arr[b])) {
break;
}
}
}
@@ -2855,7 +2816,10 @@ void seq_tx_set_final_right(Sequence *seq, int val)
since they work a bit differently to normal image seq's (during transform) */
int seq_single_check(Sequence *seq)
{
return (seq->len==1 && ELEM3(seq->type, SEQ_IMAGE, SEQ_COLOR, SEQ_MULTICAM));
return (seq->len==1 && (
seq->type == SEQ_IMAGE
|| ((seq->type & SEQ_EFFECT) &&
get_sequence_effect_num_inputs(seq->type) == 0)));
}
/* check if the selected seq's reference unselected seq's */
@@ -3214,6 +3178,24 @@ ListBase *seq_seqbase(ListBase *seqbase, Sequence *seq)
return NULL;
}
Sequence *seq_metastrip(ListBase * seqbase, Sequence * meta, Sequence *seq)
{
Sequence * iseq;
for(iseq = seqbase->first; iseq; iseq = iseq->next) {
Sequence * rval;
if (seq == iseq) {
return meta;
} else if(iseq->seqbase.first &&
(rval = seq_metastrip(&iseq->seqbase, iseq, seq))) {
return rval;
}
}
return NULL;
}
int seq_swap(Sequence *seq_a, Sequence *seq_b)
{
char name[sizeof(seq_a->name)];

View File

@@ -633,12 +633,13 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
BKE_reportf(op->reports, RPT_ERROR, "Sequencer plugin \"%s\" could not load.", path);
return OPERATOR_CANCELLED;
}
}
else if (seq->type==SEQ_COLOR) {
} else if (seq->type == SEQ_COLOR) {
SolidColorVars *colvars= (SolidColorVars *)seq->effectdata;
RNA_float_get_array(op->ptr, "color", colvars->col);
seq->blend_mode= SEQ_CROSS; /* so alpha adjustment fade to the strip below */
} else if (seq->type == SEQ_ADJUSTMENT) {
seq->blend_mode= SEQ_CROSS;
}
// XXX, this conflicts with giving a channel with invoke, perhaps we should have an active channel

View File

@@ -126,6 +126,7 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[
case SEQ_OVERDROP:
case SEQ_GLOW:
case SEQ_MULTICAM:
case SEQ_ADJUSTMENT:
UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
/* slightly offset hue to distinguish different effects */
@@ -137,6 +138,8 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[
if (seq->type == SEQ_OVERDROP) rgb_byte_set_hue_float_offset(col,0.24);
if (seq->type == SEQ_GLOW) rgb_byte_set_hue_float_offset(col,0.28);
if (seq->type == SEQ_TRANSFORM) rgb_byte_set_hue_float_offset(col,0.36);
if (seq->type == SEQ_MULTICAM) rgb_byte_set_hue_float_offset(col,0.32);
if (seq->type == SEQ_ADJUSTMENT) rgb_byte_set_hue_float_offset(col,0.40);
break;
case SEQ_COLOR:
@@ -476,7 +479,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
if(name[0]=='\0')
name= give_seqname(seq);
if(seq->type == SEQ_META) {
if(seq->type == SEQ_META || seq->type == SEQ_ADJUSTMENT) {
sprintf(str, "%d | %s", seq->len, name);
}
else if(seq->type == SEQ_SCENE) {

View File

@@ -100,6 +100,7 @@ EnumPropertyItem sequencer_prop_effect_types[] = {
{SEQ_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
{SEQ_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
{SEQ_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -406,6 +407,7 @@ int event_to_efftype(int event)
if(event==15) return SEQ_TRANSFORM;
if(event==16) return SEQ_COLOR;
if(event==17) return SEQ_SPEED;
if(event==18) return SEQ_ADJUSTMENT;
return 0;
}
@@ -517,7 +519,8 @@ static void change_sequence(Scene *scene)
"|Glow%x14"
"|Transform%x15"
"|Color Generator%x16"
"|Speed Control%x17");
"|Speed Control%x17"
"|Adjustment Layer%x18");
if(event > 0) {
if(event==1) {
SWAP(Sequence *,last_seq->seq1,last_seq->seq2);
@@ -703,15 +706,9 @@ static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short de
while(seq) {
seqn= seq->next;
if((seq->flag & flag) || deleteall) {
if(seq->type==SEQ_SOUND && seq->sound) {
((ID *)seq->sound)->us--; /* TODO, could be moved into seq_free_sequence() */
}
BLI_remlink(lb, seq);
if(seq==last_seq) seq_active_set(scene, NULL);
if(seq->type==SEQ_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1);
/* if(seq->ipo) seq->ipo->id.us--; */
/* XXX, remove fcurve */
seq_free_sequence(scene, seq);
}
seq= seqn;
@@ -1706,11 +1703,6 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
if (nothingSelected)
return OPERATOR_FINISHED;
/* free imbufs of all dependent strips */
for(seq=ed->seqbasep->first; seq; seq=seq->next)
if(seq->flag & SELECT)
update_changed_seq_and_deps(scene, seq, 1, 0);
/* for effects, try to find a replacement input */
for(seq=ed->seqbasep->first; seq; seq=seq->next)
if((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT))

View File

@@ -310,7 +310,8 @@ typedef struct SpeedControlVars {
#define SEQ_COLOR 28
#define SEQ_SPEED 29
#define SEQ_MULTICAM 30
#define SEQ_EFFECT_MAX 30
#define SEQ_ADJUSTMENT 31
#define SEQ_EFFECT_MAX 31
#define STRIPELEM_FAILED 0
#define STRIPELEM_OK 1

View File

@@ -53,6 +53,7 @@ extern StructRNA RNA_ActionGroup;
extern StructRNA RNA_Actuator;
extern StructRNA RNA_ActuatorSensor;
extern StructRNA RNA_Addon;
extern StructRNA RNA_AdjustmentSequence;
extern StructRNA RNA_AlwaysSensor;
extern StructRNA RNA_AndController;
extern StructRNA RNA_AnimData;

View File

@@ -387,6 +387,8 @@ static StructRNA* rna_Sequence_refine(struct PointerRNA *ptr)
return &RNA_EffectSequence;
case SEQ_MULTICAM:
return &RNA_MulticamSequence;
case SEQ_ADJUSTMENT:
return &RNA_AdjustmentSequence;
case SEQ_PLUGIN:
return &RNA_PluginSequence;
case SEQ_WIPE:
@@ -844,6 +846,7 @@ static void rna_def_sequence(BlenderRNA *brna)
{SEQ_COLOR, "COLOR", 0, "Color", ""},
{SEQ_SPEED, "SPEED", 0, "Speed", ""},
{SEQ_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem blend_mode_items[]= {
@@ -1371,6 +1374,20 @@ static void rna_def_multicam(BlenderRNA *brna)
rna_def_input(srna);
}
static void rna_def_adjustment(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "AdjustmentSequence", "Sequence");
RNA_def_struct_ui_text(srna, "Adjustment Layer Sequence", "Sequence strip to perform filter adjustments to layers below");
RNA_def_struct_sdna(srna, "Sequence");
rna_def_filter_video(srna);
rna_def_proxy(srna);
rna_def_input(srna);
}
static void rna_def_plugin(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1620,6 +1637,7 @@ void RNA_def_sequencer(BlenderRNA *brna)
rna_def_sound(brna);
rna_def_effect(brna);
rna_def_multicam(brna);
rna_def_adjustment(brna);
rna_def_plugin(brna);
rna_def_wipe(brna);
rna_def_glow(brna);