WIP: VSE: Use seconds for strip length and position #105620

Draft
Richard Antalik wants to merge 13 commits from iss/blender:time-in-seconds into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
31 changed files with 429 additions and 295 deletions

View File

@ -27,7 +27,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 7
#define BLENDER_FILE_SUBVERSION 8
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@ -776,12 +776,15 @@ void BKE_sound_move_scene_sound_defaults(Scene *scene, Sequence *sequence)
{
sound_verify_evaluated_id(&scene->id);
if (sequence->scene_sound) {
BKE_sound_move_scene_sound(scene,
sequence->scene_sound,
SEQ_time_left_handle_frame_get(scene, sequence),
SEQ_time_right_handle_frame_get(scene, sequence),
sequence->startofs + sequence->anim_startofs,
0.0);
BKE_sound_move_scene_sound(
scene,
sequence->scene_sound,
SEQ_time_left_handle_frame_get(scene, sequence),
SEQ_time_right_handle_frame_get(scene, sequence),
SEQ_time_seconds_to_frames(
scene,
sequence->startofs + sequence->anim_startofs), // XXX don't use the function here!
0.0);
}
}

View File

@ -670,7 +670,7 @@ static bool do_versions_sequencer_init_retiming_tool_data(Sequence *seq, void *u
const int content_length = SEQ_time_strip_length_get(scene, seq);
SEQ_retiming_data_ensure(seq);
SEQ_retiming_data_ensure(scene, seq);
SeqRetimingHandle *handle = &seq->retiming_handles[seq->retiming_handle_num - 1];
handle->strip_frame_index = round_fl_to_int(content_length / seq->speed_factor);

View File

@ -29,6 +29,9 @@
#include "BLO_readfile.h"
#include "SEQ_sequencer.h"
#include "SEQ_iterator.h"
#include "readfile.h"
#include "versioning_common.h"
@ -200,6 +203,23 @@ static void versioning_remove_microfacet_sharp_distribution(bNodeTree *ntree)
}
}
static bool version_seq_convert_frames_to_seconds(Sequence *seq, void *user_data)
{
if (seq->seq1 != nullptr || seq->seq2 != nullptr) {
return true;
}
const Scene *scene = static_cast<Scene *>(user_data);
double scene_playback_rate = (float)scene->r.frs_sec / scene->r.frs_sec_base;
seq->start /= scene_playback_rate;
seq->len /= scene_playback_rate;
seq->startofs /= scene_playback_rate;
seq->endofs /= scene_playback_rate;
// XXX anim offsets
return true;
}
void blo_do_versions_400(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
{
if (!MAIN_VERSION_ATLEAST(bmain, 400, 1)) {
@ -257,6 +277,16 @@ void blo_do_versions_400(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 400, 8)) {
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
Editing *ed = SEQ_editing_get(scene);
if (ed != nullptr) {
SEQ_for_each_callback(&ed->seqbase, version_seq_convert_frames_to_seconds, scene);
}
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -546,7 +546,7 @@ static void drawmeta_contents(Scene *scene,
ListBase *meta_channels;
int offset;
meta_seqbase = SEQ_get_seqbase_from_sequence(seqm, &meta_channels, &offset);
meta_seqbase = SEQ_get_seqbase_from_sequence(scene, seqm, &meta_channels, &offset);
if (!meta_seqbase || BLI_listbase_is_empty(meta_seqbase)) {
return;
@ -964,7 +964,7 @@ static void draw_sequence_extensions_overlay(
col[3] = SEQ_render_is_muted(channels, seq) ? MUTE_ALPHA : 200;
UI_GetColorPtrShade3ubv(col, blend_col, 10);
const float strip_content_start = SEQ_time_start_frame_get(seq);
const float strip_content_start = SEQ_time_start_frame_get(scene, seq);
const float strip_content_end = SEQ_time_content_end_frame_get(scene, seq);
float right_handle_frame = SEQ_time_right_handle_frame_get(scene, seq);
float left_handle_frame = SEQ_time_left_handle_frame_get(scene, seq);
@ -1092,7 +1092,7 @@ static void draw_seq_background(Scene *scene,
if (SEQ_time_has_left_still_frames(scene, seq)) {
float left_handle_frame = SEQ_time_left_handle_frame_get(scene, seq);
const float content_start = SEQ_time_start_frame_get(seq);
const float content_start = SEQ_time_start_frame_get(scene, seq);
immRectf(pos, left_handle_frame, y1, content_start, y2);
}
if (SEQ_time_has_right_still_frames(scene, seq)) {
@ -1315,7 +1315,7 @@ static void draw_seq_strip(const bContext *C,
SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG);
/* Draw strip body. */
x1 = SEQ_time_has_left_still_frames(scene, seq) ? SEQ_time_start_frame_get(seq) :
x1 = SEQ_time_has_left_still_frames(scene, seq) ? SEQ_time_start_frame_get(scene, seq) :
SEQ_time_left_handle_frame_get(scene, seq);
y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
x2 = SEQ_time_has_right_still_frames(scene, seq) ? SEQ_time_content_end_frame_get(scene, seq) :
@ -2280,9 +2280,8 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region)
if (seq == last_seq && (last_seq->flag & SELECT)) {
continue;
}
if (min_ii(SEQ_time_left_handle_frame_get(scene, seq), SEQ_time_start_frame_get(seq)) >
v2d->cur.xmax)
{
if (min_ii(SEQ_time_left_handle_frame_get(scene, seq),
SEQ_time_start_frame_get(scene, seq)) > v2d->cur.xmax) {
continue;
}
if (max_ii(SEQ_time_right_handle_frame_get(scene, seq),

View File

@ -74,22 +74,6 @@
/* Own include. */
#include "sequencer_intern.h"
/* -------------------------------------------------------------------- */
/** \name Structs & Enums
* \{ */
struct TransSeq {
int start, machine;
int startofs, endofs;
int anim_startofs, anim_endofs;
/* int final_left, final_right; */ /* UNUSED */
int len;
float content_start;
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Public Context Checks
* \{ */
@ -376,7 +360,8 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
SEQ_transform_sequence_can_be_translated(seq))
{
if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) {
SEQ_transform_translate_sequence(scene, seq, (snap_frame - seq->startofs) - seq->start);
const int offset = snap_frame - SEQ_time_left_handle_frame_get(scene, seq);
SEQ_transform_translate_sequence(scene, seq, offset);
}
else {
if (seq->flag & SEQ_LEFTSEL) {
@ -475,7 +460,14 @@ void SEQUENCER_OT_snap(wmOperatorType *ot)
/** \name Trim Strips Operator
* \{ */
struct SlipData {
typedef struct TransSeq {
int start;
int left_handle, right_handle;
int anim_startofs, anim_endofs;
int machine;
} TransSeq;
typedef struct SlipData {
int init_mouse[2];
float init_mouseloc[2];
TransSeq *ts;
@ -487,27 +479,24 @@ struct SlipData {
NumInput num_input;
};
static void transseq_backup(TransSeq *ts, Sequence *seq)
static void transseq_backup(TransSeq *ts, const Scene *scene, Sequence *seq)
{
ts->content_start = SEQ_time_start_frame_get(seq);
ts->start = seq->start;
ts->machine = seq->machine;
ts->startofs = seq->startofs;
ts->endofs = seq->endofs;
ts->start = SEQ_time_start_frame_get(scene, seq);
ts->left_handle = SEQ_time_left_handle_frame_get(scene, seq);
ts->right_handle = SEQ_time_right_handle_frame_get(scene, seq);
ts->anim_startofs = seq->anim_startofs;
ts->anim_endofs = seq->anim_endofs;
ts->len = seq->len;
ts->machine = seq->machine;
}
static void transseq_restore(TransSeq *ts, Sequence *seq)
static void transseq_restore(Scene *scene, TransSeq *ts, Sequence *seq)
{
seq->start = ts->start;
seq->machine = ts->machine;
seq->startofs = ts->startofs;
seq->endofs = ts->endofs;
SEQ_time_start_frame_set(scene, seq, ts->start);
SEQ_time_left_handle_frame_set(scene, seq, ts->left_handle);
SEQ_time_right_handle_frame_set(scene, seq, ts->right_handle);
seq->anim_startofs = ts->anim_startofs;
seq->anim_endofs = ts->anim_endofs;
seq->len = ts->len;
seq->machine = ts->machine;
}
static int slip_add_sequences_recursive(
@ -582,7 +571,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
slip_add_sequences_recursive(ed->seqbasep, data->seq_array, data->trim, 0, true);
for (int i = 0; i < num_seq; i++) {
transseq_backup(data->ts + i, data->seq_array[i]);
transseq_backup(data->ts + i, scene, data->seq_array[i]);
}
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
@ -603,13 +592,14 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
static void sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
{
for (int i = data->num_seq - 1; i >= 0; i--) {
Sequence *seq = data->seq_array[i];
seq->start = data->ts[i].start + offset;
if (data->trim[i]) {
seq->startofs = data->ts[i].startofs - offset;
seq->endofs = data->ts[i].endofs + offset;
if (!data->trim[i]) {
continue;
}
Sequence *seq = data->seq_array[i];
SEQ_time_start_frame_set(scene, seq, data->ts[i].start + offset);
SEQ_time_left_handle_frame_set(scene, seq, data->ts[i].left_handle);
SEQ_time_right_handle_frame_set(scene, seq, data->ts[i].right_handle);
}
for (int i = data->num_seq - 1; i >= 0; i--) {
@ -625,7 +615,8 @@ static void sequencer_slip_apply_limits(const Scene *scene, SlipData *data, int
if (data->trim[i]) {
Sequence *seq = data->seq_array[i];
int seq_content_start = data->ts[i].start + *offset;
int seq_content_end = seq_content_start + seq->len + seq->anim_startofs + seq->anim_endofs;
int seq_content_end = seq_content_start + SEQ_time_strip_length_get(scene, seq) +
seq->anim_startofs + seq->anim_endofs;
int diff = 0;
if (seq_content_start >= SEQ_time_right_handle_frame_get(scene, seq)) {
@ -663,7 +654,7 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
slip_add_sequences_recursive(ed->seqbasep, data->seq_array, data->trim, 0, true);
for (int i = 0; i < num_seq; i++) {
transseq_backup(data->ts + i, data->seq_array[i]);
transseq_backup(data->ts + i, scene, data->seq_array[i]);
}
sequencer_slip_apply_limits(scene, data, &offset);
@ -774,7 +765,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
case EVT_ESCKEY:
case RIGHTMOUSE: {
for (int i = 0; i < data->num_seq; i++) {
transseq_restore(data->ts + i, data->seq_array[i]);
transseq_restore(scene, data->ts + i, data->seq_array[i]);
}
for (int i = 0; i < data->num_seq; i++) {
@ -1272,7 +1263,7 @@ static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
last_seq->seq2 = seq2;
last_seq->seq3 = seq3;
int old_start = last_seq->start;
int old_start = SEQ_time_start_frame_get(scene, last_seq);
/* Force time position update for reassigned effects.
* TODO(Richard): This is because internally startdisp is still used, due to poor performance of
@ -1281,7 +1272,7 @@ static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
SEQ_time_left_handle_frame_set(scene, seq1, SEQ_time_left_handle_frame_get(scene, seq1));
SEQ_relations_invalidate_cache_preprocessed(scene, last_seq);
SEQ_offset_animdata(scene, last_seq, (last_seq->start - old_start));
SEQ_offset_animdata(scene, last_seq, (SEQ_time_start_frame_get(scene, last_seq) - old_start));
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@ -1783,7 +1774,10 @@ static int sequencer_offset_clear_exec(bContext *C, wmOperator * /*op*/)
seq = static_cast<Sequence *>(seq->next))
{
if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) {
seq->startofs = seq->endofs = 0;
const int start = SEQ_time_start_frame_get(scene, seq);
const int end = start + SEQ_time_strip_length_get(scene, seq);
SEQ_time_left_handle_frame_set(scene, seq, start);
SEQ_time_right_handle_frame_set(scene, seq, end);
}
}
@ -1848,7 +1842,8 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
SEQ_prefetch_stop(scene);
while (seq) {
if ((seq->flag & SELECT) && (seq->type == SEQ_TYPE_IMAGE) && (seq->len > 1)) {
if ((seq->flag & SELECT) && (seq->type == SEQ_TYPE_IMAGE) &&
SEQ_transform_single_image_check(seq)) {
Sequence *seq_next;
/* Remove seq so overlap tests don't conflict,
@ -3623,7 +3618,7 @@ static int sequencer_scene_frame_range_update_exec(bContext *C, wmOperator * /*o
Scene *target_scene = seq->scene;
seq->len = target_scene->r.efra - target_scene->r.sfra + 1;
SEQ_time_strip_length_set(scene, seq, target_scene->r.efra - target_scene->r.sfra + 1);
SEQ_time_left_handle_frame_set(scene, seq, old_start);
SEQ_time_right_handle_frame_set(scene, seq, old_end);

View File

@ -222,8 +222,9 @@ static void gizmo_retime_handle_add_draw(const bContext *C, wmGizmo *gz)
const Scene *scene = CTX_data_scene(C);
const Sequence *seq = active_seq_from_context(C);
const int frame_index = BKE_scene_frame_get(scene) - SEQ_time_start_frame_get(seq);
const SeqRetimingHandle *handle = SEQ_retiming_find_segment_start_handle(seq, frame_index);
const int frame_index = BKE_scene_frame_get(scene) - SEQ_time_start_frame_get(scene, seq);
const SeqRetimingHandle *handle = SEQ_retiming_find_segment_start_handle(
scene, seq, frame_index);
if (handle != nullptr && (SEQ_retiming_handle_is_transition_type(handle) ||
SEQ_retiming_handle_is_freeze_frame(handle)))
@ -407,7 +408,7 @@ static void gizmo_retime_handle_draw(const bContext *C, wmGizmo *gz)
{
RetimeHandleMoveGizmo *gizmo = (RetimeHandleMoveGizmo *)gz;
const View2D *v2d = UI_view2d_fromcontext(C);
const Scene *scene = CTX_data_scene(C);
/* TODO: This is hard-coded behavior, same as pre-select gizmos in 3D view.
* Better solution would be to check operator keymap and display this information in status bar
* and tool-tip. */
@ -429,7 +430,7 @@ static void gizmo_retime_handle_draw(const bContext *C, wmGizmo *gz)
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
Sequence *seq = active_seq_from_context(C);
SEQ_retiming_data_ensure(seq);
SEQ_retiming_data_ensure(scene, seq);
MutableSpan handles = SEQ_retiming_handles_get(seq);
for (const SeqRetimingHandle &handle : handles) {
@ -454,7 +455,7 @@ static int gizmo_retime_handle_test_select(bContext *C, wmGizmo *gz, const int m
gizmo->mouse_over_seq = nullptr;
Sequence *seq = active_seq_from_context(C);
SEQ_retiming_data_ensure(seq);
SEQ_retiming_data_ensure(scene, seq);
const SeqRetimingHandle *handle = mouse_over_handle_get(
scene, seq, UI_view2d_fromcontext(C), mval);
const int handle_index = SEQ_retiming_handle_index_get(seq, handle);
@ -531,7 +532,7 @@ static int gizmo_retime_remove_test_select(bContext *C, wmGizmo *gz, const int m
Scene *scene = CTX_data_scene(C);
Sequence *seq = active_seq_from_context(C);
SEQ_retiming_data_ensure(seq);
SEQ_retiming_data_ensure(scene, seq);
const SeqRetimingHandle *handle = mouse_over_handle_get(
scene, seq, UI_view2d_fromcontext(C), mval);
const int handle_index = SEQ_retiming_handle_index_get(seq, handle);
@ -594,22 +595,23 @@ void GIZMO_GT_retime_remove(wmGizmoType *gzt)
/** \name Retiming Speed Set Gizmo
* \{ */
static size_t label_str_get(const Sequence *seq,
static size_t label_str_get(const Scene *scene,
const Sequence *seq,
const SeqRetimingHandle *handle,
size_t str_len,
char *r_label_str)
{
const SeqRetimingHandle *next_handle = handle + 1;
if (SEQ_retiming_handle_is_transition_type(handle)) {
const float prev_speed = SEQ_retiming_handle_speed_get(seq, handle - 1);
const float next_speed = SEQ_retiming_handle_speed_get(seq, next_handle + 1);
const float prev_speed = SEQ_retiming_handle_speed_get(scene, seq, handle - 1);
const float next_speed = SEQ_retiming_handle_speed_get(scene, seq, next_handle + 1);
return BLI_snprintf_rlen(r_label_str,
str_len,
"%d%% - %d%%",
round_fl_to_int(prev_speed * 100.0f),
round_fl_to_int(next_speed * 100.0f));
}
const float speed = SEQ_retiming_handle_speed_get(seq, next_handle);
const float speed = SEQ_retiming_handle_speed_get(scene, seq, next_handle);
return BLI_snprintf_rlen(r_label_str, str_len, "%d%%", round_fl_to_int(speed * 100.0f));
}
@ -669,7 +671,7 @@ static void retime_speed_text_draw(const bContext *C,
char label_str[40];
rctf label_rect;
size_t label_len = label_str_get(seq, handle, sizeof(label_str), label_str);
size_t label_len = label_str_get(scene, seq, handle, sizeof(label_str), label_str);
if (!label_rect_get(C, seq, handle, label_str, label_len, &label_rect)) {
return; /* Not enough space to draw label. */
@ -683,6 +685,7 @@ static void retime_speed_text_draw(const bContext *C,
static void gizmo_retime_speed_set_draw(const bContext *C, wmGizmo * /* gz */)
{
const View2D *v2d = UI_view2d_fromcontext(C);
const Scene *scene = CTX_data_scene(C);
wmOrtho2_region_pixelspace(CTX_wm_region(C));
GPU_blend(GPU_BLEND_ALPHA);
@ -690,7 +693,7 @@ static void gizmo_retime_speed_set_draw(const bContext *C, wmGizmo * /* gz */)
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
Sequence *seq = active_seq_from_context(C);
SEQ_retiming_data_ensure(seq);
SEQ_retiming_data_ensure(scene, seq);
MutableSpan handles = SEQ_retiming_handles_get(seq);
for (const SeqRetimingHandle &handle : handles) {
@ -711,7 +714,7 @@ static int gizmo_retime_speed_set_test_select(bContext *C, wmGizmo *gz, const in
const View2D *v2d = UI_view2d_fromcontext(C);
Sequence *seq = active_seq_from_context(C);
SEQ_retiming_data_ensure(seq);
SEQ_retiming_data_ensure(scene, seq);
for (const SeqRetimingHandle &handle : SEQ_retiming_handles_get(seq)) {
if (SEQ_retiming_handle_is_transition_type(&handle)) {
@ -720,7 +723,7 @@ static int gizmo_retime_speed_set_test_select(bContext *C, wmGizmo *gz, const in
char label_str[40];
rctf label_rect;
size_t label_len = label_str_get(seq, &handle, sizeof(label_str), label_str);
size_t label_len = label_str_get(scene, seq, &handle, sizeof(label_str), label_str);
if (!label_rect_get(C, seq, &handle, label_str, label_len, &label_rect)) {
continue;

View File

@ -325,7 +325,7 @@ static int sequesequencer_retiming_handle_add_exec(bContext *C, wmOperator *op)
const Editing *ed = SEQ_editing_get(scene);
Sequence *seq = ed->act_seq;
SEQ_retiming_data_ensure(seq);
SEQ_retiming_data_ensure(scene, seq);
float timeline_frame;
if (RNA_struct_property_is_set(op->ptr, "timeline_frame")) {
@ -335,8 +335,9 @@ static int sequesequencer_retiming_handle_add_exec(bContext *C, wmOperator *op)
timeline_frame = BKE_scene_frame_get(scene);
}
const int frame_index = BKE_scene_frame_get(scene) - SEQ_time_start_frame_get(seq);
const SeqRetimingHandle *handle = SEQ_retiming_find_segment_start_handle(seq, frame_index);
const int frame_index = BKE_scene_frame_get(scene) - SEQ_time_start_frame_get(scene, seq);
const SeqRetimingHandle *handle = SEQ_retiming_find_segment_start_handle(
scene, seq, frame_index);
if (SEQ_retiming_handle_is_transition_type(handle)) {
BKE_report(op->reports, RPT_ERROR, "Can not create handle inside of speed transition");
@ -509,7 +510,7 @@ static int sequencer_retiming_segment_speed_set_invoke(bContext *C,
return OPERATOR_CANCELLED;
}
RNA_float_set(op->ptr, "speed", SEQ_retiming_handle_speed_get(seq, handle) * 100.0f);
RNA_float_set(op->ptr, "speed", SEQ_retiming_handle_speed_get(scene, seq, handle) * 100.0f);
RNA_int_set(op->ptr, "handle_index", SEQ_retiming_handle_index_get(seq, handle));
return WM_operator_props_popup(C, op, event);
}

View File

@ -75,9 +75,8 @@ static bool check_seq_need_thumbnails(const Scene *scene, Sequence *seq, rctf *v
if (!ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE)) {
return false;
}
if (min_ii(SEQ_time_left_handle_frame_get(scene, seq), SEQ_time_start_frame_get(seq)) >
view_area->xmax)
{
if (min_ii(SEQ_time_left_handle_frame_get(scene, seq), SEQ_time_start_frame_get(scene, seq)) >
view_area->xmax) {
return false;
}
if (max_ii(SEQ_time_right_handle_frame_get(scene, seq),

View File

@ -181,7 +181,8 @@ static TransData *SeqToTransData(Scene *scene,
* tdsq->start_offset is used when flushing the tx data back */
start_left = SEQ_time_left_handle_frame_get(scene, seq);
td2d->loc[0] = start_left;
tdsq->start_offset = start_left - seq->start; /* use to apply the original location */
tdsq->start_offset = start_left - SEQ_time_start_frame_get(
scene, seq); /* use to apply the original location */
break;
case SEQ_LEFTSEL:
start_left = SEQ_time_left_handle_frame_get(scene, seq);
@ -604,7 +605,7 @@ static void flushTransSeq(TransInfo *t)
switch (tdsq->sel_flag) {
case SELECT: {
if (SEQ_transform_sequence_can_be_translated(seq)) {
offset = new_frame - tdsq->start_offset - seq->start;
offset = new_frame - tdsq->start_offset - SEQ_time_start_frame_get(scene, seq);
SEQ_transform_translate_sequence(scene, seq, offset);
if (abs(offset) > abs(max_offset)) {
max_offset = offset;

View File

@ -205,11 +205,12 @@ static void seq_snap_target_points_build(Scene *scene,
if (snap_mode & SEQ_SNAP_TO_STRIP_HOLD) {
int content_start = min_ii(SEQ_time_left_handle_frame_get(scene, seq),
SEQ_time_start_frame_get(seq));
SEQ_time_start_frame_get(scene, seq));
int content_end = max_ii(SEQ_time_right_handle_frame_get(scene, seq),
SEQ_time_content_end_frame_get(scene, seq));
/* Effects and single image strips produce incorrect content length. Skip these strips. */
if ((seq->type & SEQ_TYPE_EFFECT) != 0 || seq->len == 1) {
if ((seq->type & SEQ_TYPE_EFFECT) != 0 ||
seq->len == 1) { // XXX - this has to have some flag. it can't rely on precise length.
content_start = SEQ_time_left_handle_frame_get(scene, seq);
content_end = SEQ_time_right_handle_frame_get(scene, seq);
}

View File

@ -128,13 +128,13 @@ typedef enum eSeqRetimingHandleFlag {
} eSeqRetimingHandleFlag;
typedef struct SeqRetimingHandle {
int strip_frame_index;
int flag; /* eSeqRetimingHandleFlag */
int _pad0;
double strip_frame_index; /* -> strip_position in seconds. */
int flag; /* eSeqRetimingHandleFlag */
int _pad0[2];
float retiming_factor; /* Value between 0-1 mapped to original content range. */
int original_strip_frame_index; /* Used for transition handles only. */
float original_retiming_factor; /* Used for transition handles only. */
double original_strip_frame_index; /* Used for transition handles only. */
double original_retiming_factor; /* Used for transition handles only. */
} SeqRetimingHandle;
typedef struct SequenceRuntime {
@ -163,17 +163,17 @@ typedef struct Sequence {
/** Flags bitmap (see below) and the type of sequence. */
int flag, type;
/** The length of the contents of this strip - before handles are applied. */
int len;
double len;
/**
* Start frame of contents of strip in absolute frame coordinates.
* For meta-strips start of first strip startdisp.
*/
float start;
double start;
/**
* Frames after the first frame where display starts,
* frames before the last frame where display ends.
*/
float startofs, endofs;
double startofs, endofs;
/**
* Frames that use the first frame before data begins,
* frames that use the last frame after data ends.

View File

@ -337,7 +337,7 @@ static void rna_Sequence_retiming_handle_remove(ID *id, SeqRetimingHandle *handl
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
}
static int rna_Sequence_retiming_handle_frame_get(PointerRNA *ptr)
static float rna_Sequence_retiming_handle_frame_get(PointerRNA *ptr)
{
SeqRetimingHandle *handle = (SeqRetimingHandle *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
@ -347,10 +347,10 @@ static int rna_Sequence_retiming_handle_frame_get(PointerRNA *ptr)
return 0;
}
return SEQ_time_start_frame_get(seq) + handle->strip_frame_index;
return SEQ_time_start_frame_get(scene, seq) + handle->strip_frame_index;
}
static void rna_Sequence_retiming_handle_frame_set(PointerRNA *ptr, int value)
static void rna_Sequence_retiming_handle_frame_set(PointerRNA *ptr, float value)
{
SeqRetimingHandle *handle = (SeqRetimingHandle *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
@ -360,7 +360,7 @@ static void rna_Sequence_retiming_handle_frame_set(PointerRNA *ptr, int value)
return;
}
const int offset = value - (SEQ_time_start_frame_get(seq) + handle->strip_frame_index);
const int offset = value - SEQ_time_start_frame_get(scene, seq) + handle->strip_frame_index;
SEQ_retiming_offset_handle(scene, seq, handle, offset);
SEQ_relations_invalidate_cache_raw(scene, seq);
}
@ -431,18 +431,39 @@ static void rna_Sequence_start_frame_set(PointerRNA *ptr, float value)
Sequence *seq = (Sequence *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
SEQ_transform_translate_sequence(scene, seq, value - seq->start);
SEQ_transform_translate_sequence(scene, seq, value - SEQ_time_start_frame_get(scene, seq));
do_sequence_frame_change_update(scene, seq);
SEQ_relations_invalidate_cache_composite(scene, seq);
}
static float rna_Sequence_start_frame_get(PointerRNA *ptr)
{
Sequence *seq = (Sequence *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
return SEQ_time_start_frame_get(scene, seq);
}
static float rna_Sequence_frame_offset_start_get(PointerRNA *ptr)
{
Sequence *seq = (Sequence *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
return SEQ_time_seconds_to_frames(scene, seq->startofs);
}
static float rna_Sequence_frame_offset_end_get(PointerRNA *ptr)
{
Sequence *seq = (Sequence *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
return SEQ_time_seconds_to_frames(scene, seq->endofs);
}
static void rna_Sequence_frame_offset_start_set(PointerRNA *ptr, float value)
{
Sequence *seq = (Sequence *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
SEQ_relations_invalidate_cache_composite(scene, seq);
seq->startofs = value;
seq->startofs = SEQ_time_frames_to_seconds(scene, value);
}
static void rna_Sequence_frame_offset_end_set(PointerRNA *ptr, float value)
@ -451,7 +472,7 @@ static void rna_Sequence_frame_offset_end_set(PointerRNA *ptr, float value)
Scene *scene = (Scene *)ptr->owner_id;
SEQ_relations_invalidate_cache_composite(scene, seq);
seq->endofs = value;
seq->endofs = SEQ_time_frames_to_seconds(scene, value);
}
static void rna_Sequence_anim_startofs_final_set(PointerRNA *ptr, int value)
@ -498,19 +519,21 @@ static void rna_Sequence_frame_offset_start_range(
PointerRNA *ptr, float *min, float *max, float *UNUSED(softmin), float *UNUSED(softmax))
{
Sequence *seq = (Sequence *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
*min = ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD) ? 0 : INT_MIN;
*max = seq->len - seq->endofs - 1;
*max = SEQ_time_seconds_to_frames(scene, seq->len - seq->endofs) - 1;
}
static void rna_Sequence_frame_offset_end_range(
PointerRNA *ptr, float *min, float *max, float *UNUSED(softmin), float *UNUSED(softmax))
{
Sequence *seq = (Sequence *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
*min = ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD) ? 0 : INT_MIN;
*max = seq->len - seq->startofs - 1;
*max = SEQ_time_seconds_to_frames(scene, seq->len - seq->startofs) - 1;
}
static void rna_Sequence_frame_length_set(PointerRNA *ptr, int value)
static void rna_Sequence_frame_final_duration_set(PointerRNA *ptr, int value)
{
Sequence *seq = (Sequence *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
@ -520,13 +543,20 @@ static void rna_Sequence_frame_length_set(PointerRNA *ptr, int value)
SEQ_relations_invalidate_cache_composite(scene, seq);
}
static int rna_Sequence_frame_length_get(PointerRNA *ptr)
static int rna_Sequence_frame_final_duration_get(PointerRNA *ptr)
{
Sequence *seq = (Sequence *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
return SEQ_time_right_handle_frame_get(scene, seq) - SEQ_time_left_handle_frame_get(scene, seq);
}
static int rna_Sequence_frame_duration_get(PointerRNA *ptr)
{
Sequence *seq = (Sequence *)ptr->data;
Scene *scene = (Scene *)ptr->owner_id;
return SEQ_time_strip_length_get(scene, seq);
}
static int rna_Sequence_frame_editable(PointerRNA *ptr, const char **UNUSED(r_info))
{
Sequence *seq = (Sequence *)ptr->data;
@ -1594,12 +1624,12 @@ static void rna_def_retiming_handle(BlenderRNA *brna)
"Handle mapped to particular frame that can be moved to change playback speed");
RNA_def_struct_sdna(srna, "SeqRetimingHandle");
prop = RNA_def_property(srna, "timeline_frame", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "strip_frame_index");
RNA_def_property_int_funcs(prop,
"rna_Sequence_retiming_handle_frame_get",
"rna_Sequence_retiming_handle_frame_set",
NULL);
prop = RNA_def_property(srna, "timeline_frame", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "strip_frame_index");
RNA_def_property_float_funcs(prop,
"rna_Sequence_retiming_handle_frame_get",
"rna_Sequence_retiming_handle_frame_set",
NULL);
RNA_def_property_ui_text(prop, "Timeline Frame", "Position of retiming handle in timeline");
FunctionRNA *func = RNA_def_function(srna, "remove", "rna_Sequence_retiming_handle_remove");
@ -2111,32 +2141,34 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
prop, "Length", "The length of the contents of this strip after the handles are applied");
RNA_def_property_int_funcs(
prop, "rna_Sequence_frame_length_get", "rna_Sequence_frame_length_set", NULL);
RNA_def_property_int_funcs(prop,
"rna_Sequence_frame_final_duration_get",
"rna_Sequence_frame_final_duration_set",
NULL);
RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable");
RNA_def_property_update(
prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "frame_duration", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "len");
RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_ANIMATABLE);
RNA_def_property_range(prop, 1, MAXFRAME);
RNA_def_property_ui_text(
prop, "Length", "The length of the contents of this strip before the handles are applied");
RNA_def_property_int_funcs(prop, "rna_Sequence_frame_duration_get", NULL, NULL);
prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "start");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Start Frame", "X position where the strip begins");
RNA_def_property_ui_range(prop, MINFRAME, MAXFRAME, 100.0f, 0);
RNA_def_property_float_funcs(
prop, NULL, "rna_Sequence_start_frame_set", NULL); /* overlap tests and calc_seq_disp */
RNA_def_property_ui_range(prop, MINFRAME, MAXFRAME, 3, 0);
RNA_def_property_float_funcs(prop,
"rna_Sequence_start_frame_get",
"rna_Sequence_start_frame_set",
NULL); /* overlap tests and calc_seq_disp */
RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable");
RNA_def_property_update(
prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "frame_final_start", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "startdisp");
RNA_def_property_int_funcs(
prop, "rna_Sequence_frame_final_start_get", "rna_Sequence_start_frame_final_set", NULL);
RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable");
@ -2151,7 +2183,6 @@ static void rna_def_sequence(BlenderRNA *brna)
prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "frame_final_end", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "enddisp");
RNA_def_property_int_funcs(
prop, "rna_Sequence_frame_final_end_get", "rna_Sequence_end_frame_final_set", NULL);
RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable");
@ -2164,20 +2195,22 @@ static void rna_def_sequence(BlenderRNA *brna)
prop = RNA_def_property(srna, "frame_offset_start", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "startofs");
// RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
RNA_def_property_ui_text(prop, "Start Offset", "");
RNA_def_property_ui_range(prop, MINFRAME, MAXFRAME, 100.0f, 0);
RNA_def_property_float_funcs(
prop, NULL, "rna_Sequence_frame_offset_start_set", "rna_Sequence_frame_offset_start_range");
RNA_def_property_float_funcs(prop,
"rna_Sequence_frame_offset_start_get",
"rna_Sequence_frame_offset_start_set",
"rna_Sequence_frame_offset_start_range");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_frame_change_update");
prop = RNA_def_property(srna, "frame_offset_end", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "endofs");
// RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
RNA_def_property_ui_text(prop, "End Offset", "");
RNA_def_property_ui_range(prop, MINFRAME, MAXFRAME, 100.0f, 0);
RNA_def_property_float_funcs(
prop, NULL, "rna_Sequence_frame_offset_end_set", "rna_Sequence_frame_offset_end_range");
RNA_def_property_float_funcs(prop,
"rna_Sequence_frame_offset_end_get",
"rna_Sequence_frame_offset_end_set",
"rna_Sequence_frame_offset_end_range");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_frame_change_update");
prop = RNA_def_property(srna, "channel", PROP_INT, PROP_UNSIGNED);

View File

@ -578,9 +578,10 @@ static StripElem *rna_SequenceElements_append(ID *id, Sequence *seq, const char
seq->strip->stripdata = se = MEM_reallocN(seq->strip->stripdata,
sizeof(StripElem) * (seq->len + 1));
se += seq->len;
STRNCPY(se->filename, filename);
seq->len++;
/* se += seq->len; // XXX get size of se before realloc...
BLI_strncpy(se->name, filename, sizeof(se->name));
seq->len++;*/
seq->flag &= ~SEQ_SINGLE_FRAME_CONTENT;

View File

@ -18,7 +18,7 @@ struct SeqRetimingHandle;
int SEQ_retiming_handles_count(const struct Sequence *seq);
bool SEQ_retiming_is_active(const struct Sequence *seq);
void SEQ_retiming_data_ensure(struct Sequence *seq);
void SEQ_retiming_data_ensure(const struct Scene *scene, struct Sequence *seq);
void SEQ_retiming_data_clear(struct Sequence *seq);
bool SEQ_retiming_is_allowed(const struct Sequence *seq);
@ -46,7 +46,8 @@ void SEQ_retiming_offset_handle(const struct Scene *scene,
struct Sequence *seq,
struct SeqRetimingHandle *handle,
const int offset);
float SEQ_retiming_handle_speed_get(const struct Sequence *seq,
float SEQ_retiming_handle_speed_get(const struct Scene *scene,
const struct Sequence *seq,
const struct SeqRetimingHandle *handle);
void SEQ_retiming_handle_speed_set(const struct Scene *scene,
struct Sequence *seq,
@ -58,7 +59,8 @@ void SEQ_retiming_sound_animation_data_set(const struct Scene *scene, const stru
float SEQ_retiming_handle_timeline_frame_get(const struct Scene *scene,
const struct Sequence *seq,
const struct SeqRetimingHandle *handle);
const SeqRetimingHandle *SEQ_retiming_find_segment_start_handle(const struct Sequence *seq,
const SeqRetimingHandle *SEQ_retiming_find_segment_start_handle(const struct Scene *scene,
const struct Sequence *seq,
const int frame_index);
bool SEQ_retiming_handle_is_transition_type(const struct SeqRetimingHandle *handle);
bool SEQ_retiming_handle_is_freeze_frame(const struct SeqRetimingHandle *handle);

View File

@ -67,7 +67,7 @@ struct ListBase *SEQ_active_seqbase_get(const struct Editing *ed);
* \param seqbase: ListBase with strips
*/
void SEQ_seqbase_active_set(struct Editing *ed, struct ListBase *seqbase);
struct Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type);
struct Sequence *SEQ_sequence_alloc(ListBase *lb, double start_time, int machine, int type);
void SEQ_sequence_free(struct Scene *scene, struct Sequence *seq);
/**
* Get #MetaStack that corresponds to current level that is being viewed

View File

@ -114,6 +114,10 @@ void SEQ_time_right_handle_frame_set(const struct Scene *scene,
* This can change depending on scene FPS or strip speed factor.
*/
int SEQ_time_strip_length_get(const struct Scene *scene, const struct Sequence *seq);
void SEQ_time_strip_length_set(const struct Scene *scene,
struct Sequence *seq,
const double length_in_frames);
/**
* Set strip playback speed.
* Strip length is affected by changing speed factor.
@ -124,7 +128,7 @@ void SEQ_time_speed_factor_set(const struct Scene *scene,
/**
* Get timeline frame where strip content starts.
*/
float SEQ_time_start_frame_get(const struct Sequence *seq);
float SEQ_time_start_frame_get(const struct Scene *scene, const struct Sequence *seq);
/**
* Get timeline frame where strip content ends.
*/
@ -141,6 +145,9 @@ void SEQ_time_start_frame_set(const struct Scene *scene, struct Sequence *seq, i
* \note this function is currently only used internally and in versioning code.
*/
void SEQ_time_update_meta_strip_range(const struct Scene *scene, struct Sequence *seq_meta);
double SEQ_time_frames_to_seconds(const struct Scene *scene, const double frames);
int SEQ_time_seconds_to_frames(const struct Scene *scene, const double seconds);
#ifdef __cplusplus
}
#endif

View File

@ -24,7 +24,8 @@ void SEQ_sequence_base_unique_name_recursive(struct Scene *scene,
struct ListBase *seqbasep,
struct Sequence *seq);
const char *SEQ_sequence_give_name(struct Sequence *seq);
struct ListBase *SEQ_get_seqbase_from_sequence(struct Sequence *seq,
struct ListBase *SEQ_get_seqbase_from_sequence(const struct Scene *scene,
struct Sequence *seq,
struct ListBase **channels,
int *r_offset);
const struct Sequence *SEQ_get_topmost_sequence(const struct Scene *scene, int frame);

View File

@ -395,7 +395,7 @@ static void seq_disk_cache_delete_invalid_files(SeqDiskCache *disk_cache,
if (cache_file->cache_type & invalidate_types) {
if (STREQ(cache_dir, cache_file->dir)) {
int timeline_frame_start = seq_cache_frame_index_to_timeline_frame(
seq, cache_file->start_frame);
scene, seq, cache_file->start_frame);
if (timeline_frame_start > range_start && timeline_frame_start <= range_end) {
seq_disk_cache_delete_file(disk_cache, cache_file);
}

View File

@ -146,12 +146,12 @@ static float seq_cache_timeline_frame_to_frame_index(Scene *scene,
return SEQ_give_frame_index(scene, seq, timeline_frame);
}
return timeline_frame - SEQ_time_start_frame_get(seq);
return timeline_frame - SEQ_time_start_frame_get(scene, seq);
}
float seq_cache_frame_index_to_timeline_frame(Sequence *seq, float frame_index)
float seq_cache_frame_index_to_timeline_frame(const Scene *scene, Sequence *seq, float frame_index)
{
return frame_index + SEQ_time_start_frame_get(seq);
return frame_index + SEQ_time_start_frame_get(scene, seq);
}
static SeqCache *seq_cache_get_from_scene(Scene *scene)

View File

@ -70,7 +70,9 @@ void seq_cache_cleanup_sequence(struct Scene *scene,
bool force_seq_changed_range);
void seq_cache_thumbnail_cleanup(Scene *scene, rctf *view_area);
bool seq_cache_is_full(void);
float seq_cache_frame_index_to_timeline_frame(struct Sequence *seq, float frame_index);
float seq_cache_frame_index_to_timeline_frame(const struct Scene *scene,
struct Sequence *seq,
float frame_index);
#ifdef __cplusplus
}

View File

@ -1646,7 +1646,7 @@ static ImBuf *do_render_strip_seqbase(const SeqRenderData *context,
ListBase *channels = NULL;
int offset;
seqbase = SEQ_get_seqbase_from_sequence(seq, &channels, &offset);
seqbase = SEQ_get_seqbase_from_sequence(context->scene, seq, &channels, &offset);
if (seqbase && !BLI_listbase_is_empty(seqbase)) {
@ -2190,7 +2190,7 @@ void SEQ_render_thumbnails(const SeqRenderData *context,
int SEQ_render_thumbnails_guaranteed_set_frame_step_get(const Scene *scene, const Sequence *seq)
{
const int content_start = max_ii(SEQ_time_left_handle_frame_get(scene, seq),
SEQ_time_start_frame_get(seq));
SEQ_time_start_frame_get(scene, seq));
const int content_end = min_ii(SEQ_time_right_handle_frame_get(scene, seq),
SEQ_time_content_end_frame_get(scene, seq));
const int content_len = content_end - content_start;

View File

@ -113,7 +113,7 @@ static void seq_free_strip(Strip *strip)
MEM_freeN(strip);
}
Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type)
Sequence *SEQ_sequence_alloc(ListBase *lb, double start_time, int machine, int type)
{
Sequence *seq;
@ -124,7 +124,7 @@ Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int
seq->name[2] = 0;
seq->flag = SELECT;
seq->start = timeline_frame;
seq->start = start_time;
seq->machine = machine;
seq->sat = 1.0;
seq->mul = 1.0;

View File

@ -47,15 +47,12 @@ static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene,
continue;
}
int old = seq->len;
float fac;
seq->len = MAX2(1, round((info.length - seq->sound->offset_time) * FPS));
fac = (float)seq->len / (float)old;
old = seq->startofs;
seq->startofs *= fac;
seq->endofs *= fac;
seq->start += (old - seq->startofs); /* So that visual/"real" start frame does not change! */
const int left_handle = SEQ_time_left_handle_frame_get(scene, seq);
const int right_handle = SEQ_time_right_handle_frame_get(scene, seq);
SEQ_time_strip_length_set(
scene, seq, MAX2(1, round((info.length - seq->sound->offset_time) * FPS)));
SEQ_time_left_handle_frame_set(scene, seq, left_handle);
SEQ_time_right_handle_frame_set(scene, seq, right_handle);
changed = true;
}
@ -98,7 +95,8 @@ void SEQ_sound_update_bounds(Scene *scene, Sequence *seq)
if (seq->type == SEQ_TYPE_SCENE) {
if (seq->scene && seq->scene_sound) {
/* We have to take into account start frame of the sequence's scene! */
int startofs = seq->startofs + seq->anim_startofs + seq->scene->r.sfra;
int startofs = SEQ_time_seconds_to_frames(scene, seq->startofs + seq->anim_startofs) +
seq->scene->r.sfra;
BKE_sound_move_scene_sound(scene,
seq->scene_sound,

View File

@ -128,7 +128,7 @@ Sequence *SEQ_add_scene_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_SCENE);
seq->scene = load_data->scene;
seq->len = load_data->scene->r.efra - load_data->scene->r.sfra + 1;
SEQ_time_strip_length_set(scene, seq, load_data->scene->r.efra - load_data->scene->r.sfra + 1);
id_us_ensure_real((ID *)load_data->scene);
seq_add_set_name(scene, seq, load_data);
seq_add_generic_update(scene, seq);
@ -140,7 +140,7 @@ Sequence *SEQ_add_movieclip_strip(Scene *scene, ListBase *seqbase, SeqLoadData *
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MOVIECLIP);
seq->clip = load_data->clip;
seq->len = BKE_movieclip_get_duration(load_data->clip);
SEQ_time_strip_length_set(scene, seq, BKE_movieclip_get_duration(load_data->clip));
id_us_ensure_real((ID *)load_data->clip);
seq_add_set_name(scene, seq, load_data);
seq_add_generic_update(scene, seq);
@ -152,7 +152,7 @@ Sequence *SEQ_add_mask_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MASK);
seq->mask = load_data->mask;
seq->len = BKE_mask_get_duration(load_data->mask);
SEQ_time_strip_length_set(scene, seq, BKE_mask_get_duration(load_data->mask));
id_us_ensure_real((ID *)load_data->mask);
seq_add_set_name(scene, seq, load_data);
seq_add_generic_update(scene, seq);
@ -161,8 +161,10 @@ Sequence *SEQ_add_mask_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_
Sequence *SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
{
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, load_data->effect.type);
Sequence *seq = SEQ_sequence_alloc(seqbase,
SEQ_time_frames_to_seconds(scene, load_data->start_frame),
load_data->channel,
load_data->effect.type);
seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
struct SeqEffectHandle sh = SEQ_effect_handle_get(seq);
@ -176,7 +178,7 @@ Sequence *SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, SeqLoadData *loa
}
if (!load_data->effect.seq1) {
seq->len = 1; /* Effect is generator, set non zero length. */
SEQ_time_strip_length_set(scene, seq, 0);
seq->flag |= SEQ_SINGLE_FRAME_CONTENT;
SEQ_time_right_handle_frame_set(scene, seq, load_data->effect.end_frame);
}
@ -196,7 +198,7 @@ void SEQ_add_image_set_directory(Sequence *seq, const char *dirpath)
void SEQ_add_image_load_file(Scene *scene, Sequence *seq, size_t strip_frame, const char *filename)
{
StripElem *se = SEQ_render_give_stripelem(
scene, seq, SEQ_time_start_frame_get(seq) + strip_frame);
scene, seq, SEQ_time_start_frame_get(scene, seq) + strip_frame);
STRNCPY(se->filename, filename);
}
@ -234,7 +236,7 @@ Sequence *SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
{
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_IMAGE);
seq->len = load_data->image.len;
SEQ_time_strip_length_set(scene, seq, load_data->image.len);
Strip *strip = seq->strip;
strip->stripdata = MEM_callocN(load_data->image.len * sizeof(StripElem), "stripelem");
@ -322,7 +324,7 @@ Sequence *SEQ_add_sound_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
* nearest frame as the audio track usually overshoots or undershoots the
* end frame of the video by a little bit.
* See #47135 for under shoot example. */
seq->len = MAX2(1, round((info.length - sound->offset_time) * FPS));
SEQ_time_strip_length_set(scene, seq, MAX2(1, round((info.length - sound->offset_time) * FPS)));
Strip *strip = seq->strip;
/* We only need 1 element to store the filename. */
@ -447,8 +449,10 @@ Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
load_data->r_video_stream_start = IMD_anim_get_offset(anim_arr[0]);
}
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MOVIE);
Sequence *seq = SEQ_sequence_alloc(seqbase,
SEQ_time_frames_to_seconds(scene, load_data->start_frame),
load_data->channel,
SEQ_TYPE_MOVIE);
/* Multiview settings. */
if (load_data->use_multiview) {
@ -471,7 +475,7 @@ Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
}
if (anim_arr[0] != NULL) {
seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN);
SEQ_time_strip_length_set(scene, seq, IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN));
IMB_anim_load_metadata(anim_arr[0]);
@ -488,7 +492,7 @@ Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
}
}
seq->len = MAX2(1, seq->len);
seq->len = MAX2(SEQ_time_frames_to_seconds(scene, 1), seq->len); // XXX
if (load_data->adjust_playback_rate) {
seq->flag |= SEQ_AUTO_PLAYBACK_RATE;
}
@ -536,17 +540,17 @@ void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const boo
prev_enddisp = SEQ_time_right_handle_frame_get(scene, seq);
}
int length;
switch (seq->type) {
case SEQ_TYPE_IMAGE: {
/* Hack? */
size_t olen = MEM_allocN_len(seq->strip->stripdata) / sizeof(StripElem);
seq->len = olen;
seq->len -= seq->anim_startofs;
seq->len -= seq->anim_endofs;
if (seq->len < 0) {
seq->len = 0;
length = olen - seq->anim_startofs - seq->anim_endofs;
if (length < 0) {
length = 0;
}
SEQ_time_strip_length_set(scene, seq, length);
break;
}
case SEQ_TYPE_MOVIE: {
@ -614,14 +618,15 @@ void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const boo
IMB_anim_load_metadata(sanim->anim);
seq->len = IMB_anim_get_duration(
length = IMB_anim_get_duration(
sanim->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN);
seq->len -= seq->anim_startofs;
seq->len -= seq->anim_endofs;
if (seq->len < 0) {
seq->len = 0;
length -= seq->anim_startofs;
length -= seq->anim_endofs;
if (length < 0) {
length = 0;
}
SEQ_time_strip_length_set(scene, seq, length);
break;
}
case SEQ_TYPE_MOVIECLIP:
@ -629,48 +634,52 @@ void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const boo
return;
}
seq->len = BKE_movieclip_get_duration(seq->clip);
length = BKE_movieclip_get_duration(seq->clip);
seq->len -= seq->anim_startofs;
seq->len -= seq->anim_endofs;
if (seq->len < 0) {
seq->len = 0;
length -= seq->anim_startofs;
length -= seq->anim_endofs;
if (length < 0) {
length = 0;
}
SEQ_time_strip_length_set(scene, seq, length);
break;
case SEQ_TYPE_MASK:
if (seq->mask == NULL) {
return;
}
seq->len = BKE_mask_get_duration(seq->mask);
seq->len -= seq->anim_startofs;
seq->len -= seq->anim_endofs;
if (seq->len < 0) {
seq->len = 0;
length = BKE_mask_get_duration(seq->mask);
length -= seq->anim_startofs;
length -= seq->anim_endofs;
if (length < 0) {
length = 0;
}
SEQ_time_strip_length_set(scene, seq, length);
break;
case SEQ_TYPE_SOUND_RAM:
#ifdef WITH_AUDASPACE
if (!seq->sound) {
return;
}
seq->len = ceil((double)BKE_sound_get_length(bmain, seq->sound) * FPS);
seq->len -= seq->anim_startofs;
seq->len -= seq->anim_endofs;
if (seq->len < 0) {
seq->len = 0;
length = ceil((double)BKE_sound_get_length(bmain, seq->sound) * FPS);
length -= seq->anim_startofs;
length -= seq->anim_endofs;
if (length < 0) {
length = 0;
}
SEQ_time_strip_length_set(scene, seq, length);
#else
UNUSED_VARS(bmain);
return;
#endif
break;
case SEQ_TYPE_SCENE: {
seq->len = (seq->scene) ? seq->scene->r.efra - seq->scene->r.sfra + 1 : 0;
seq->len -= seq->anim_startofs;
seq->len -= seq->anim_endofs;
if (seq->len < 0) {
seq->len = 0;
length = (seq->scene) ? seq->scene->r.efra - seq->scene->r.sfra + 1 : 0;
length -= seq->anim_startofs;
length -= seq->anim_endofs;
if (length < 0) {
length = 0;
}
SEQ_time_strip_length_set(scene, seq, length);
break;
}
}

View File

@ -264,7 +264,7 @@ static void seq_split_set_right_hold_offset(Main *bmain,
Sequence *seq,
int timeline_frame)
{
const float content_start = SEQ_time_start_frame_get(seq);
const float content_start = SEQ_time_start_frame_get(scene, seq);
const float content_end = SEQ_time_content_end_frame_get(scene, seq);
/* Adjust within range of extended still-frames before strip. */
@ -290,7 +290,7 @@ static void seq_split_set_left_hold_offset(Main *bmain,
Sequence *seq,
int timeline_frame)
{
const float content_start = SEQ_time_start_frame_get(seq);
const float content_start = SEQ_time_start_frame_get(scene, seq);
const float content_end = SEQ_time_content_end_frame_get(scene, seq);
/* Adjust within range of strip contents. */

View File

@ -65,7 +65,8 @@ static bool seq_retiming_is_last_handle(const Sequence *seq, const SeqRetimingHa
return SEQ_retiming_handle_index_get(seq, handle) == seq->retiming_handle_num - 1;
}
const SeqRetimingHandle *SEQ_retiming_find_segment_start_handle(const Sequence *seq,
const SeqRetimingHandle *SEQ_retiming_find_segment_start_handle(const Scene *scene,
const Sequence *seq,
const int frame_index)
{
const SeqRetimingHandle *start_handle = nullptr;
@ -73,7 +74,7 @@ const SeqRetimingHandle *SEQ_retiming_find_segment_start_handle(const Sequence *
if (seq_retiming_is_last_handle(seq, &handle)) {
break;
}
if (handle.strip_frame_index > frame_index) {
if (handle.strip_frame_index > SEQ_time_frames_to_seconds(scene, frame_index)) {
break;
}
@ -88,7 +89,7 @@ int SEQ_retiming_handles_count(const Sequence *seq)
return seq->retiming_handle_num;
}
void SEQ_retiming_data_ensure(Sequence *seq)
void SEQ_retiming_data_ensure(const Scene *scene, Sequence *seq)
{
if (!SEQ_retiming_is_allowed(seq)) {
return;
@ -129,16 +130,19 @@ bool SEQ_retiming_is_allowed(const Sequence *seq)
SEQ_TYPE_MASK);
}
static int seq_retiming_segment_length_get(const SeqRetimingHandle *start_handle)
static int seq_retiming_segment_length_get(const Scene *scene,
const SeqRetimingHandle *start_handle)
{
const SeqRetimingHandle *end_handle = start_handle + 1;
return end_handle->strip_frame_index - start_handle->strip_frame_index;
return SEQ_time_seconds_to_frames(
scene, end_handle->strip_frame_index - start_handle->strip_frame_index);
}
static float seq_retiming_segment_step_get(const SeqRetimingHandle *start_handle)
static float seq_retiming_segment_step_get(const Scene *scene,
const SeqRetimingHandle *start_handle)
{
const SeqRetimingHandle *end_handle = start_handle + 1;
const int segment_length = seq_retiming_segment_length_get(start_handle);
const int segment_length = seq_retiming_segment_length_get(scene, start_handle);
const float segment_fac_diff = end_handle->retiming_factor - start_handle->retiming_factor;
return segment_fac_diff / segment_length;
}
@ -199,41 +203,45 @@ bool SEQ_retiming_handle_is_freeze_frame(const SeqRetimingHandle *handle)
/* Check colinearity of 2 segments allowing for some imprecision.
* `isect_seg_seg_v2_lambda_mu_db()` return value does not work well in this case. */
static bool seq_retiming_transition_is_linear(const Sequence *seq, const SeqRetimingHandle *handle)
static bool seq_retiming_transition_is_linear(const Scene *scene,
const Sequence *seq,
const SeqRetimingHandle *handle)
{
const float prev_speed = SEQ_retiming_handle_speed_get(seq, handle - 1);
const float next_speed = SEQ_retiming_handle_speed_get(seq, handle + 1);
const float prev_speed = SEQ_retiming_handle_speed_get(scene, seq, handle - 1);
const float next_speed = SEQ_retiming_handle_speed_get(scene, seq, handle + 1);
return abs(prev_speed - next_speed) < 0.01f;
}
static float seq_retiming_evaluate_arc_segment(const SeqRetimingHandle *handle,
const float frame_index)
const float eval_time)
{
double c[2], r;
seq_retiming_line_segments_tangent_circle(handle, c, &r);
const int side = c[1] > handle->retiming_factor ? -1 : 1;
const float y = c[1] + side * sqrt(pow(r, 2) - pow((frame_index - c[0]), 2));
const float y = c[1] + side * sqrt(pow(r, 2) - pow((eval_time - c[0]), 2));
return y;
}
float seq_retiming_evaluate(const Sequence *seq, const float frame_index)
float seq_retiming_evaluate(const Scene *scene, const Sequence *seq, const float frame_index)
{
const SeqRetimingHandle *start_handle = SEQ_retiming_find_segment_start_handle(seq, frame_index);
const SeqRetimingHandle *start_handle = SEQ_retiming_find_segment_start_handle(
scene, seq, frame_index);
const double eval_time = SEQ_time_frames_to_seconds(scene, frame_index);
const int start_handle_index = start_handle - seq->retiming_handles;
BLI_assert(start_handle_index < seq->retiming_handle_num);
const float segment_frame_index = frame_index - start_handle->strip_frame_index;
const float segment_eval_time = eval_time - start_handle->strip_frame_index;
if (!SEQ_retiming_handle_is_transition_type(start_handle)) {
const float segment_step = seq_retiming_segment_step_get(start_handle);
return start_handle->retiming_factor + segment_step * segment_frame_index;
const float segment_step = seq_retiming_segment_step_get(scene, start_handle);
return start_handle->retiming_factor + segment_step * segment_eval_time;
}
if (seq_retiming_transition_is_linear(seq, start_handle)) {
const float segment_step = seq_retiming_segment_step_get(start_handle - 1);
return start_handle->retiming_factor + segment_step * segment_frame_index;
if (seq_retiming_transition_is_linear(scene, seq, start_handle)) {
const float segment_step = seq_retiming_segment_step_get(scene, start_handle - 1);
return start_handle->retiming_factor + segment_step * segment_eval_time;
}
/* Sanity check for transition type. */
@ -241,18 +249,19 @@ float seq_retiming_evaluate(const Sequence *seq, const float frame_index)
BLI_assert(start_handle_index < seq->retiming_handle_num - 1);
UNUSED_VARS_NDEBUG(start_handle_index);
return seq_retiming_evaluate_arc_segment(start_handle, frame_index);
return seq_retiming_evaluate_arc_segment(start_handle, eval_time);
}
SeqRetimingHandle *SEQ_retiming_add_handle(const Scene *scene,
Sequence *seq,
const int timeline_frame)
{
float frame_index = (timeline_frame - SEQ_time_start_frame_get(seq)) *
float frame_index = (timeline_frame - SEQ_time_start_frame_get(scene, seq)) *
seq_time_media_playback_rate_factor_get(scene, seq);
float value = seq_retiming_evaluate(seq, frame_index);
float value = seq_retiming_evaluate(scene, seq, frame_index);
const SeqRetimingHandle *start_handle = SEQ_retiming_find_segment_start_handle(seq, frame_index);
const SeqRetimingHandle *start_handle = SEQ_retiming_find_segment_start_handle(
scene, seq, frame_index);
if (start_handle->strip_frame_index == frame_index) {
return nullptr; /* Retiming handle already exists. */
}
@ -284,7 +293,7 @@ SeqRetimingHandle *SEQ_retiming_add_handle(const Scene *scene,
seq->retiming_handle_num++;
SeqRetimingHandle *added_handle = (new_handles + new_handle_index);
added_handle->strip_frame_index = frame_index;
added_handle->strip_frame_index = SEQ_time_frames_to_seconds(scene, frame_index);
added_handle->retiming_factor = value;
return added_handle;
@ -298,7 +307,7 @@ static void seq_retiming_offset_linear_handle(const Scene *scene,
MutableSpan handles = SEQ_retiming_handles_get(seq);
for (SeqRetimingHandle *next_handle = handle; next_handle < handles.end(); next_handle++) {
next_handle->strip_frame_index += offset * seq_time_media_playback_rate_factor_get(scene, seq);
next_handle->strip_frame_index += SEQ_time_frames_to_seconds(scene, offset);
}
/* Handle affected transitions: remove and re-create transition. This way transition won't change
@ -310,8 +319,9 @@ static void seq_retiming_offset_linear_handle(const Scene *scene,
{
SeqRetimingHandle *transition_handle = handle - 2;
const int transition_offset = transition_handle->strip_frame_index -
transition_handle->original_strip_frame_index;
const int transition_offset = SEQ_time_seconds_to_frames(
scene,
transition_handle->strip_frame_index - transition_handle->original_strip_frame_index);
const int transition_handle_index = SEQ_retiming_handle_index_get(seq, transition_handle);
@ -358,13 +368,15 @@ static void seq_retiming_offset_transition_handle(const Scene *scene,
end_frame - SEQ_retiming_handle_timeline_frame_get(scene, seq, next_segment_start) - 1;
corrected_offset = max_iii(corrected_offset, offset_min_left, offset_min_right);
const float prev_segment_step = seq_retiming_segment_step_get(handle_start - 1);
const float next_segment_step = seq_retiming_segment_step_get(handle_end);
const float prev_segment_step = seq_retiming_segment_step_get(scene, handle_start - 1);
const float next_segment_step = seq_retiming_segment_step_get(scene, handle_end);
handle_start->strip_frame_index += corrected_offset;
handle_start->retiming_factor += corrected_offset * prev_segment_step;
handle_end->strip_frame_index -= corrected_offset;
handle_end->retiming_factor -= corrected_offset * next_segment_step;
handle_start->strip_frame_index += SEQ_time_frames_to_seconds(scene, corrected_offset);
handle_start->retiming_factor += SEQ_time_frames_to_seconds(scene, corrected_offset) *
prev_segment_step;
handle_end->strip_frame_index -= SEQ_time_frames_to_seconds(scene, corrected_offset);
handle_end->retiming_factor -= SEQ_time_frames_to_seconds(scene, corrected_offset) *
next_segment_step;
}
void SEQ_retiming_offset_handle(const Scene *scene,
@ -441,7 +453,9 @@ static void seq_retiming_remove_transition(const Scene *scene,
/* Create original linear handle. */
SeqRetimingHandle *orig_handle = SEQ_retiming_add_handle(
scene, seq, SEQ_time_start_frame_get(seq) + orig_frame_index);
scene,
seq,
SEQ_time_start_frame_get(scene, seq) + SEQ_time_seconds_to_frames(scene, orig_frame_index));
orig_handle->retiming_factor = orig_retiming_factor;
}
@ -516,7 +530,9 @@ SeqRetimingHandle *SEQ_retiming_add_transition(const Scene *scene,
return seq->retiming_handles + orig_handle_index;
}
float SEQ_retiming_handle_speed_get(const Sequence *seq, const SeqRetimingHandle *handle)
float SEQ_retiming_handle_speed_get(const Scene *scene,
const Sequence *seq,
const SeqRetimingHandle *handle)
{
if (handle->strip_frame_index == 0) {
return 1.0f;
@ -524,7 +540,7 @@ float SEQ_retiming_handle_speed_get(const Sequence *seq, const SeqRetimingHandle
const SeqRetimingHandle *handle_prev = handle - 1;
const int frame_index_max = seq->len - 1;
const int frame_index_max = SEQ_time_seconds_to_frames(scene, seq->len);
const int frame_retimed_prev = round_fl_to_int(handle_prev->retiming_factor * frame_index_max);
const int frame_index_prev = handle_prev->strip_frame_index;
const int frame_retimed = round_fl_to_int(handle->retiming_factor * frame_index_max);
@ -580,12 +596,17 @@ class RetimingRange {
blender::Vector<float> speed_table;
eRangeType type;
RetimingRange(const Sequence *seq, int start_frame, int end_frame, float speed, eRangeType type)
RetimingRange(const Scene *scene,
const Sequence *seq,
int start_frame,
int end_frame,
float speed,
eRangeType type)
: start(start_frame), end(end_frame), speed(speed), type(type)
{
if (type == TRANSITION) {
speed = 1.0f;
claculate_speed_table_from_seq(seq);
claculate_speed_table_from_seq(scene, seq);
}
}
@ -665,15 +686,15 @@ class RetimingRange {
return new_range;
}
void claculate_speed_table_from_seq(const Sequence *seq)
void claculate_speed_table_from_seq(const Scene *scene, const Sequence *seq)
{
for (int frame = start; frame <= end; frame++) {
/* We need number actual number of frames here. */
const double normal_step = 1 / double(seq->len);
/* Who needs calculus, when you can have slow code? */
const double val_prev = seq_retiming_evaluate(seq, frame - 1);
const double val = seq_retiming_evaluate(seq, frame);
const double val_prev = seq_retiming_evaluate(scene, seq, frame - 1);
const double val = seq_retiming_evaluate(scene, seq, frame);
const double speed_at_frame = (val - val_prev) / normal_step;
speed_table.append(speed_at_frame);
}
@ -700,7 +721,7 @@ class RetimingRange {
class RetimingRangeData {
public:
blender::Vector<RetimingRange> ranges;
RetimingRangeData(const Sequence *seq)
RetimingRangeData(const Scene *scene, const Sequence *seq)
{
MutableSpan handles = SEQ_retiming_handles_get(seq);
for (const SeqRetimingHandle &handle : handles) {
@ -708,12 +729,12 @@ class RetimingRangeData {
continue;
}
const SeqRetimingHandle *handle_prev = &handle - 1;
float speed = SEQ_retiming_handle_speed_get(seq, &handle);
int frame_start = SEQ_time_start_frame_get(seq) + handle_prev->strip_frame_index;
int frame_end = SEQ_time_start_frame_get(seq) + handle.strip_frame_index;
float speed = SEQ_retiming_handle_speed_get(scene, seq, &handle);
int frame_start = SEQ_retiming_handle_timeline_frame_get(scene, seq, handle_prev);
int frame_end = SEQ_retiming_handle_timeline_frame_get(scene, seq, &handle);
eRangeType type = SEQ_retiming_handle_is_transition_type(handle_prev) ? TRANSITION : LINEAR;
RetimingRange range = RetimingRange(seq, frame_start, frame_end, speed, type);
RetimingRange range = RetimingRange(scene, seq, frame_start, frame_end, speed, type);
ranges.append(range);
}
}
@ -765,14 +786,14 @@ class RetimingRangeData {
static RetimingRangeData seq_retiming_range_data_get(const Scene *scene, const Sequence *seq)
{
RetimingRangeData strip_retiming_data = RetimingRangeData(seq);
RetimingRangeData strip_retiming_data = RetimingRangeData(scene, seq);
const Sequence *meta_parent = seq_sequence_lookup_meta_by_seq(scene, seq);
if (meta_parent == nullptr) {
return strip_retiming_data;
}
RetimingRangeData meta_retiming_data = RetimingRangeData(meta_parent);
RetimingRangeData meta_retiming_data = RetimingRangeData(scene, meta_parent);
strip_retiming_data *= meta_retiming_data;
return strip_retiming_data;
}
@ -802,6 +823,6 @@ float SEQ_retiming_handle_timeline_frame_get(const Scene *scene,
const Sequence *seq,
const SeqRetimingHandle *handle)
{
return SEQ_time_start_frame_get(seq) +
handle->strip_frame_index / seq_time_media_playback_rate_factor_get(scene, seq);
return SEQ_time_start_frame_get(scene, seq) +
SEQ_time_seconds_to_frames(scene, handle->strip_frame_index);
}

View File

@ -66,9 +66,10 @@ int seq_time_strip_original_content_length_get(const Scene *scene, const Sequenc
float SEQ_give_frame_index(const Scene *scene, Sequence *seq, float timeline_frame)
{
float frame_index;
float sta = SEQ_time_start_frame_get(seq);
float sta = SEQ_time_start_frame_get(scene, seq);
float end = SEQ_time_content_end_frame_get(scene, seq) - 1;
const float length = seq->len;
const float length = SEQ_time_seconds_to_frames(scene, seq->len) *
seq_time_media_playback_rate_factor_get(scene, seq);
if (seq->type & SEQ_TYPE_EFFECT) {
end = SEQ_time_right_handle_frame_get(scene, seq);
@ -94,7 +95,7 @@ float SEQ_give_frame_index(const Scene *scene, Sequence *seq, float timeline_fra
frame_index *= seq_time_media_playback_rate_factor_get(scene, seq);
if (SEQ_retiming_is_active(seq)) {
const float retiming_factor = seq_retiming_evaluate(seq, frame_index);
const float retiming_factor = seq_retiming_evaluate(scene, seq, frame_index);
frame_index = retiming_factor * (length);
}
/* Clamp frame index to strip content frame range. */
@ -110,17 +111,6 @@ float SEQ_give_frame_index(const Scene *scene, Sequence *seq, float timeline_fra
return frame_index;
}
static int metaseq_start(Sequence *metaseq)
{
return metaseq->start + metaseq->startofs;
}
static int metaseq_end(Sequence *metaseq)
{
return metaseq->start + metaseq->len - metaseq->endofs;
}
static void seq_update_sound_bounds_recursive_impl(const Scene *scene,
Sequence *metaseq,
int start,
@ -133,18 +123,23 @@ static void seq_update_sound_bounds_recursive_impl(const Scene *scene,
for (seq = metaseq->seqbase.first; seq; seq = seq->next) {
if (seq->type == SEQ_TYPE_META) {
seq_update_sound_bounds_recursive_impl(
scene, seq, max_ii(start, metaseq_start(seq)), min_ii(end, metaseq_end(seq)));
scene,
seq,
max_ii(start, SEQ_time_left_handle_frame_get(scene, seq)),
min_ii(end, SEQ_time_right_handle_frame_get(scene, seq)));
}
else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
if (seq->scene_sound) {
int startofs = seq->startofs;
int endofs = seq->endofs;
if (seq->startofs + seq->start < start) {
startofs = start - seq->start;
int start_frame = SEQ_time_start_frame_get(scene, seq);
int length = SEQ_time_strip_length_get(scene, seq);
int startofs = SEQ_time_seconds_to_frames(scene, seq->startofs);
int endofs = SEQ_time_seconds_to_frames(scene, seq->endofs);
if (startofs + start_frame < start) {
startofs = start - start_frame;
}
if (seq->start + seq->len - seq->endofs > end) {
endofs = seq->start + seq->len - end;
if (start_frame + length - endofs > end) {
endofs = start_frame + length - end;
}
double offset_time = 0.0f;
@ -154,8 +149,8 @@ static void seq_update_sound_bounds_recursive_impl(const Scene *scene,
BKE_sound_move_scene_sound(scene,
seq->scene_sound,
seq->start + startofs,
seq->start + seq->len - endofs,
start_frame + startofs,
start_frame + length - endofs,
startofs + seq->anim_startofs,
offset_time);
}
@ -165,8 +160,10 @@ static void seq_update_sound_bounds_recursive_impl(const Scene *scene,
void seq_update_sound_bounds_recursive(const Scene *scene, Sequence *metaseq)
{
seq_update_sound_bounds_recursive_impl(
scene, metaseq, metaseq_start(metaseq), metaseq_end(metaseq));
seq_update_sound_bounds_recursive_impl(scene,
metaseq,
SEQ_time_left_handle_frame_get(scene, metaseq),
SEQ_time_right_handle_frame_get(scene, metaseq));
}
void SEQ_time_update_meta_strip_range(const Scene *scene, Sequence *seq_meta)
@ -233,8 +230,8 @@ void seq_time_effect_range_set(const Scene *scene, Sequence *seq)
/* Values unusable for effects, these should be always 0. */
seq->startofs = seq->endofs = seq->anim_startofs = seq->anim_endofs = 0;
seq->start = seq->startdisp;
seq->len = seq->enddisp - seq->startdisp;
seq->start = SEQ_time_frames_to_seconds(scene, seq->startdisp);
seq->len = SEQ_time_frames_to_seconds(scene, seq->enddisp - seq->startdisp);
}
void seq_time_update_effects_strip_range(const Scene *scene, SeqCollection *effects)
@ -489,7 +486,7 @@ void SEQ_time_speed_factor_set(const Scene *scene, Sequence *seq, const float sp
bool SEQ_time_has_left_still_frames(const Scene *scene, const Sequence *seq)
{
return SEQ_time_left_handle_frame_get(scene, seq) < SEQ_time_start_frame_get(seq);
return SEQ_time_left_handle_frame_get(scene, seq) < SEQ_time_start_frame_get(scene, seq);
}
bool SEQ_time_has_right_still_frames(const Scene *scene, const Sequence *seq)
@ -502,42 +499,49 @@ bool SEQ_time_has_still_frames(const Scene *scene, const Sequence *seq)
return SEQ_time_has_right_still_frames(scene, seq) || SEQ_time_has_left_still_frames(scene, seq);
}
void SEQ_time_strip_length_set(const Scene *scene, Sequence *seq, double length_in_frames)
{
seq->len = SEQ_time_frames_to_seconds(scene, length_in_frames);
}
int SEQ_time_strip_length_get(const Scene *scene, const Sequence *seq)
{
if (SEQ_retiming_is_active(seq)) {
SeqRetimingHandle *handle_start = seq->retiming_handles;
SeqRetimingHandle *handle_end = seq->retiming_handles + (SEQ_retiming_handles_count(seq) - 1);
return handle_end->strip_frame_index / seq_time_media_playback_rate_factor_get(scene, seq) -
(handle_start->strip_frame_index) / seq_time_media_playback_rate_factor_get(scene, seq);
return SEQ_time_seconds_to_frames(
scene, handle_end->strip_frame_index - handle_start->strip_frame_index);
}
return seq->len / seq_time_media_playback_rate_factor_get(scene, seq);
/* XXX it was seq->len / seq_time_media_playback_rate_factor_get(scene, seq) but now it doesn't
* make sense, because playback rate factor does not influence length. */
return SEQ_time_seconds_to_frames(scene, seq->len);
}
float SEQ_time_start_frame_get(const Sequence *seq)
float SEQ_time_start_frame_get(const Scene *scene, const Sequence *seq)
{
return seq->start;
return SEQ_time_seconds_to_frames(scene, seq->start);
}
void SEQ_time_start_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
{
seq->start = timeline_frame;
seq->start = SEQ_time_frames_to_seconds(scene, timeline_frame);
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
}
float SEQ_time_content_end_frame_get(const Scene *scene, const Sequence *seq)
{
return SEQ_time_start_frame_get(seq) + SEQ_time_strip_length_get(scene, seq);
return SEQ_time_start_frame_get(scene, seq) + SEQ_time_strip_length_get(scene, seq);
}
int SEQ_time_left_handle_frame_get(const Scene *UNUSED(scene), const Sequence *seq)
int SEQ_time_left_handle_frame_get(const Scene *scene, const Sequence *seq)
{
if (seq->seq1 || seq->seq2) {
return seq->startdisp;
}
return seq->start + seq->startofs;
return SEQ_time_start_frame_get(scene, seq) + SEQ_time_seconds_to_frames(scene, seq->startofs);
}
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
@ -546,7 +550,8 @@ int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
return seq->enddisp;
}
return SEQ_time_content_end_frame_get(scene, seq) - seq->endofs;
return SEQ_time_content_end_frame_get(scene, seq) -
SEQ_time_seconds_to_frames(scene, seq->endofs);
}
void SEQ_time_left_handle_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
@ -557,13 +562,13 @@ void SEQ_time_left_handle_frame_set(const Scene *scene, Sequence *seq, int timel
timeline_frame = right_handle_orig_frame - 1;
}
float offset = timeline_frame - SEQ_time_start_frame_get(seq);
float offset = SEQ_time_frames_to_seconds(scene, timeline_frame) - seq->start;
if (SEQ_transform_single_image_check(seq)) {
/* This strip has only 1 frame of content, that is always stretched to whole strip length.
* Therefore, strip start should be moved instead of adjusting offset. */
SEQ_time_start_frame_set(scene, seq, timeline_frame);
seq->endofs += offset;
seq->len -= offset;
}
else {
seq->startofs = offset;
@ -583,7 +588,15 @@ void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int time
timeline_frame = left_handle_orig_frame + 1;
}
seq->endofs = SEQ_time_content_end_frame_get(scene, seq) - timeline_frame;
if (SEQ_transform_single_image_check(seq)) {
double strip_end_time = seq->start + seq->len;
double time = SEQ_time_frames_to_seconds(scene, timeline_frame);
seq->len += time - strip_end_time;
}
else {
seq->endofs = seq->start + seq->len - SEQ_time_frames_to_seconds(scene, timeline_frame);
}
seq->enddisp = timeline_frame; /* Only to make files usable in older versions. */
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
@ -600,3 +613,15 @@ void seq_time_translate_handles(const Scene *scene, Sequence *seq, const int off
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
}
double SEQ_time_frames_to_seconds(const Scene *scene, double frames)
{
double scene_playback_rate = (float)scene->r.frs_sec / scene->r.frs_sec_base;
return frames / scene_playback_rate;
}
int SEQ_time_seconds_to_frames(const Scene *scene, double seconds)
{
double scene_playback_rate = (float)scene->r.frs_sec / scene->r.frs_sec_base;
return round_db_to_int(seconds * scene_playback_rate);
}

View File

@ -48,7 +48,7 @@ float seq_time_media_playback_rate_factor_get(const struct Scene *scene,
const struct Sequence *seq);
int seq_time_strip_original_content_length_get(const struct Scene *scene,
const struct Sequence *seq);
float seq_retiming_evaluate(const struct Sequence *seq, const float frame_index);
float seq_retiming_evaluate(const struct Scene *scene, const struct Sequence *seq, const float frame_index);
#ifdef __cplusplus
}

View File

@ -130,7 +130,7 @@ void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delt
seq_time_translate_handles(evil_scene, seq, delta);
}
else if (seq->seq1 == NULL && seq->seq2 == NULL) { /* All other strip types. */
seq->start += delta;
seq->start += SEQ_time_frames_to_seconds(evil_scene, delta);
/* Only to make files usable in older versions. */
seq->startdisp = SEQ_time_left_handle_frame_get(evil_scene, seq);
seq->enddisp = SEQ_time_right_handle_frame_get(evil_scene, seq);

View File

@ -176,7 +176,10 @@ const char *SEQ_sequence_give_name(Sequence *seq)
return name;
}
ListBase *SEQ_get_seqbase_from_sequence(Sequence *seq, ListBase **r_channels, int *r_offset)
ListBase *SEQ_get_seqbase_from_sequence(const Scene *scene,
Sequence *seq,
ListBase **r_channels,
int *r_offset)
{
ListBase *seqbase = NULL;
@ -184,7 +187,7 @@ ListBase *SEQ_get_seqbase_from_sequence(Sequence *seq, ListBase **r_channels, in
case SEQ_TYPE_META: {
seqbase = &seq->seqbase;
*r_channels = &seq->channels;
*r_offset = SEQ_time_start_frame_get(seq);
*r_offset = SEQ_time_start_frame_get(scene, seq);
break;
}
case SEQ_TYPE_SCENE: {