VSE: Refactor VSE strip loading code
Isolate RNA and operator logic from functions that create strips. - Operator specific code was removed from `SeqLoadInfo` structure and `SEQ_add_*` functions. - Strip loading code was removed from RNA and operator functions. - `SEQ_add_*` API was unified to work on `SeqLoadData` struct. Only exception is image strip, which require files to be loaded separately to strip creation itself. This is not ideal, but I think it's acceptable. - Some functions and variables were refactored so the code reads better. There are minor functional changes (coincidental bugfixes): - Operator errors are reported per-strip. Previously they were not reported at all? - `new_sound()` RNA API function now create sound with length of 1 if source file does not exist. Previously it created strip with length of 0. - Replace selection operator property wasn't working correctly. Fixed in this patch. Reviewed By: sergey Differential Revision: https://developer.blender.org/D9760
This commit is contained in:
parent
b279fef85d
commit
bbb1936411
Notes:
blender-bot
2023-02-14 04:40:22 +01:00
Referenced by commit787350dde8
, Fix T90737: VSE adding nested strips could have non-unique names Referenced by commitf65a3172a8
, Fix issues introduced strip loading refactoring Referenced by issue #90737, Effect Strip added to a nested Metastrip gets duplicate name (thus inherits fcurves from other Strips)
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "DNA_mask_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_sound_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_lib_id.h"
|
||||
|
@ -44,6 +45,8 @@
|
|||
#include "BKE_movieclip.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
|
@ -89,8 +92,6 @@ typedef struct SequencerAddData {
|
|||
#define SEQPROP_NOCHAN (1 << 3)
|
||||
#define SEQPROP_FIT_METHOD (1 << 4)
|
||||
|
||||
#define SELECT 1
|
||||
|
||||
static const EnumPropertyItem scale_fit_methods[] = {
|
||||
{SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image to fit within the canvas"},
|
||||
{SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image to completely fill the canvas"},
|
||||
|
@ -216,7 +217,7 @@ static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, i
|
|||
}
|
||||
}
|
||||
|
||||
static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperator *op)
|
||||
static void load_data_init_from_operator(SeqLoadData *load_data, bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
|
@ -224,69 +225,56 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato
|
|||
const bool relative = (prop = RNA_struct_find_property(op->ptr, "relative_path")) &&
|
||||
RNA_property_boolean_get(op->ptr, prop);
|
||||
int is_file = -1;
|
||||
memset(seq_load, 0, sizeof(SeqLoadInfo));
|
||||
memset(load_data, 0, sizeof(SeqLoadData));
|
||||
|
||||
seq_load->start_frame = RNA_int_get(op->ptr, "frame_start");
|
||||
seq_load->end_frame = seq_load->start_frame;
|
||||
seq_load->channel = RNA_int_get(op->ptr, "channel");
|
||||
seq_load->len = 1;
|
||||
seq_load->fit_method = RNA_enum_get(op->ptr, "fit_method");
|
||||
SEQ_tool_settings_fit_method_set(CTX_data_scene(C), seq_load->fit_method);
|
||||
load_data->start_frame = RNA_int_get(op->ptr, "frame_start");
|
||||
load_data->channel = RNA_int_get(op->ptr, "channel");
|
||||
load_data->image.end_frame = load_data->start_frame;
|
||||
load_data->image.len = 1;
|
||||
load_data->fit_method = RNA_enum_get(op->ptr, "fit_method");
|
||||
SEQ_tool_settings_fit_method_set(CTX_data_scene(C), load_data->fit_method);
|
||||
|
||||
if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
|
||||
/* Full path, file is set by the caller. */
|
||||
RNA_property_string_get(op->ptr, prop, seq_load->path);
|
||||
RNA_property_string_get(op->ptr, prop, load_data->path);
|
||||
is_file = 1;
|
||||
}
|
||||
else if ((prop = RNA_struct_find_property(op->ptr, "directory"))) {
|
||||
/* Full path, file is set by the caller. */
|
||||
RNA_property_string_get(op->ptr, prop, seq_load->path);
|
||||
RNA_property_string_get(op->ptr, prop, load_data->path);
|
||||
is_file = 0;
|
||||
}
|
||||
|
||||
if ((is_file != -1) && relative) {
|
||||
BLI_path_rel(seq_load->path, BKE_main_blendfile_path(bmain));
|
||||
BLI_path_rel(load_data->path, BKE_main_blendfile_path(bmain));
|
||||
}
|
||||
|
||||
if ((prop = RNA_struct_find_property(op->ptr, "frame_end"))) {
|
||||
seq_load->end_frame = RNA_property_int_get(op->ptr, prop);
|
||||
}
|
||||
|
||||
if ((prop = RNA_struct_find_property(op->ptr, "replace_sel")) &&
|
||||
RNA_property_boolean_get(op->ptr, prop)) {
|
||||
seq_load->flag |= SEQ_LOAD_REPLACE_SEL;
|
||||
load_data->image.end_frame = RNA_property_int_get(op->ptr, prop);
|
||||
}
|
||||
|
||||
if ((prop = RNA_struct_find_property(op->ptr, "cache")) &&
|
||||
RNA_property_boolean_get(op->ptr, prop)) {
|
||||
seq_load->flag |= SEQ_LOAD_SOUND_CACHE;
|
||||
load_data->flags |= SEQ_LOAD_SOUND_CACHE;
|
||||
}
|
||||
|
||||
if ((prop = RNA_struct_find_property(op->ptr, "mono")) &&
|
||||
RNA_property_boolean_get(op->ptr, prop)) {
|
||||
seq_load->flag |= SEQ_LOAD_SOUND_MONO;
|
||||
}
|
||||
|
||||
if ((prop = RNA_struct_find_property(op->ptr, "sound")) &&
|
||||
RNA_property_boolean_get(op->ptr, prop)) {
|
||||
seq_load->flag |= SEQ_LOAD_MOVIE_SOUND;
|
||||
load_data->flags |= SEQ_LOAD_SOUND_MONO;
|
||||
}
|
||||
|
||||
if ((prop = RNA_struct_find_property(op->ptr, "use_framerate")) &&
|
||||
RNA_property_boolean_get(op->ptr, prop)) {
|
||||
seq_load->flag |= SEQ_LOAD_SYNC_FPS;
|
||||
load_data->flags |= SEQ_LOAD_MOVIE_SYNC_FPS;
|
||||
}
|
||||
|
||||
/* Create consecutive array of strips. */
|
||||
seq_load->flag |= SEQ_LOAD_FRAME_ADVANCE;
|
||||
|
||||
if (is_file == 1) {
|
||||
BLI_strncpy(seq_load->name, BLI_path_basename(seq_load->path), sizeof(seq_load->name));
|
||||
BLI_strncpy(load_data->name, BLI_path_basename(load_data->path), sizeof(load_data->name));
|
||||
}
|
||||
else if ((prop = RNA_struct_find_property(op->ptr, "files"))) {
|
||||
RNA_PROP_BEGIN (op->ptr, itemptr, prop) {
|
||||
char *name = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
|
||||
BLI_strncpy(seq_load->name, name, sizeof(seq_load->name));
|
||||
BLI_strncpy(load_data->name, name, sizeof(load_data->name));
|
||||
MEM_freeN(name);
|
||||
break;
|
||||
}
|
||||
|
@ -299,21 +287,27 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato
|
|||
SequencerAddData *sad = op->customdata;
|
||||
ImageFormatData *imf = &sad->im_format;
|
||||
|
||||
seq_load->views_format = imf->views_format;
|
||||
seq_load->flag |= SEQ_USE_VIEWS;
|
||||
seq_load->stereo3d_format = &imf->stereo3d_format;
|
||||
load_data->use_multiview = true;
|
||||
load_data->views_format = imf->views_format;
|
||||
load_data->stereo3d_format = &imf->stereo3d_format;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply generic operator options.
|
||||
*/
|
||||
static void sequencer_add_apply_overlap(bContext *C, wmOperator *op, Sequence *seq)
|
||||
static void seq_load_apply_generic_options(bContext *C, wmOperator *op, Sequence *seq)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene, false);
|
||||
|
||||
if (seq == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (RNA_boolean_get(op->ptr, "replace_sel")) {
|
||||
seq->flag |= SELECT;
|
||||
SEQ_select_active_set(scene, seq);
|
||||
}
|
||||
|
||||
if (RNA_boolean_get(op->ptr, "overlap") == false) {
|
||||
if (SEQ_transform_test_overlap(ed->seqbasep, seq)) {
|
||||
SEQ_transform_seqbase_shuffle(ed->seqbasep, seq, scene);
|
||||
|
@ -321,17 +315,6 @@ static void sequencer_add_apply_overlap(bContext *C, wmOperator *op, Sequence *s
|
|||
}
|
||||
}
|
||||
|
||||
static void sequencer_add_apply_replace_sel(bContext *C, wmOperator *op, Sequence *seq)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
if (RNA_boolean_get(op->ptr, "replace_sel")) {
|
||||
ED_sequencer_deselect_all(scene);
|
||||
SEQ_select_active_set(scene, seq);
|
||||
seq->flag |= SELECT;
|
||||
}
|
||||
}
|
||||
|
||||
static bool seq_effect_add_properties_poll(const bContext *UNUSED(C),
|
||||
wmOperator *op,
|
||||
const PropertyRNA *prop)
|
||||
|
@ -356,34 +339,24 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
|
|||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene, true);
|
||||
Scene *sce_seq;
|
||||
Sequence *seq;
|
||||
|
||||
int start_frame, channel;
|
||||
start_frame = RNA_int_get(op->ptr, "frame_start");
|
||||
channel = RNA_int_get(op->ptr, "channel");
|
||||
sce_seq = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene"));
|
||||
const Editing *ed = SEQ_editing_get(scene, true);
|
||||
Scene *sce_seq = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene"));
|
||||
|
||||
if (sce_seq == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Scene not found");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_SCENE);
|
||||
seq->blend_mode = SEQ_TYPE_CROSS;
|
||||
seq->scene = sce_seq;
|
||||
seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
|
||||
if (RNA_boolean_get(op->ptr, "replace_sel")) {
|
||||
ED_sequencer_deselect_all(scene);
|
||||
}
|
||||
|
||||
BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2);
|
||||
SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
|
||||
SeqLoadData load_data;
|
||||
load_data_init_from_operator(&load_data, C, op);
|
||||
load_data.scene = sce_seq;
|
||||
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
SEQ_sort(scene);
|
||||
|
||||
sequencer_add_apply_replace_sel(C, op, seq);
|
||||
sequencer_add_apply_overlap(C, op, seq);
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
Sequence *seq = SEQ_add_scene_strip(scene, ed->seqbasep, &load_data);
|
||||
seq_load_apply_generic_options(C, op, seq);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
DEG_relations_tag_update(bmain);
|
||||
|
@ -430,36 +403,24 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
|
|||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene, true);
|
||||
MovieClip *clip;
|
||||
Sequence *seq;
|
||||
|
||||
int start_frame, channel;
|
||||
start_frame = RNA_int_get(op->ptr, "frame_start");
|
||||
channel = RNA_int_get(op->ptr, "channel");
|
||||
clip = BLI_findlink(&bmain->movieclips, RNA_enum_get(op->ptr, "clip"));
|
||||
const Editing *ed = SEQ_editing_get(scene, true);
|
||||
MovieClip *clip = BLI_findlink(&bmain->movieclips, RNA_enum_get(op->ptr, "clip"));
|
||||
|
||||
if (clip == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Movie clip not found");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MOVIECLIP);
|
||||
seq->blend_mode = SEQ_TYPE_CROSS;
|
||||
seq->clip = clip;
|
||||
seq->len = BKE_movieclip_get_duration(clip);
|
||||
if (RNA_boolean_get(op->ptr, "replace_sel")) {
|
||||
ED_sequencer_deselect_all(scene);
|
||||
}
|
||||
|
||||
id_us_ensure_real(&seq->clip->id);
|
||||
SeqLoadData load_data;
|
||||
load_data_init_from_operator(&load_data, C, op);
|
||||
load_data.clip = clip;
|
||||
|
||||
BLI_strncpy(seq->name + 2, clip->id.name + 2, sizeof(seq->name) - 2);
|
||||
SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
|
||||
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
SEQ_sort(scene);
|
||||
|
||||
sequencer_add_apply_replace_sel(C, op, seq);
|
||||
sequencer_add_apply_overlap(C, op, seq);
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
Sequence *seq = SEQ_add_movieclip_strip(scene, ed->seqbasep, &load_data);
|
||||
seq_load_apply_generic_options(C, op, seq);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
@ -506,36 +467,24 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
|
|||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene, true);
|
||||
Mask *mask;
|
||||
Sequence *seq;
|
||||
|
||||
int start_frame, channel;
|
||||
start_frame = RNA_int_get(op->ptr, "frame_start");
|
||||
channel = RNA_int_get(op->ptr, "channel");
|
||||
mask = BLI_findlink(&bmain->masks, RNA_enum_get(op->ptr, "mask"));
|
||||
const Editing *ed = SEQ_editing_get(scene, true);
|
||||
Mask *mask = BLI_findlink(&bmain->masks, RNA_enum_get(op->ptr, "mask"));
|
||||
|
||||
if (mask == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Mask not found");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, SEQ_TYPE_MASK);
|
||||
seq->blend_mode = SEQ_TYPE_CROSS;
|
||||
seq->mask = mask;
|
||||
seq->len = BKE_mask_get_duration(mask);
|
||||
if (RNA_boolean_get(op->ptr, "replace_sel")) {
|
||||
ED_sequencer_deselect_all(scene);
|
||||
}
|
||||
|
||||
id_us_ensure_real(&seq->mask->id);
|
||||
SeqLoadData load_data;
|
||||
load_data_init_from_operator(&load_data, C, op);
|
||||
load_data.mask = mask;
|
||||
|
||||
BLI_strncpy(seq->name + 2, mask->id.name + 2, sizeof(seq->name) - 2);
|
||||
SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
|
||||
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
SEQ_sort(scene);
|
||||
|
||||
sequencer_add_apply_replace_sel(C, op, seq);
|
||||
sequencer_add_apply_overlap(C, op, seq);
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
Sequence *seq = SEQ_add_mask_strip(scene, ed->seqbasep, &load_data);
|
||||
seq_load_apply_generic_options(C, op, seq);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
@ -577,75 +526,6 @@ void SEQUENCER_OT_mask_strip_add(struct wmOperatorType *ot)
|
|||
ot->prop = prop;
|
||||
}
|
||||
|
||||
static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFn seq_load_fn)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene, true);
|
||||
SeqLoadInfo seq_load;
|
||||
int tot_files;
|
||||
|
||||
seq_load_operator_info(&seq_load, C, op);
|
||||
|
||||
if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) {
|
||||
ED_sequencer_deselect_all(scene);
|
||||
}
|
||||
|
||||
tot_files = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
|
||||
|
||||
if (tot_files > 1) {
|
||||
char dir_only[FILE_MAX];
|
||||
char file_only[FILE_MAX];
|
||||
|
||||
RNA_BEGIN (op->ptr, itemptr, "files") {
|
||||
Sequence *seq;
|
||||
|
||||
RNA_string_get(op->ptr, "directory", dir_only);
|
||||
RNA_string_get(&itemptr, "name", file_only);
|
||||
BLI_join_dirfile(seq_load.path, sizeof(seq_load.path), dir_only, file_only);
|
||||
|
||||
/* Set seq_load.name, otherwise all video/audio files get the same name. */
|
||||
BLI_strncpy(seq_load.name, file_only, sizeof(seq_load.name));
|
||||
|
||||
seq = seq_load_fn(C, ed->seqbasep, &seq_load);
|
||||
if (seq) {
|
||||
if (seq_load.seq_sound) {
|
||||
sequencer_add_apply_overlap(C, op, seq_load.seq_sound);
|
||||
}
|
||||
sequencer_add_apply_overlap(C, op, seq);
|
||||
}
|
||||
}
|
||||
RNA_END;
|
||||
}
|
||||
else { /* Single file./ */
|
||||
Sequence *seq;
|
||||
seq = seq_load_fn(C, ed->seqbasep, &seq_load);
|
||||
|
||||
if (seq) {
|
||||
if (seq_load.seq_sound) {
|
||||
sequencer_add_apply_overlap(C, op, seq_load.seq_sound);
|
||||
}
|
||||
sequencer_add_apply_overlap(C, op, seq);
|
||||
}
|
||||
}
|
||||
|
||||
if (op->customdata) {
|
||||
MEM_freeN(op->customdata);
|
||||
}
|
||||
|
||||
if (seq_load.tot_success == 0) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", seq_load.path);
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
SEQ_sort(scene);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void sequencer_add_init(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
op->customdata = MEM_callocN(sizeof(SequencerAddData), __func__);
|
||||
|
@ -668,9 +548,98 @@ static bool sequencer_add_draw_check_fn(PointerRNA *UNUSED(ptr),
|
|||
return !(STR_ELEM(prop_id, "filepath", "directory", "filename"));
|
||||
}
|
||||
|
||||
static void sequencer_add_movie_multiple_strips(bContext *C,
|
||||
wmOperator *op,
|
||||
SeqLoadData *load_data)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const Editing *ed = SEQ_editing_get(scene, true);
|
||||
|
||||
RNA_BEGIN (op->ptr, itemptr, "files") {
|
||||
char dir_only[FILE_MAX];
|
||||
char file_only[FILE_MAX];
|
||||
RNA_string_get(op->ptr, "directory", dir_only);
|
||||
RNA_string_get(&itemptr, "name", file_only);
|
||||
BLI_join_dirfile(load_data->path, sizeof(load_data->path), dir_only, file_only);
|
||||
BLI_strncpy(load_data->name, file_only, sizeof(load_data->name));
|
||||
Sequence *seq_movie = NULL;
|
||||
Sequence *seq_sound = NULL;
|
||||
load_data->channel++;
|
||||
seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data);
|
||||
load_data->channel--;
|
||||
if (seq_movie == NULL) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
|
||||
}
|
||||
else {
|
||||
if (RNA_boolean_get(op->ptr, "sound")) {
|
||||
seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
|
||||
}
|
||||
load_data->start_frame += seq_movie->enddisp - seq_movie->startdisp;
|
||||
seq_load_apply_generic_options(C, op, seq_sound);
|
||||
seq_load_apply_generic_options(C, op, seq_movie);
|
||||
}
|
||||
}
|
||||
RNA_END;
|
||||
}
|
||||
|
||||
static bool sequencer_add_movie_single_strip(bContext *C, wmOperator *op, SeqLoadData *load_data)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const Editing *ed = SEQ_editing_get(scene, true);
|
||||
|
||||
Sequence *seq_movie = NULL;
|
||||
Sequence *seq_sound = NULL;
|
||||
load_data->channel++;
|
||||
seq_movie = SEQ_add_movie_strip(bmain, scene, ed->seqbasep, load_data);
|
||||
load_data->channel--;
|
||||
|
||||
if (seq_movie == NULL) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
|
||||
return false;
|
||||
}
|
||||
if (RNA_boolean_get(op->ptr, "sound")) {
|
||||
seq_sound = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
|
||||
}
|
||||
seq_load_apply_generic_options(C, op, seq_sound);
|
||||
seq_load_apply_generic_options(C, op, seq_movie);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
return sequencer_add_generic_strip_exec(C, op, SEQ_add_movie_strip);
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
SeqLoadData load_data;
|
||||
|
||||
load_data_init_from_operator(&load_data, C, op);
|
||||
|
||||
if (RNA_boolean_get(op->ptr, "replace_sel")) {
|
||||
ED_sequencer_deselect_all(scene);
|
||||
}
|
||||
|
||||
const int tot_files = RNA_property_collection_length(op->ptr,
|
||||
RNA_struct_find_property(op->ptr, "files"));
|
||||
if (tot_files > 1) {
|
||||
sequencer_add_movie_multiple_strips(C, op, &load_data);
|
||||
}
|
||||
else {
|
||||
if (!sequencer_add_movie_single_strip(C, op, &load_data)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (op->customdata) {
|
||||
MEM_freeN(op->customdata);
|
||||
}
|
||||
|
||||
DEG_relations_tag_update(bmain);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int sequencer_add_movie_strip_invoke(bContext *C,
|
||||
|
@ -681,7 +650,8 @@ static int sequencer_add_movie_strip_invoke(bContext *C,
|
|||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene, false);
|
||||
|
||||
/* Only enable "use_framerate" if there aren't any existing strips, unless overridden by user. */
|
||||
/* Only enable "use_framerate" if there aren't any existing strips, unless overridden by user.
|
||||
*/
|
||||
if (ed && ed->seqbasep && ed->seqbasep->first) {
|
||||
RNA_boolean_set(op->ptr, "use_framerate", false);
|
||||
}
|
||||
|
@ -761,9 +731,80 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
|
|||
"Use framerate from the movie to keep sound and video in sync");
|
||||
}
|
||||
|
||||
static void sequencer_add_sound_multiple_strips(bContext *C,
|
||||
wmOperator *op,
|
||||
SeqLoadData *load_data)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene, true);
|
||||
|
||||
RNA_BEGIN (op->ptr, itemptr, "files") {
|
||||
char dir_only[FILE_MAX];
|
||||
char file_only[FILE_MAX];
|
||||
RNA_string_get(op->ptr, "directory", dir_only);
|
||||
RNA_string_get(&itemptr, "name", file_only);
|
||||
BLI_join_dirfile(load_data->path, sizeof(load_data->path), dir_only, file_only);
|
||||
BLI_strncpy(load_data->name, file_only, sizeof(load_data->name));
|
||||
Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
|
||||
if (seq == NULL) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
|
||||
}
|
||||
else {
|
||||
seq_load_apply_generic_options(C, op, seq);
|
||||
load_data->start_frame += seq->enddisp - seq->startdisp;
|
||||
}
|
||||
}
|
||||
RNA_END;
|
||||
}
|
||||
|
||||
static bool sequencer_add_sound_single_strip(bContext *C, wmOperator *op, SeqLoadData *load_data)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene, true);
|
||||
|
||||
Sequence *seq = SEQ_add_sound_strip(bmain, scene, ed->seqbasep, load_data);
|
||||
if (seq == NULL) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", load_data->path);
|
||||
return false;
|
||||
}
|
||||
seq_load_apply_generic_options(C, op, seq);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
return sequencer_add_generic_strip_exec(C, op, SEQ_add_sound_strip);
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
SeqLoadData load_data;
|
||||
load_data_init_from_operator(&load_data, C, op);
|
||||
|
||||
if (RNA_boolean_get(op->ptr, "replace_sel")) {
|
||||
ED_sequencer_deselect_all(scene);
|
||||
}
|
||||
|
||||
const int tot_files = RNA_property_collection_length(op->ptr,
|
||||
RNA_struct_find_property(op->ptr, "files"));
|
||||
if (tot_files > 1) {
|
||||
sequencer_add_sound_multiple_strips(C, op, &load_data);
|
||||
}
|
||||
else {
|
||||
if (!sequencer_add_sound_single_strip(C, op, &load_data)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (op->customdata) {
|
||||
MEM_freeN(op->customdata);
|
||||
}
|
||||
|
||||
DEG_relations_tag_update(bmain);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int sequencer_add_sound_strip_invoke(bContext *C,
|
||||
|
@ -873,78 +914,86 @@ void sequencer_image_seq_reserve_frames(
|
|||
}
|
||||
}
|
||||
|
||||
static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
|
||||
static int sequencer_add_image_strip_calculate_length(wmOperator *op,
|
||||
const int start_frame,
|
||||
int *minframe,
|
||||
int *numdigits)
|
||||
{
|
||||
int minframe, numdigits;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene, true);
|
||||
SeqLoadInfo seq_load;
|
||||
Sequence *seq;
|
||||
Strip *strip;
|
||||
StripElem *se;
|
||||
const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
|
||||
|
||||
seq_load_operator_info(&seq_load, C, op);
|
||||
|
||||
/* Images are unique in how they handle this - 1 per strip elem. */
|
||||
if (use_placeholders) {
|
||||
seq_load.len = sequencer_image_seq_get_minmax_frame(
|
||||
op, seq_load.start_frame, &minframe, &numdigits);
|
||||
return sequencer_image_seq_get_minmax_frame(op, start_frame, minframe, numdigits);
|
||||
}
|
||||
else {
|
||||
seq_load.len = RNA_property_collection_length(op->ptr,
|
||||
RNA_struct_find_property(op->ptr, "files"));
|
||||
return RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
|
||||
}
|
||||
}
|
||||
|
||||
if (seq_load.len == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
static void sequencer_add_image_strip_load_files(bContext *C,
|
||||
wmOperator *op,
|
||||
Sequence *seq,
|
||||
SeqLoadData *load_data,
|
||||
const int minframe,
|
||||
const int numdigits)
|
||||
{
|
||||
const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
|
||||
|
||||
if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) {
|
||||
ED_sequencer_deselect_all(scene);
|
||||
}
|
||||
|
||||
/* Main adding function. */
|
||||
seq = SEQ_add_image_strip(C, ed->seqbasep, &seq_load);
|
||||
strip = seq->strip;
|
||||
se = strip->stripdata;
|
||||
seq->blend_mode = SEQ_TYPE_ALPHAOVER;
|
||||
SEQ_add_image_set_directory(seq, load_data->path);
|
||||
|
||||
if (use_placeholders) {
|
||||
sequencer_image_seq_reserve_frames(op, se, seq_load.len, minframe, numdigits);
|
||||
sequencer_image_seq_reserve_frames(
|
||||
op, seq->strip->stripdata, load_data->image.len, minframe, numdigits);
|
||||
}
|
||||
else {
|
||||
size_t strip_frame = 0;
|
||||
RNA_BEGIN (op->ptr, itemptr, "files") {
|
||||
char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
|
||||
BLI_strncpy(se->name, filename, sizeof(se->name));
|
||||
SEQ_add_image_load_file(seq, strip_frame, filename);
|
||||
MEM_freeN(filename);
|
||||
se++;
|
||||
strip_frame++;
|
||||
}
|
||||
RNA_END;
|
||||
}
|
||||
}
|
||||
|
||||
if (seq_load.len == 1) {
|
||||
if (seq_load.start_frame < seq_load.end_frame) {
|
||||
seq->endstill = seq_load.end_frame - seq_load.start_frame;
|
||||
}
|
||||
static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene, true);
|
||||
|
||||
SeqLoadData load_data;
|
||||
load_data_init_from_operator(&load_data, C, op);
|
||||
|
||||
int minframe, numdigits;
|
||||
load_data.image.len = sequencer_add_image_strip_calculate_length(
|
||||
op, load_data.start_frame, &minframe, &numdigits);
|
||||
if (load_data.image.len == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
SEQ_render_init_colorspace(seq);
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
SEQ_sort(scene);
|
||||
if (RNA_boolean_get(op->ptr, "replace_sel")) {
|
||||
ED_sequencer_deselect_all(scene);
|
||||
}
|
||||
|
||||
/* Last active name. */
|
||||
BLI_strncpy(ed->act_imagedir, strip->dir, sizeof(ed->act_imagedir));
|
||||
sequencer_add_apply_overlap(C, op, seq);
|
||||
Sequence *seq = SEQ_add_image_strip(CTX_data_main(C), scene, ed->seqbasep, &load_data);
|
||||
sequencer_add_image_strip_load_files(C, op, seq, &load_data, minframe, numdigits);
|
||||
SEQ_add_image_init_alpha_mode(seq);
|
||||
|
||||
/* Adjust length. */
|
||||
if (load_data.image.len == 1) {
|
||||
SEQ_transform_set_right_handle_frame(seq, load_data.image.end_frame);
|
||||
SEQ_time_update_sequence(scene, seq);
|
||||
}
|
||||
|
||||
seq_load_apply_generic_options(C, op, seq);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
if (op->customdata) {
|
||||
MEM_freeN(op->customdata);
|
||||
}
|
||||
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
@ -1016,80 +1065,46 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
|
|||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene, true);
|
||||
Sequence *seq;
|
||||
struct SeqEffectHandle sh;
|
||||
Sequence *seq1, *seq2, *seq3;
|
||||
const char *error_msg;
|
||||
int start_frame, end_frame, channel, type;
|
||||
|
||||
start_frame = RNA_int_get(op->ptr, "frame_start");
|
||||
end_frame = RNA_int_get(op->ptr, "frame_end");
|
||||
channel = RNA_int_get(op->ptr, "channel");
|
||||
type = RNA_enum_get(op->ptr, "type");
|
||||
SeqLoadData load_data;
|
||||
load_data_init_from_operator(&load_data, C, op);
|
||||
load_data.effect.type = RNA_enum_get(op->ptr, "type");
|
||||
|
||||
if (!seq_effect_find_selected(scene, NULL, type, &seq1, &seq2, &seq3, &error_msg)) {
|
||||
Sequence *seq1, *seq2, *seq3;
|
||||
if (!seq_effect_find_selected(
|
||||
scene, NULL, load_data.effect.type, &seq1, &seq2, &seq3, &error_msg)) {
|
||||
BKE_report(op->reports, RPT_ERROR, error_msg);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Check its start and end frames are valid. */
|
||||
if (seq1 == NULL && end_frame <= start_frame) {
|
||||
end_frame = start_frame + 1;
|
||||
RNA_int_set(op->ptr, "frame_end", end_frame);
|
||||
if (RNA_boolean_get(op->ptr, "replace_sel")) {
|
||||
ED_sequencer_deselect_all(scene);
|
||||
}
|
||||
|
||||
seq = SEQ_sequence_alloc(ed->seqbasep, start_frame, channel, type);
|
||||
BLI_strncpy(seq->name + 2, SEQ_sequence_give_name(seq), sizeof(seq->name) - 2);
|
||||
SEQ_sequence_base_unique_name_recursive(&ed->seqbase, seq);
|
||||
|
||||
sh = SEQ_effect_handle_get(seq);
|
||||
sh.init(seq);
|
||||
seq->seq1 = seq1;
|
||||
seq->seq2 = seq2;
|
||||
seq->seq3 = seq3;
|
||||
|
||||
if (!seq1) {
|
||||
seq->len = 1; /* Effect is generator, set non zero length. */
|
||||
SEQ_transform_set_right_handle_frame(seq, end_frame);
|
||||
}
|
||||
|
||||
seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
|
||||
SEQ_time_update_sequence(scene, seq);
|
||||
|
||||
if (seq->type == SEQ_TYPE_COLOR) {
|
||||
SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
|
||||
RNA_float_get_array(op->ptr, "color", colvars->col);
|
||||
seq->blend_mode = SEQ_TYPE_CROSS;
|
||||
}
|
||||
else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
|
||||
seq->blend_mode = SEQ_TYPE_CROSS;
|
||||
}
|
||||
else if (seq->type == SEQ_TYPE_TEXT) {
|
||||
seq->blend_mode = SEQ_TYPE_ALPHAOVER;
|
||||
}
|
||||
else if (SEQ_effect_get_num_inputs(seq->type) == 1) {
|
||||
seq->blend_mode = seq1->blend_mode;
|
||||
}
|
||||
load_data.effect.seq1 = seq1;
|
||||
load_data.effect.seq2 = seq2;
|
||||
load_data.effect.seq3 = seq3;
|
||||
|
||||
/* Set channel. If unset, use lowest free one above strips. */
|
||||
if (!RNA_struct_property_is_set(op->ptr, "channel")) {
|
||||
if (seq->seq1) {
|
||||
int chan = max_iii(seq->seq1 ? seq->seq1->machine : 0,
|
||||
seq->seq2 ? seq->seq2->machine : 0,
|
||||
seq->seq3 ? seq->seq3->machine : 0);
|
||||
if (seq1 != NULL) {
|
||||
int chan = max_iii(
|
||||
seq1 ? seq1->machine : 0, seq2 ? seq2->machine : 0, seq3 ? seq3->machine : 0);
|
||||
if (chan < MAXSEQ) {
|
||||
seq->machine = chan;
|
||||
load_data.channel = chan;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sequencer_add_apply_replace_sel(C, op, seq);
|
||||
sequencer_add_apply_overlap(C, op, seq);
|
||||
Sequence *seq = SEQ_add_effect_strip(scene, ed->seqbasep, &load_data);
|
||||
seq_load_apply_generic_options(C, op, seq);
|
||||
|
||||
SEQ_relations_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs SEQ_time_update_sequence. */
|
||||
SEQ_sort(scene);
|
||||
if (seq->type == SEQ_TYPE_COLOR) {
|
||||
SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
|
||||
RNA_float_get_array(op->ptr, "color", colvars->col);
|
||||
}
|
||||
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
# include "SEQ_add.h"
|
||||
# include "SEQ_edit.h"
|
||||
# include "SEQ_effects.h"
|
||||
# include "SEQ_relations.h"
|
||||
# include "SEQ_render.h"
|
||||
# include "SEQ_sequencer.h"
|
||||
|
@ -80,34 +81,6 @@ static void rna_Sequence_swap_internal(Sequence *seq_self,
|
|||
}
|
||||
}
|
||||
|
||||
static Sequence *alloc_generic_sequence(
|
||||
ListBase *seqbase, const char *name, int frame_start, int channel, int type, const char *file)
|
||||
{
|
||||
Sequence *seq;
|
||||
StripElem *se;
|
||||
|
||||
seq = SEQ_sequence_alloc(seqbase, frame_start, channel, type);
|
||||
|
||||
BLI_strncpy(seq->name + 2, name, sizeof(seq->name) - 2);
|
||||
SEQ_sequence_base_unique_name_recursive(seqbase, seq);
|
||||
|
||||
Strip *strip = seq->strip;
|
||||
|
||||
/* Don't allocate StripElem for clip, mask and scene types. This struct is not handled in
|
||||
* seq_dupli() function. */
|
||||
if (file && !ELEM(type, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK, SEQ_TYPE_SCENE)) {
|
||||
strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem");
|
||||
BLI_split_dirfile(file, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
|
||||
|
||||
SEQ_render_init_colorspace(seq);
|
||||
}
|
||||
else {
|
||||
strip->stripdata = NULL;
|
||||
}
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
static Sequence *rna_Sequences_new_clip(ID *id,
|
||||
ListBase *seqbase,
|
||||
Main *bmain,
|
||||
|
@ -117,15 +90,10 @@ static Sequence *rna_Sequences_new_clip(ID *id,
|
|||
int frame_start)
|
||||
{
|
||||
Scene *scene = (Scene *)id;
|
||||
Sequence *seq;
|
||||
|
||||
seq = alloc_generic_sequence(
|
||||
seqbase, name, frame_start, channel, SEQ_TYPE_MOVIECLIP, clip->filepath);
|
||||
seq->clip = clip;
|
||||
seq->len = BKE_movieclip_get_duration(clip);
|
||||
id_us_plus((ID *)clip);
|
||||
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
SeqLoadData load_data;
|
||||
SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel);
|
||||
load_data.clip = clip;
|
||||
Sequence *seq = SEQ_add_movieclip_strip(scene, seqbase, &load_data);
|
||||
|
||||
DEG_relations_tag_update(bmain);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
|
@ -165,15 +133,10 @@ static Sequence *rna_Sequences_new_mask(ID *id,
|
|||
int frame_start)
|
||||
{
|
||||
Scene *scene = (Scene *)id;
|
||||
Sequence *seq;
|
||||
|
||||
seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_MASK, mask->id.name);
|
||||
seq->mask = mask;
|
||||
seq->len = BKE_mask_get_duration(mask);
|
||||
id_us_plus((ID *)mask);
|
||||
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
SeqLoadData load_data;
|
||||
SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel);
|
||||
load_data.mask = mask;
|
||||
Sequence *seq = SEQ_add_mask_strip(scene, seqbase, &load_data);
|
||||
|
||||
DEG_relations_tag_update(bmain);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
|
@ -202,15 +165,10 @@ static Sequence *rna_Sequences_new_scene(ID *id,
|
|||
int frame_start)
|
||||
{
|
||||
Scene *scene = (Scene *)id;
|
||||
Sequence *seq;
|
||||
|
||||
seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_SCENE, NULL);
|
||||
seq->scene = sce_seq;
|
||||
seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
|
||||
id_us_plus((ID *)sce_seq);
|
||||
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
SeqLoadData load_data;
|
||||
SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel);
|
||||
load_data.scene = sce_seq;
|
||||
Sequence *seq = SEQ_add_scene_strip(scene, seqbase, &load_data);
|
||||
|
||||
DEG_relations_tag_update(bmain);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
|
@ -251,20 +209,17 @@ static Sequence *rna_Sequences_new_image(ID *id,
|
|||
int frame_start)
|
||||
{
|
||||
Scene *scene = (Scene *)id;
|
||||
Sequence *seq;
|
||||
|
||||
seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_IMAGE, file);
|
||||
seq->len = 1;
|
||||
SeqLoadData load_data;
|
||||
SEQ_add_load_data_init(&load_data, name, file, frame_start, channel);
|
||||
load_data.image.len = 1;
|
||||
Sequence *seq = SEQ_add_image_strip(bmain, scene, seqbase, &load_data);
|
||||
|
||||
if (seq->strip->stripdata->name[0] == '\0') {
|
||||
BKE_report(reports, RPT_ERROR, "Sequences.new_image: unable to open image file");
|
||||
BLI_remlink(seqbase, seq);
|
||||
SEQ_sequence_free(scene, seq, true);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
char dir[FILE_MAX], filename[FILE_MAX];
|
||||
BLI_split_dirfile(file, dir, filename, sizeof(dir), sizeof(filename));
|
||||
SEQ_add_image_set_directory(seq, dir);
|
||||
SEQ_add_image_load_file(seq, 0, filename);
|
||||
SEQ_add_image_init_alpha_mode(seq);
|
||||
|
||||
DEG_relations_tag_update(bmain);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
|
@ -299,48 +254,47 @@ static Sequence *rna_Sequences_meta_new_image(ID *id,
|
|||
id, &seq->seqbase, bmain, reports, name, file, channel, frame_start);
|
||||
}
|
||||
|
||||
static Sequence *rna_Sequences_new_movie(
|
||||
ID *id, ListBase *seqbase, const char *name, const char *file, int channel, int frame_start)
|
||||
static Sequence *rna_Sequences_new_movie(ID *id,
|
||||
ListBase *seqbase,
|
||||
Main *bmain,
|
||||
const char *name,
|
||||
const char *file,
|
||||
int channel,
|
||||
int frame_start)
|
||||
{
|
||||
Scene *scene = (Scene *)id;
|
||||
Sequence *seq;
|
||||
StripAnim *sanim;
|
||||
|
||||
seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_MOVIE, file);
|
||||
|
||||
struct anim *an = openanim(file, IB_rect, 0, NULL);
|
||||
if (an == NULL) {
|
||||
/* Without anim, the strip gets duration 0, which makes it impossible to select in the UI. */
|
||||
seq->len = 1;
|
||||
}
|
||||
else {
|
||||
sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
|
||||
BLI_addtail(&seq->anims, sanim);
|
||||
sanim->anim = an;
|
||||
|
||||
seq->anim_preseek = IMB_anim_get_preseek(an);
|
||||
seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN);
|
||||
}
|
||||
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
SeqLoadData load_data;
|
||||
SEQ_add_load_data_init(&load_data, name, file, frame_start, channel);
|
||||
load_data.allow_invalid_file = true;
|
||||
Sequence *seq = SEQ_add_movie_strip(bmain, scene, seqbase, &load_data);
|
||||
|
||||
DEG_relations_tag_update(bmain);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
static Sequence *rna_Sequences_editing_new_movie(
|
||||
ID *id, Editing *ed, const char *name, const char *file, int channel, int frame_start)
|
||||
static Sequence *rna_Sequences_editing_new_movie(ID *id,
|
||||
Editing *ed,
|
||||
Main *bmain,
|
||||
const char *name,
|
||||
const char *file,
|
||||
int channel,
|
||||
int frame_start)
|
||||
{
|
||||
return rna_Sequences_new_movie(id, &ed->seqbase, name, file, channel, frame_start);
|
||||
return rna_Sequences_new_movie(id, &ed->seqbase, bmain, name, file, channel, frame_start);
|
||||
}
|
||||
|
||||
static Sequence *rna_Sequences_meta_new_movie(
|
||||
ID *id, Sequence *seq, const char *name, const char *file, int channel, int frame_start)
|
||||
static Sequence *rna_Sequences_meta_new_movie(ID *id,
|
||||
Sequence *seq,
|
||||
Main *bmain,
|
||||
const char *name,
|
||||
const char *file,
|
||||
int channel,
|
||||
int frame_start)
|
||||
{
|
||||
return rna_Sequences_new_movie(id, &seq->seqbase, name, file, channel, frame_start);
|
||||
return rna_Sequences_new_movie(id, &seq->seqbase, bmain, name, file, channel, frame_start);
|
||||
}
|
||||
|
||||
# ifdef WITH_AUDASPACE
|
||||
|
@ -354,22 +308,15 @@ static Sequence *rna_Sequences_new_sound(ID *id,
|
|||
int frame_start)
|
||||
{
|
||||
Scene *scene = (Scene *)id;
|
||||
Sequence *seq;
|
||||
SeqLoadData load_data;
|
||||
SEQ_add_load_data_init(&load_data, name, file, frame_start, channel);
|
||||
load_data.allow_invalid_file = true;
|
||||
Sequence *seq = SEQ_add_sound_strip(bmain, scene, seqbase, &load_data);
|
||||
|
||||
bSound *sound = BKE_sound_new_file(bmain, file);
|
||||
|
||||
SoundInfo info;
|
||||
if (!BKE_sound_info_get(bmain, sound, &info)) {
|
||||
BKE_id_free(bmain, sound);
|
||||
if (seq == NULL) {
|
||||
BKE_report(reports, RPT_ERROR, "Sequences.new_sound: unable to open sound file");
|
||||
return NULL;
|
||||
}
|
||||
seq = alloc_generic_sequence(
|
||||
seqbase, name, frame_start, channel, SEQ_TYPE_SOUND_RAM, sound->filepath);
|
||||
seq->sound = sound;
|
||||
seq->len = ceil((double)info.length * FPS);
|
||||
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
|
||||
DEG_relations_tag_update(bmain);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
|
@ -432,8 +379,7 @@ static Sequence *rna_Sequences_new_effect(ID *id,
|
|||
{
|
||||
Scene *scene = (Scene *)id;
|
||||
Sequence *seq;
|
||||
struct SeqEffectHandle sh;
|
||||
int num_inputs = SEQ_effect_get_num_inputs(type);
|
||||
const int num_inputs = SEQ_effect_get_num_inputs(type);
|
||||
|
||||
switch (num_inputs) {
|
||||
case 0:
|
||||
|
@ -469,26 +415,14 @@ static Sequence *rna_Sequences_new_effect(ID *id,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
seq = alloc_generic_sequence(seqbase, name, frame_start, channel, type, NULL);
|
||||
|
||||
sh = SEQ_effect_handle_get(seq);
|
||||
|
||||
seq->seq1 = seq1;
|
||||
seq->seq2 = seq2;
|
||||
seq->seq3 = seq3;
|
||||
|
||||
sh.init(seq);
|
||||
|
||||
if (!seq1) { /* effect has no deps */
|
||||
seq->len = 1;
|
||||
SEQ_transform_set_right_handle_frame(seq, frame_end);
|
||||
}
|
||||
|
||||
seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
|
||||
|
||||
SEQ_time_update_sequence(scene, seq);
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
SeqLoadData load_data;
|
||||
SEQ_add_load_data_init(&load_data, name, NULL, frame_start, channel);
|
||||
load_data.effect.end_frame = frame_end;
|
||||
load_data.effect.type = type;
|
||||
load_data.effect.seq1 = seq1;
|
||||
load_data.effect.seq2 = seq2;
|
||||
load_data.effect.seq3 = seq3;
|
||||
seq = SEQ_add_effect_strip(scene, seqbase, &load_data);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
||||
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
@ -865,7 +799,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop, const bool metastri
|
|||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "new_movie", new_movie_func_name);
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
|
||||
RNA_def_function_ui_description(func, "Add a new movie sequence");
|
||||
parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
|
|
|
@ -32,48 +32,73 @@ struct Scene;
|
|||
struct Sequence;
|
||||
struct bContext;
|
||||
|
||||
/* api for adding new sequence strips */
|
||||
typedef struct SeqLoadInfo {
|
||||
int start_frame;
|
||||
int end_frame;
|
||||
int channel;
|
||||
int flag; /* use sound, replace sel */
|
||||
int type;
|
||||
int len; /* only for image strips */
|
||||
char path[1024]; /* 1024 = FILE_MAX */
|
||||
eSeqImageFitMethod fit_method;
|
||||
/* SeqLoadData.flags */
|
||||
typedef enum eSeqLoadFlags {
|
||||
SEQ_LOAD_SOUND_CACHE = (1 << 1),
|
||||
SEQ_LOAD_SOUND_MONO = (1 << 2),
|
||||
SEQ_LOAD_MOVIE_SYNC_FPS = (1 << 3),
|
||||
} eSeqLoadFlags;
|
||||
|
||||
/* multiview */
|
||||
/* Api for adding new sequence strips. */
|
||||
typedef struct SeqLoadData {
|
||||
int start_frame;
|
||||
int channel;
|
||||
char name[64]; /* Strip name. */
|
||||
char path[1024]; /* 1024 = FILE_MAX */
|
||||
struct {
|
||||
int len;
|
||||
int end_frame;
|
||||
} image; /* Only for image strips. */
|
||||
struct Scene *scene; /* Only for scene strips. */
|
||||
struct MovieClip *clip; /* Only for clip strips. */
|
||||
struct Mask *mask; /* Only for mask strips. */
|
||||
struct {
|
||||
int type;
|
||||
int end_frame;
|
||||
struct Sequence *seq1;
|
||||
struct Sequence *seq2;
|
||||
struct Sequence *seq3;
|
||||
} effect; /* Only for effect strips. */
|
||||
eSeqLoadFlags flags;
|
||||
eSeqImageFitMethod fit_method;
|
||||
bool use_multiview;
|
||||
char views_format;
|
||||
struct Stereo3dFormat *stereo3d_format;
|
||||
bool allow_invalid_file; /* Used by RNA API to create placeholder strips. */
|
||||
} SeqLoadData;
|
||||
|
||||
/* return values */
|
||||
char name[64];
|
||||
struct Sequence *seq_sound; /* for movie's */
|
||||
int tot_success;
|
||||
int tot_error;
|
||||
} SeqLoadInfo;
|
||||
|
||||
/* SeqLoadInfo.flag */
|
||||
#define SEQ_LOAD_REPLACE_SEL (1 << 0)
|
||||
#define SEQ_LOAD_FRAME_ADVANCE (1 << 1)
|
||||
#define SEQ_LOAD_MOVIE_SOUND (1 << 2)
|
||||
#define SEQ_LOAD_SOUND_CACHE (1 << 3)
|
||||
#define SEQ_LOAD_SYNC_FPS (1 << 4)
|
||||
#define SEQ_LOAD_SOUND_MONO (1 << 5)
|
||||
|
||||
/* use as an api function */
|
||||
typedef struct Sequence *(*SeqLoadFn)(struct bContext *, ListBase *, struct SeqLoadInfo *);
|
||||
|
||||
struct Sequence *SEQ_add_image_strip(struct bContext *C,
|
||||
ListBase *seqbasep,
|
||||
struct SeqLoadInfo *seq_load);
|
||||
struct Sequence *SEQ_add_sound_strip(struct bContext *C,
|
||||
ListBase *seqbasep,
|
||||
struct SeqLoadInfo *seq_load);
|
||||
struct Sequence *SEQ_add_movie_strip(struct bContext *C,
|
||||
ListBase *seqbasep,
|
||||
struct SeqLoadInfo *seq_load);
|
||||
void SEQ_add_load_data_init(struct SeqLoadData *load_data,
|
||||
const char *name,
|
||||
const char *path,
|
||||
const int start_frame,
|
||||
const int channel);
|
||||
struct Sequence *SEQ_add_image_strip(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct ListBase *seqbase,
|
||||
struct SeqLoadData *load_data);
|
||||
struct Sequence *SEQ_add_sound_strip(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct ListBase *seqbase,
|
||||
struct SeqLoadData *load_data);
|
||||
struct Sequence *SEQ_add_movie_strip(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct ListBase *seqbase,
|
||||
struct SeqLoadData *load_data);
|
||||
struct Sequence *SEQ_add_scene_strip(struct Scene *scene,
|
||||
struct ListBase *seqbase,
|
||||
struct SeqLoadData *load_data);
|
||||
struct Sequence *SEQ_add_movieclip_strip(struct Scene *scene,
|
||||
struct ListBase *seqbase,
|
||||
struct SeqLoadData *load_data);
|
||||
struct Sequence *SEQ_add_mask_strip(struct Scene *scene,
|
||||
struct ListBase *seqbase,
|
||||
struct SeqLoadData *load_data);
|
||||
struct Sequence *SEQ_add_effect_strip(struct Scene *scene,
|
||||
struct ListBase *seqbase,
|
||||
struct SeqLoadData *load_data);
|
||||
void SEQ_add_image_set_directory(struct Sequence *seq, char *path);
|
||||
void SEQ_add_image_load_file(struct Sequence *seq, size_t strip_frame, char *filename);
|
||||
void SEQ_add_image_init_alpha_mode(struct Sequence *seq);
|
||||
void SEQ_add_reload_new_file(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct Sequence *seq,
|
||||
|
|
|
@ -203,34 +203,6 @@ void SEQ_render_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4
|
|||
}
|
||||
}
|
||||
|
||||
void SEQ_render_init_colorspace(Sequence *seq)
|
||||
{
|
||||
if (seq->strip && seq->strip->stripdata) {
|
||||
char name[FILE_MAX];
|
||||
ImBuf *ibuf;
|
||||
|
||||
BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name);
|
||||
BLI_path_abs(name, BKE_main_blendfile_path_from_global());
|
||||
|
||||
/* initialize input color space */
|
||||
if (seq->type == SEQ_TYPE_IMAGE) {
|
||||
ibuf = IMB_loadiffname(
|
||||
name, IB_test | IB_alphamode_detect, seq->strip->colorspace_settings.name);
|
||||
|
||||
/* byte images are default to straight alpha, however sequencer
|
||||
* works in premul space, so mark strip to be premultiplied first
|
||||
*/
|
||||
seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
|
||||
if (ibuf) {
|
||||
if (ibuf->flags & IB_alphamode_premul) {
|
||||
seq->alpha_mode = IMA_ALPHA_PREMUL;
|
||||
}
|
||||
|
||||
IMB_freeImBuf(ibuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_mask_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_sequence_types.h"
|
||||
#include "DNA_sound_types.h"
|
||||
|
@ -54,7 +55,9 @@
|
|||
#include "IMB_metadata.h"
|
||||
|
||||
#include "SEQ_add.h"
|
||||
#include "SEQ_effects.h"
|
||||
#include "SEQ_relations.h"
|
||||
#include "SEQ_render.h"
|
||||
#include "SEQ_select.h"
|
||||
#include "SEQ_sequencer.h"
|
||||
#include "SEQ_time.h"
|
||||
|
@ -65,168 +68,369 @@
|
|||
#include "proxy.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void seq_load_apply(Main *bmain, Scene *scene, Sequence *seq, SeqLoadInfo *seq_load)
|
||||
/**
|
||||
* Initialize common SeqLoadData members
|
||||
*
|
||||
* \param load_data: SeqLoadData to be initialized
|
||||
* \param name: strip name (can be NULL)
|
||||
* \param path: path to file that is used as strip input (can be NULL)
|
||||
* \param start_frame: timeline frame where strip will be created
|
||||
* \param channel: timeline channel where strip will be created
|
||||
*
|
||||
*/
|
||||
void SEQ_add_load_data_init(SeqLoadData *load_data,
|
||||
const char *name,
|
||||
const char *path,
|
||||
const int start_frame,
|
||||
const int channel)
|
||||
{
|
||||
if (seq) {
|
||||
BLI_strncpy_utf8(seq->name + 2, seq_load->name, sizeof(seq->name) - 2);
|
||||
BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2));
|
||||
SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
|
||||
memset(load_data, 0, sizeof(SeqLoadData));
|
||||
if (name != NULL) {
|
||||
BLI_strncpy(load_data->name, name, sizeof(load_data->name));
|
||||
}
|
||||
if (path != NULL) {
|
||||
BLI_strncpy(load_data->path, path, sizeof(load_data->path));
|
||||
}
|
||||
load_data->start_frame = start_frame;
|
||||
load_data->channel = channel;
|
||||
}
|
||||
|
||||
if (seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) {
|
||||
seq_load->start_frame += (seq->enddisp - seq->startdisp);
|
||||
}
|
||||
static void seq_add_generic_update(Scene *scene, ListBase *seqbase, Sequence *seq)
|
||||
{
|
||||
SEQ_sequence_base_unique_name_recursive(seqbase, seq);
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
SEQ_sort(scene);
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
}
|
||||
|
||||
if (seq_load->flag & SEQ_LOAD_REPLACE_SEL) {
|
||||
seq_load->flag |= SELECT;
|
||||
SEQ_select_active_set(scene, seq);
|
||||
}
|
||||
|
||||
if (seq_load->flag & SEQ_LOAD_SOUND_MONO) {
|
||||
seq->sound->flags |= SOUND_FLAGS_MONO;
|
||||
BKE_sound_load(bmain, seq->sound);
|
||||
}
|
||||
|
||||
if (seq_load->flag & SEQ_LOAD_SOUND_CACHE) {
|
||||
if (seq->sound) {
|
||||
seq->sound->flags |= SOUND_FLAGS_CACHING;
|
||||
}
|
||||
}
|
||||
|
||||
seq_load->tot_success++;
|
||||
static void seq_add_set_name(Sequence *seq, SeqLoadData *load_data)
|
||||
{
|
||||
if (load_data->name != NULL) {
|
||||
BLI_strncpy(seq->name + 2, load_data->name, sizeof(seq->name) - 2);
|
||||
}
|
||||
else {
|
||||
seq_load->tot_error++;
|
||||
if (seq->type == SEQ_TYPE_SCENE) {
|
||||
BLI_strncpy(seq->name + 2, load_data->scene->id.name + 2, sizeof(seq->name) - 2);
|
||||
}
|
||||
else if (seq->type == SEQ_TYPE_MOVIECLIP) {
|
||||
BLI_strncpy(seq->name + 2, load_data->clip->id.name + 2, sizeof(seq->name) - 2);
|
||||
}
|
||||
else if (seq->type == SEQ_TYPE_MASK) {
|
||||
BLI_strncpy(seq->name + 2, load_data->mask->id.name + 2, sizeof(seq->name) - 2);
|
||||
}
|
||||
else if ((seq->type & SEQ_TYPE_EFFECT) != 0) {
|
||||
BLI_strncpy(seq->name + 2, SEQ_sequence_give_name(seq), sizeof(seq->name) - 2);
|
||||
}
|
||||
else { /* Image, sound and movie. */
|
||||
BLI_strncpy_utf8(seq->name + 2, load_data->name, sizeof(seq->name) - 2);
|
||||
BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: this function doesn't fill in image names */
|
||||
Sequence *SEQ_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
||||
/**
|
||||
* Add scene strip.
|
||||
*
|
||||
* \param scene: Scene where strips will be added
|
||||
* \param seqbase: ListBase where strips will be added
|
||||
* \param load_data: SeqLoadData with information necessary to create strip
|
||||
* \return created strip
|
||||
*/
|
||||
Sequence *SEQ_add_scene_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C); /* only for active seq */
|
||||
Sequence *seq;
|
||||
Strip *strip;
|
||||
Sequence *seq = SEQ_sequence_alloc(
|
||||
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_SCENE);
|
||||
seq->blend_mode = SEQ_TYPE_CROSS;
|
||||
seq->scene = load_data->scene;
|
||||
seq->len = load_data->scene->r.efra - load_data->scene->r.sfra + 1;
|
||||
id_us_ensure_real((ID *)load_data->scene);
|
||||
seq_add_set_name(seq, load_data);
|
||||
seq_add_generic_update(scene, seqbase, seq);
|
||||
return seq;
|
||||
}
|
||||
|
||||
seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_IMAGE);
|
||||
seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
|
||||
/**
|
||||
* Add movieclip strip.
|
||||
*
|
||||
* \param scene: Scene where strips will be added
|
||||
* \param seqbase: ListBase where strips will be added
|
||||
* \param load_data: SeqLoadData with information necessary to create strip
|
||||
* \return created strip
|
||||
*/
|
||||
Sequence *SEQ_add_movieclip_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
|
||||
{
|
||||
Sequence *seq = SEQ_sequence_alloc(
|
||||
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MOVIECLIP);
|
||||
seq->blend_mode = SEQ_TYPE_CROSS;
|
||||
seq->clip = load_data->clip;
|
||||
seq->len = BKE_movieclip_get_duration(load_data->clip);
|
||||
id_us_ensure_real((ID *)load_data->clip);
|
||||
seq_add_set_name(seq, load_data);
|
||||
seq_add_generic_update(scene, seqbase, seq);
|
||||
return seq;
|
||||
}
|
||||
|
||||
/* basic defaults */
|
||||
seq->len = seq_load->len ? seq_load->len : 1;
|
||||
/**
|
||||
* Add mask strip.
|
||||
*
|
||||
* \param scene: Scene where strips will be added
|
||||
* \param seqbase: ListBase where strips will be added
|
||||
* \param load_data: SeqLoadData with information necessary to create strip
|
||||
* \return created strip
|
||||
*/
|
||||
Sequence *SEQ_add_mask_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
|
||||
{
|
||||
Sequence *seq = SEQ_sequence_alloc(
|
||||
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MASK);
|
||||
seq->blend_mode = SEQ_TYPE_CROSS;
|
||||
seq->mask = load_data->mask;
|
||||
seq->len = BKE_mask_get_duration(load_data->mask);
|
||||
id_us_ensure_real((ID *)load_data->mask);
|
||||
seq_add_set_name(seq, load_data);
|
||||
seq_add_generic_update(scene, seqbase, seq);
|
||||
return seq;
|
||||
}
|
||||
|
||||
strip = seq->strip;
|
||||
strip->stripdata = MEM_callocN(seq->len * sizeof(StripElem), "stripelem");
|
||||
BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir));
|
||||
/**
|
||||
* Add effect strip.
|
||||
*
|
||||
* \param scene: Scene where strips will be added
|
||||
* \param seqbase: ListBase where strips will be added
|
||||
* \param load_data: SeqLoadData with information necessary to create strip
|
||||
* \return created strip
|
||||
*/
|
||||
Sequence *SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
|
||||
{
|
||||
Sequence *seq = SEQ_sequence_alloc(
|
||||
seqbase, load_data->start_frame, load_data->channel, load_data->effect.type);
|
||||
|
||||
if (seq_load->stereo3d_format) {
|
||||
*seq->stereo3d_format = *seq_load->stereo3d_format;
|
||||
seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
|
||||
struct SeqEffectHandle sh = SEQ_effect_handle_get(seq);
|
||||
sh.init(seq);
|
||||
seq->seq1 = load_data->effect.seq1;
|
||||
seq->seq2 = load_data->effect.seq2;
|
||||
seq->seq3 = load_data->effect.seq3;
|
||||
|
||||
if (seq->type == SEQ_TYPE_COLOR) {
|
||||
seq->blend_mode = SEQ_TYPE_CROSS;
|
||||
}
|
||||
else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
|
||||
seq->blend_mode = SEQ_TYPE_CROSS;
|
||||
}
|
||||
else if (seq->type == SEQ_TYPE_TEXT) {
|
||||
seq->blend_mode = SEQ_TYPE_ALPHAOVER;
|
||||
}
|
||||
else if (SEQ_effect_get_num_inputs(seq->type) == 1) {
|
||||
seq->blend_mode = seq->seq1->blend_mode;
|
||||
}
|
||||
|
||||
seq->views_format = seq_load->views_format;
|
||||
seq->flag |= seq_load->flag & SEQ_USE_VIEWS;
|
||||
if (!load_data->effect.seq1) {
|
||||
seq->len = 1; /* Effect is generator, set non zero length. */
|
||||
SEQ_transform_set_right_handle_frame(seq, load_data->image.end_frame);
|
||||
}
|
||||
SEQ_relations_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs SEQ_time_update_sequence. */
|
||||
seq_add_set_name(seq, load_data);
|
||||
seq_add_generic_update(scene, seqbase, seq);
|
||||
|
||||
seq_load_apply(CTX_data_main(C), scene, seq, seq_load);
|
||||
return seq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set directory used by image strip.
|
||||
*
|
||||
* \param seq: image strip to be changed
|
||||
* \param path: directory path
|
||||
*/
|
||||
void SEQ_add_image_set_directory(Sequence *seq, char *path)
|
||||
{
|
||||
BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set directory used by image strip.
|
||||
*
|
||||
* \param seq: image strip to be changed
|
||||
* \param strip_frame: frame index of strip to be changed
|
||||
* \param filename: image filename (only filename, not complete path)
|
||||
*/
|
||||
void SEQ_add_image_load_file(Sequence *seq, size_t strip_frame, char *filename)
|
||||
{
|
||||
StripElem *se = SEQ_render_give_stripelem(seq, seq->start + strip_frame);
|
||||
BLI_strncpy(se->name, filename, sizeof(se->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set image strip alpha mode
|
||||
*
|
||||
* \param seq: image strip to be changed
|
||||
*/
|
||||
void SEQ_add_image_init_alpha_mode(Sequence *seq)
|
||||
{
|
||||
if (seq->strip && seq->strip->stripdata) {
|
||||
char name[FILE_MAX];
|
||||
ImBuf *ibuf;
|
||||
|
||||
BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name);
|
||||
BLI_path_abs(name, BKE_main_blendfile_path_from_global());
|
||||
|
||||
/* Initialize input color space. */
|
||||
if (seq->type == SEQ_TYPE_IMAGE) {
|
||||
ibuf = IMB_loadiffname(
|
||||
name, IB_test | IB_alphamode_detect, seq->strip->colorspace_settings.name);
|
||||
|
||||
/* Byte images are default to straight alpha, however sequencer
|
||||
* works in premul space, so mark strip to be premultiplied first.
|
||||
*/
|
||||
seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
|
||||
if (ibuf) {
|
||||
if (ibuf->flags & IB_alphamode_premul) {
|
||||
seq->alpha_mode = IMA_ALPHA_PREMUL;
|
||||
}
|
||||
|
||||
IMB_freeImBuf(ibuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add image strip.
|
||||
* NOTE: Use SEQ_add_image_set_directory() and SEQ_add_image_load_file() to load image sequences
|
||||
*
|
||||
* \param main: Main reference
|
||||
* \param scene: Scene where strips will be added
|
||||
* \param seqbase: ListBase where strips will be added
|
||||
* \param load_data: SeqLoadData with information necessary to create strip
|
||||
* \return created strip
|
||||
*/
|
||||
Sequence *SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
|
||||
{
|
||||
Sequence *seq = SEQ_sequence_alloc(
|
||||
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_IMAGE);
|
||||
seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
|
||||
seq->len = load_data->image.len;
|
||||
Strip *strip = seq->strip;
|
||||
strip->stripdata = MEM_callocN(load_data->image.len * sizeof(StripElem), "stripelem");
|
||||
|
||||
/* Multiview settings. */
|
||||
if (load_data->use_multiview) {
|
||||
seq->flag |= SEQ_USE_VIEWS;
|
||||
seq->views_format = load_data->views_format;
|
||||
}
|
||||
if (load_data->stereo3d_format) {
|
||||
seq->stereo3d_format = load_data->stereo3d_format;
|
||||
}
|
||||
|
||||
/* Set initial scale based on load_data->fit_method. */
|
||||
char file_path[FILE_MAX];
|
||||
BLI_join_dirfile(file_path, sizeof(file_path), seq_load->path, seq_load->name);
|
||||
BLI_path_abs(file_path, BKE_main_blendfile_path(CTX_data_main(C)));
|
||||
BLI_join_dirfile(file_path, sizeof(file_path), load_data->path, load_data->name);
|
||||
BLI_path_abs(file_path, BKE_main_blendfile_path(bmain));
|
||||
ImBuf *ibuf = IMB_loadiffname(file_path, IB_rect, seq->strip->colorspace_settings.name);
|
||||
if (ibuf != NULL) {
|
||||
SEQ_set_scale_to_fit(
|
||||
seq, ibuf->x, ibuf->y, scene->r.xsch, scene->r.ysch, seq_load->fit_method);
|
||||
seq, ibuf->x, ibuf->y, scene->r.xsch, scene->r.ysch, load_data->fit_method);
|
||||
IMB_freeImBuf(ibuf);
|
||||
}
|
||||
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
/* Set Last active directory. */
|
||||
BLI_strncpy(scene->ed->act_imagedir, seq->strip->dir, sizeof(scene->ed->act_imagedir));
|
||||
seq_add_set_name(seq, load_data);
|
||||
seq_add_generic_update(scene, seqbase, seq);
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
#ifdef WITH_AUDASPACE
|
||||
Sequence *SEQ_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
||||
/**
|
||||
* Add sound strip.
|
||||
* NOTE: Use SEQ_add_image_set_directory() and SEQ_add_image_load_file() to load image sequences
|
||||
*
|
||||
* \param main: Main reference
|
||||
* \param scene: Scene where strips will be added
|
||||
* \param seqbase: ListBase where strips will be added
|
||||
* \param load_data: SeqLoadData with information necessary to create strip
|
||||
* \return created strip
|
||||
*/
|
||||
|
||||
Sequence *SEQ_add_sound_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C); /* only for sound */
|
||||
Editing *ed = SEQ_editing_get(scene, false);
|
||||
bSound *sound;
|
||||
|
||||
Sequence *seq; /* generic strip vars */
|
||||
Strip *strip;
|
||||
StripElem *se;
|
||||
|
||||
sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */
|
||||
|
||||
bSound *sound = BKE_sound_new_file(bmain, load_data->path); /* Handles relative paths. */
|
||||
SoundInfo info;
|
||||
if (!BKE_sound_info_get(bmain, sound, &info)) {
|
||||
bool sound_loaded = BKE_sound_info_get(bmain, sound, &info);
|
||||
|
||||
if (!sound_loaded && !load_data->allow_invalid_file) {
|
||||
BKE_id_free(bmain, sound);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (info.specs.channels == SOUND_CHANNELS_INVALID) {
|
||||
if (info.specs.channels == SOUND_CHANNELS_INVALID && !load_data->allow_invalid_file) {
|
||||
BKE_id_free(bmain, sound);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_SOUND_RAM);
|
||||
Sequence *seq = SEQ_sequence_alloc(
|
||||
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_SOUND_RAM);
|
||||
seq->sound = sound;
|
||||
BLI_strncpy(seq->name + 2, "Sound", SEQ_NAME_MAXSTR - 2);
|
||||
SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
|
||||
|
||||
/* basic defaults */
|
||||
/* We add a very small negative offset here, because
|
||||
* ceil(132.0) == 133.0, not nice with videos, see T47135. */
|
||||
seq->len = (int)ceil((double)info.length * FPS - 1e-4);
|
||||
strip = seq->strip;
|
||||
|
||||
/* we only need 1 element to store the filename */
|
||||
strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem");
|
||||
|
||||
BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
|
||||
|
||||
seq->scene_sound = NULL;
|
||||
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
/* We add a very small negative offset here, because
|
||||
* ceil(132.0) == 133.0, not nice with videos, see T47135. */
|
||||
seq->len = MAX2(1, (int)ceil((double)info.length * FPS - 1e-4));
|
||||
|
||||
/* last active name */
|
||||
BLI_strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR);
|
||||
Strip *strip = seq->strip;
|
||||
/* We only need 1 element to store the filename. */
|
||||
StripElem *se = strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem");
|
||||
BLI_split_dirfile(load_data->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
|
||||
|
||||
seq_load_apply(bmain, scene, seq, seq_load);
|
||||
if (seq != NULL && seq->sound != NULL) {
|
||||
if (load_data->flags & SEQ_LOAD_SOUND_MONO) {
|
||||
seq->sound->flags |= SOUND_FLAGS_MONO;
|
||||
}
|
||||
|
||||
/* TODO(sergey): Shall we tag here or in the operator? */
|
||||
DEG_relations_tag_update(bmain);
|
||||
if (load_data->flags & SEQ_LOAD_SOUND_CACHE) {
|
||||
if (seq->sound) {
|
||||
seq->sound->flags |= SOUND_FLAGS_CACHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Last active directory. */
|
||||
BLI_strncpy(scene->ed->act_sounddir, strip->dir, FILE_MAXDIR);
|
||||
seq_add_set_name(seq, load_data);
|
||||
seq_add_generic_update(scene, seqbase, seq);
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
#else // WITH_AUDASPACE
|
||||
Sequence *SEQ_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
||||
{
|
||||
(void)C;
|
||||
(void)seqbasep;
|
||||
(void)seq_load;
|
||||
return NULL;
|
||||
}
|
||||
Sequence *SEQ_add_sound_strip(Main *UNUSED(bmain),
|
||||
Scene *UNUSED(scene),
|
||||
ListBase *UNUSED(seqbase),
|
||||
const SeqLoadData *UNUSED(load_data))
|
||||
#endif // WITH_AUDASPACE
|
||||
|
||||
Sequence *SEQ_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
||||
/**
|
||||
* Add movie strip.
|
||||
*
|
||||
* \param main: Main reference
|
||||
* \param scene: Scene where strips will be added
|
||||
* \param seqbase: ListBase where strips will be added
|
||||
* \param load_data: SeqLoadData with information necessary to create strip
|
||||
* \return created strip
|
||||
*/
|
||||
Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C); /* only for sound */
|
||||
char path[sizeof(seq_load->path)];
|
||||
|
||||
Sequence *seq; /* generic strip vars */
|
||||
Strip *strip;
|
||||
StripElem *se;
|
||||
char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */
|
||||
bool is_multiview_loaded = false;
|
||||
const bool is_multiview = (seq_load->flag & SEQ_USE_VIEWS) != 0;
|
||||
const int totfiles = seq_num_files(scene, seq_load->views_format, is_multiview);
|
||||
struct anim **anim_arr;
|
||||
int i;
|
||||
|
||||
BLI_strncpy(path, seq_load->path, sizeof(path));
|
||||
char path[sizeof(load_data->path)];
|
||||
BLI_strncpy(path, load_data->path, sizeof(path));
|
||||
BLI_path_abs(path, BKE_main_blendfile_path(bmain));
|
||||
|
||||
anim_arr = MEM_callocN(sizeof(struct anim *) * totfiles, "Video files");
|
||||
char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */
|
||||
bool is_multiview_loaded = false;
|
||||
const int totfiles = seq_num_files(scene, load_data->views_format, load_data->use_multiview);
|
||||
struct anim **anim_arr = MEM_callocN(sizeof(struct anim *) * totfiles, "Video files");
|
||||
int i;
|
||||
|
||||
if (is_multiview && (seq_load->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
|
||||
if (load_data->use_multiview && (load_data->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
|
||||
char prefix[FILE_MAX];
|
||||
const char *ext = NULL;
|
||||
size_t j = 0;
|
||||
|
@ -245,38 +449,30 @@ Sequence *SEQ_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_
|
|||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == 0) {
|
||||
MEM_freeN(anim_arr);
|
||||
return NULL;
|
||||
}
|
||||
is_multiview_loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_multiview_loaded == false) {
|
||||
anim_arr[0] = openanim(path, IB_rect, 0, colorspace);
|
||||
|
||||
if (anim_arr[0] == NULL) {
|
||||
MEM_freeN(anim_arr);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) {
|
||||
seq_load->channel++;
|
||||
if (anim_arr[0] == NULL && !load_data->allow_invalid_file) {
|
||||
MEM_freeN(anim_arr);
|
||||
return NULL;
|
||||
}
|
||||
seq = SEQ_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_MOVIE);
|
||||
|
||||
/* multiview settings */
|
||||
if (seq_load->stereo3d_format) {
|
||||
*seq->stereo3d_format = *seq_load->stereo3d_format;
|
||||
seq->views_format = seq_load->views_format;
|
||||
Sequence *seq = SEQ_sequence_alloc(
|
||||
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MOVIE);
|
||||
|
||||
/* Multiview settings. */
|
||||
if (load_data->use_multiview) {
|
||||
seq->flag |= SEQ_USE_VIEWS;
|
||||
seq->views_format = load_data->views_format;
|
||||
}
|
||||
if (load_data->stereo3d_format) {
|
||||
seq->stereo3d_format = load_data->stereo3d_format;
|
||||
}
|
||||
seq->flag |= seq_load->flag & SEQ_USE_VIEWS;
|
||||
|
||||
seq->type = SEQ_TYPE_MOVIE;
|
||||
seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
|
||||
|
||||
for (i = 0; i < totfiles; i++) {
|
||||
if (anim_arr[i]) {
|
||||
|
@ -289,51 +485,38 @@ Sequence *SEQ_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_
|
|||
}
|
||||
}
|
||||
|
||||
IMB_anim_load_metadata(anim_arr[0]);
|
||||
seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
|
||||
|
||||
seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]);
|
||||
if (anim_arr[0] != NULL) {
|
||||
seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]);
|
||||
seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN);
|
||||
|
||||
const float width = IMB_anim_get_image_width(anim_arr[0]);
|
||||
const float height = IMB_anim_get_image_height(anim_arr[0]);
|
||||
SEQ_set_scale_to_fit(seq, width, height, scene->r.xsch, scene->r.ysch, seq_load->fit_method);
|
||||
IMB_anim_load_metadata(anim_arr[0]);
|
||||
|
||||
BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2);
|
||||
SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
|
||||
/* Adjust scene's frame rate settings to match. */
|
||||
if (load_data->flags & SEQ_LOAD_MOVIE_SYNC_FPS) {
|
||||
IMB_anim_get_fps(anim_arr[0], &scene->r.frs_sec, &scene->r.frs_sec_base, true);
|
||||
}
|
||||
|
||||
/* adjust scene's frame rate settings to match */
|
||||
if (seq_load->flag & SEQ_LOAD_SYNC_FPS) {
|
||||
IMB_anim_get_fps(anim_arr[0], &scene->r.frs_sec, &scene->r.frs_sec_base, true);
|
||||
/* Set initial scale based on load_data->fit_method. */
|
||||
const float width = IMB_anim_get_image_width(anim_arr[0]);
|
||||
const float height = IMB_anim_get_image_height(anim_arr[0]);
|
||||
SEQ_set_scale_to_fit(seq, width, height, scene->r.xsch, scene->r.ysch, load_data->fit_method);
|
||||
}
|
||||
|
||||
/* basic defaults */
|
||||
seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN);
|
||||
strip = seq->strip;
|
||||
|
||||
seq->len = MAX2(1, seq->len);
|
||||
BLI_strncpy(seq->strip->colorspace_settings.name,
|
||||
colorspace,
|
||||
sizeof(seq->strip->colorspace_settings.name));
|
||||
|
||||
/* we only need 1 element for MOVIE strips */
|
||||
Strip *strip = seq->strip;
|
||||
/* We only need 1 element for MOVIE strips. */
|
||||
StripElem *se;
|
||||
strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem");
|
||||
BLI_split_dirfile(load_data->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
|
||||
|
||||
BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
|
||||
|
||||
SEQ_time_update_sequence_bounds(scene, seq);
|
||||
|
||||
if (seq_load->name[0] == '\0') {
|
||||
BLI_strncpy(seq_load->name, se->name, sizeof(seq_load->name));
|
||||
}
|
||||
|
||||
if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) {
|
||||
int start_frame_back = seq_load->start_frame;
|
||||
seq_load->channel--;
|
||||
seq_load->seq_sound = SEQ_add_sound_strip(C, seqbasep, seq_load);
|
||||
seq_load->start_frame = start_frame_back;
|
||||
}
|
||||
|
||||
/* can be NULL */
|
||||
seq_load_apply(CTX_data_main(C), scene, seq, seq_load);
|
||||
SEQ_relations_invalidate_cache_composite(scene, seq);
|
||||
seq_add_set_name(seq, load_data);
|
||||
seq_add_generic_update(scene, seqbase, seq);
|
||||
|
||||
MEM_freeN(anim_arr);
|
||||
return seq;
|
||||
|
@ -525,9 +708,9 @@ void SEQ_add_movie_reload_if_needed(struct Main *bmain,
|
|||
|
||||
bool must_reload = false;
|
||||
|
||||
/* The Sequence struct allows for multiple anim structs to be associated with one strip. This
|
||||
* function will return true only if there is at least one 'anim' AND all anims can produce
|
||||
* frames. */
|
||||
/* The Sequence struct allows for multiple anim structs to be associated with one strip.
|
||||
* This function will return true only if there is at least one 'anim' AND all anims can
|
||||
* produce frames. */
|
||||
|
||||
if (BLI_listbase_is_empty(&seq->anims)) {
|
||||
/* No anim present, so reloading is always necessary. */
|
||||
|
|
Loading…
Reference in New Issue