Sequencer: nested scene strip support (like metas)
This makes it possible to use scenes as a kind of multi-user meta-strip (with their own time). Currently this supports rendering & drawing nested strips, but no convenient way to tab-enter into a scene strip.
This commit is contained in:
parent
456fdaba67
commit
485ea4353f
Notes:
blender-bot
2023-02-14 10:35:28 +01:00
Referenced by issue #102514, No Camera Found in Scene - Not True Referenced by issue #46800, Nesting video strips from another scene
|
@ -827,11 +827,13 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
|
|||
layout.template_ID(strip, "scene")
|
||||
|
||||
scene = strip.scene
|
||||
layout.prop(strip, "use_sequence")
|
||||
|
||||
layout.label(text="Camera Override")
|
||||
layout.template_ID(strip, "scene_camera")
|
||||
if not strip.use_sequence:
|
||||
layout.label(text="Camera Override")
|
||||
layout.template_ID(strip, "scene_camera")
|
||||
|
||||
layout.prop(strip, "use_grease_pencil", text="Show Grease Pencil")
|
||||
layout.prop(strip, "use_grease_pencil", text="Show Grease Pencil")
|
||||
|
||||
if scene:
|
||||
layout.prop(scene, "audio_volume", text="Audio Volume")
|
||||
|
|
|
@ -237,6 +237,7 @@ void BKE_sequencer_base_clipboard_pointers_restore(struct ListBase *seqbase, str
|
|||
void BKE_sequence_free(struct Scene *scene, struct Sequence *seq);
|
||||
void BKE_sequence_free_anim(struct Sequence *seq);
|
||||
const char *BKE_sequence_give_name(struct Sequence *seq);
|
||||
ListBase *BKE_sequence_seqbase_get(struct Sequence *seq, int *r_offset);
|
||||
void BKE_sequence_calc(struct Scene *scene, struct Sequence *seq);
|
||||
void BKE_sequence_calc_disp(struct Scene *scene, struct Sequence *seq);
|
||||
void BKE_sequence_reload_new_file(struct Scene *scene, struct Sequence *seq, const bool lock_range);
|
||||
|
|
|
@ -91,6 +91,8 @@
|
|||
# include AUD_SPECIAL_H
|
||||
#endif
|
||||
|
||||
#define USE_SCENE_RECURSIVE_HACK
|
||||
|
||||
static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seqbasep, float cfra, int chanshown);
|
||||
static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, float cfra);
|
||||
static void seq_free_animdata(Scene *scene, Sequence *seq);
|
||||
|
@ -1149,6 +1151,33 @@ const char *BKE_sequence_give_name(Sequence *seq)
|
|||
return name;
|
||||
}
|
||||
|
||||
ListBase *BKE_sequence_seqbase_get(Sequence *seq, int *r_offset)
|
||||
{
|
||||
ListBase *seqbase = NULL;
|
||||
|
||||
switch (seq->type) {
|
||||
case SEQ_TYPE_META:
|
||||
{
|
||||
seqbase = &seq->seqbase;
|
||||
*r_offset = seq->start;
|
||||
break;
|
||||
}
|
||||
case SEQ_TYPE_SCENE:
|
||||
{
|
||||
if (seq->flag & SEQ_SCENE_STRIPS) {
|
||||
Editing *ed = BKE_sequencer_editing_get(seq->scene, false);
|
||||
if (ed) {
|
||||
seqbase = &ed->seqbase;
|
||||
*r_offset = seq->scene->r.sfra;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return seqbase;
|
||||
}
|
||||
|
||||
/*********************** DO THE SEQUENCE *************************/
|
||||
|
||||
static void make_black_ibuf(ImBuf *ibuf)
|
||||
|
@ -3319,6 +3348,40 @@ finally:
|
|||
return ibuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for meta-strips & scenes with #SEQ_SCENE_STRIPS flag set.
|
||||
*/
|
||||
static ImBuf *do_render_strip_seqbase(
|
||||
const SeqRenderData *context, Sequence *seq, float nr,
|
||||
bool use_preprocess)
|
||||
{
|
||||
ImBuf *meta_ibuf = NULL, *ibuf = NULL;
|
||||
ListBase *seqbase = NULL;
|
||||
int offset;
|
||||
|
||||
seqbase = BKE_sequence_seqbase_get(seq, &offset);
|
||||
|
||||
if (seqbase && !BLI_listbase_is_empty(seqbase)) {
|
||||
meta_ibuf = seq_render_strip_stack(
|
||||
context, seqbase,
|
||||
/* scene strips don't have their start taken into account */
|
||||
nr + offset, 0);
|
||||
}
|
||||
|
||||
if (meta_ibuf) {
|
||||
ibuf = meta_ibuf;
|
||||
if (ibuf && use_preprocess) {
|
||||
ImBuf *i = IMB_dupImBuf(ibuf);
|
||||
|
||||
IMB_freeImBuf(ibuf);
|
||||
|
||||
ibuf = i;
|
||||
}
|
||||
}
|
||||
|
||||
return ibuf;
|
||||
}
|
||||
|
||||
static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *seq, float cfra)
|
||||
{
|
||||
ImBuf *ibuf = NULL;
|
||||
|
@ -3329,22 +3392,38 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s
|
|||
switch (type) {
|
||||
case SEQ_TYPE_META:
|
||||
{
|
||||
ImBuf *meta_ibuf = NULL;
|
||||
ibuf = do_render_strip_seqbase(context, seq, nr, use_preprocess);
|
||||
break;
|
||||
}
|
||||
|
||||
if (seq->seqbase.first)
|
||||
meta_ibuf = seq_render_strip_stack(context, &seq->seqbase, seq->start + nr, 0);
|
||||
case SEQ_TYPE_SCENE:
|
||||
{
|
||||
if (seq->flag & SEQ_SCENE_STRIPS) {
|
||||
if (seq->scene && (context->scene != seq->scene)) {
|
||||
#ifdef USE_SCENE_RECURSIVE_HACK
|
||||
/* weak recusrive check, same as T32017 */
|
||||
if (seq->scene->id.flag & LIB_DOIT) {
|
||||
break;
|
||||
}
|
||||
seq->scene->id.flag |= LIB_DOIT;
|
||||
#endif
|
||||
|
||||
if (meta_ibuf) {
|
||||
ibuf = meta_ibuf;
|
||||
if (ibuf && use_preprocess) {
|
||||
ImBuf *i = IMB_dupImBuf(ibuf);
|
||||
ibuf = do_render_strip_seqbase(context, seq, nr, use_preprocess);
|
||||
|
||||
IMB_freeImBuf(ibuf);
|
||||
|
||||
ibuf = i;
|
||||
#ifdef USE_SCENE_RECURSIVE_HACK
|
||||
seq->scene->id.flag &= ~LIB_DOIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* scene can be NULL after deletions */
|
||||
ibuf = seq_render_scene_strip(context, seq, nr, cfra);
|
||||
|
||||
/* Scene strips update all animation, so we need to restore original state.*/
|
||||
BKE_animsys_evaluate_all_animation(context->bmain, context->scene, cfra);
|
||||
|
||||
copy_to_ibuf_still(context, seq, nr, ibuf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3395,18 +3474,6 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s
|
|||
break;
|
||||
}
|
||||
|
||||
case SEQ_TYPE_SCENE:
|
||||
{
|
||||
/* scene can be NULL after deletions */
|
||||
ibuf = seq_render_scene_strip(context, seq, nr, cfra);
|
||||
|
||||
/* Scene strips update all animation, so we need to restore original state.*/
|
||||
BKE_animsys_evaluate_all_animation(context->bmain, context->scene, cfra);
|
||||
|
||||
copy_to_ibuf_still(context, seq, nr, ibuf);
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_TYPE_MOVIECLIP:
|
||||
{
|
||||
ibuf = seq_render_movieclip_strip(context, seq, nr);
|
||||
|
@ -3731,6 +3798,10 @@ ImBuf *BKE_sequencer_give_ibuf(const SeqRenderData *context, float cfra, int cha
|
|||
seqbasep = ed->seqbasep;
|
||||
}
|
||||
|
||||
#ifdef USE_SCENE_RECURSIVE_HACK
|
||||
BKE_main_id_tag_idcode(context->bmain, ID_SCE, false);
|
||||
#endif
|
||||
|
||||
return seq_render_strip_stack(context, seqbasep, cfra, chanshown);
|
||||
}
|
||||
|
||||
|
|
|
@ -301,6 +301,20 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
|
|||
int chan_range = 0;
|
||||
float draw_range = y2 - y1;
|
||||
float draw_height;
|
||||
ListBase *seqbase;
|
||||
int offset;
|
||||
|
||||
seqbase = BKE_sequence_seqbase_get(seqm, &offset);
|
||||
if (!seqbase || BLI_listbase_is_empty(seqbase)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (seqm->type == SEQ_TYPE_SCENE) {
|
||||
offset = seqm->start - offset;
|
||||
}
|
||||
else {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
@ -308,7 +322,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
|
|||
if (seqm->flag & SEQ_MUTE)
|
||||
drawmeta_stipple(1);
|
||||
|
||||
for (seq = seqm->seqbase.first; seq; seq = seq->next) {
|
||||
for (seq = seqbase->first; seq; seq = seq->next) {
|
||||
chan_min = min_ii(chan_min, seq->machine);
|
||||
chan_max = max_ii(chan_max, seq->machine);
|
||||
}
|
||||
|
@ -318,11 +332,14 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
|
|||
|
||||
col[3] = 196; /* alpha, used for all meta children */
|
||||
|
||||
for (seq = seqm->seqbase.first; seq; seq = seq->next) {
|
||||
if ((seq->startdisp > x2 || seq->enddisp < x1) == 0) {
|
||||
for (seq = seqbase->first; seq; seq = seq->next) {
|
||||
const int startdisp = seq->startdisp + offset;
|
||||
const int enddisp = seq->enddisp + offset;
|
||||
|
||||
if ((startdisp > x2 || enddisp < x1) == 0) {
|
||||
float y_chan = (seq->machine - chan_min) / (float)(chan_range) * draw_range;
|
||||
float x1_chan = seq->startdisp;
|
||||
float x2_chan = seq->enddisp;
|
||||
float x1_chan = startdisp;
|
||||
float x2_chan = enddisp;
|
||||
float y1_chan, y2_chan;
|
||||
|
||||
if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE))
|
||||
|
@ -830,7 +847,9 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
|
|||
glDisable(GL_LINE_STIPPLE);
|
||||
}
|
||||
|
||||
if (seq->type == SEQ_TYPE_META) {
|
||||
if ((seq->type == SEQ_TYPE_META) ||
|
||||
((seq->type == SEQ_TYPE_SCENE) && (seq->flag & SEQ_SCENE_STRIPS)))
|
||||
{
|
||||
drawmeta_contents(scene, seq, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
|
|
|
@ -417,6 +417,9 @@ enum {
|
|||
SEQ_SCENE_NO_GPENCIL = (1 << 28),
|
||||
SEQ_USE_VIEWS = (1 << 29),
|
||||
|
||||
/* access scene strips directly (like a metastrip) */
|
||||
SEQ_SCENE_STRIPS = (1 << 30),
|
||||
|
||||
SEQ_INVALID_EFFECT = (1 << 31),
|
||||
};
|
||||
|
||||
|
|
|
@ -1901,7 +1901,12 @@ static void rna_def_scene(BlenderRNA *brna)
|
|||
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Camera_object_poll");
|
||||
RNA_def_property_ui_text(prop, "Camera Override", "Override the scenes active camera");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
|
||||
|
||||
|
||||
prop = RNA_def_property(srna, "use_sequence", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SCENE_STRIPS);
|
||||
RNA_def_property_ui_text(prop, "Use Sequence", "Use scenes sequence strips directly, instead of rendering");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_grease_pencil", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_SCENE_NO_GPENCIL);
|
||||
RNA_def_property_ui_text(prop, "Use Grease Pencil", "Show Grease Pencil strokes in OpenGL previews");
|
||||
|
|
|
@ -2832,6 +2832,8 @@ static bool check_valid_camera_multiview(Scene *scene, Object *camera, ReportLis
|
|||
|
||||
static int check_valid_camera(Scene *scene, Object *camera_override, ReportList *reports)
|
||||
{
|
||||
const char *err_msg = "No camera found in scene \"%s\"";
|
||||
|
||||
if (camera_override == NULL && scene->camera == NULL)
|
||||
scene->camera = BKE_scene_camera_find(scene);
|
||||
|
||||
|
@ -2843,14 +2845,17 @@ static int check_valid_camera(Scene *scene, Object *camera_override, ReportList
|
|||
Sequence *seq = scene->ed->seqbase.first;
|
||||
|
||||
while (seq) {
|
||||
if (seq->type == SEQ_TYPE_SCENE && seq->scene) {
|
||||
if ((seq->type == SEQ_TYPE_SCENE) &&
|
||||
((seq->flag & SEQ_SCENE_STRIPS) == 0) &&
|
||||
(seq->scene != NULL))
|
||||
{
|
||||
if (!seq->scene_camera) {
|
||||
if (!seq->scene->camera && !BKE_scene_camera_find(seq->scene)) {
|
||||
/* camera could be unneeded due to composite nodes */
|
||||
Object *override = (seq->scene == scene) ? camera_override : NULL;
|
||||
|
||||
if (!check_valid_compositing_camera(seq->scene, override)) {
|
||||
BKE_reportf(reports, RPT_ERROR, "No camera found in scene \"%s\"", seq->scene->id.name+2);
|
||||
BKE_reportf(reports, RPT_ERROR, err_msg, seq->scene->id.name + 2);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2864,7 +2869,7 @@ static int check_valid_camera(Scene *scene, Object *camera_override, ReportList
|
|||
}
|
||||
}
|
||||
else if (!check_valid_compositing_camera(scene, camera_override)) {
|
||||
BKE_report(reports, RPT_ERROR, "No camera found in scene");
|
||||
BKE_reportf(reports, RPT_ERROR, err_msg, scene->id.name + 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue