[PATCH] == Sequencer ==
authorPeter Schlaile <peter@schlaile.de>
Mon, 16 May 2011 17:14:47 +0000 (17:14 +0000)
committerPeter Schlaile <peter@schlaile.de>
Mon, 16 May 2011 17:14:47 +0000 (17:14 +0000)
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.

release/scripts/startup/bl_ui/space_sequencer.py
source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/intern/seqeffects.c
source/blender/blenkernel/intern/sequencer.c
source/blender/editors/space_sequencer/sequencer_add.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_sequencer.c

index 2079aef640212315b1bff18a9aeace0c39cdf61b..858c619d3c14bd52045837aaccbb9470d46fc957 100644 (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
index 57829e957f7793d1a7ba85b02de171559f4edd17..94c474c668fd34c19a5bf907a34ab87a785f9a68 100644 (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);
index 6f49155c0fd2945af5e45d675a095cbe6bd5962d..d2f05a8ca530a78cd6fe94d45dae8708d379b94e 100644 (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;
index e3639dd1c51279fe5002818b61e34b8655ff573d..b0da40bf0c51b74689403f4df0c6e6307b4959ee 100644 (file)
 #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)];
index 77901f7fd293ffcf7daf1789fa136c9effa4331d..ad0d0048388e798e09b43d8645146ec64a472c47 100644 (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
index 2f95e8fa64c2d6f5036a93c5a24eb2e0f3015ce5..f351d52db07f11e916962365504b1ee74e341ecb 100644 (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) {
index 6d74ba07005c6cf7207c65a9c021217360d96431..880f285c3e30eb66ee5360f04615169120f8b30a 100644 (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))
index 22f0c23ea9bc4213d88bf21d8acb47d05680c752..f89cc9d518a27b3ad7c5ca9a93692f4028ebef9a 100644 (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
index 5b42e01989ec0705e68a22563a1d463f69de170c..4672a77bd065ab244da82a79ec1c3101ce313199 100644 (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;
index 34963e9507f9fe9dcaa3b70b02852c5b0e43ec05..ef42d795f40a56f6dcf466c81df05f7ef550872b 100644 (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);