VSE: Hook up sound subframe sliding to the VSE slip modal operator
Updates the slide operator to be able to do subframe adjustments of audio strips. If you hold shift while sliding (the S shortcut), it will start to do subframe adjustments. It is also possible to type in fractional inputs while in modal mode. (IE start sliding then type 1.5)
This commit is contained in:
committed by
Sebastian Parborg
parent
fb6aaf3200
commit
7b25d1327e
@@ -466,6 +466,8 @@ void SEQUENCER_OT_snap(wmOperatorType *ot)
|
||||
struct SlipData {
|
||||
float init_mouseloc[2];
|
||||
int previous_offset;
|
||||
float previous_subframe_offset;
|
||||
float subframe_restore;
|
||||
Sequence **seq_array;
|
||||
int num_seq;
|
||||
bool slow;
|
||||
@@ -522,7 +524,6 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
|
||||
|
||||
initNumInput(&data->num_input);
|
||||
data->num_input.idx_max = 0;
|
||||
data->num_input.val_flag[0] |= NUM_NO_FRACTION;
|
||||
data->num_input.unit_sys = USER_UNIT_NONE;
|
||||
data->num_input.unit_type[0] = 0;
|
||||
|
||||
@@ -542,7 +543,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static void sequencer_slip_strips(Scene *scene, SlipData *data, int delta)
|
||||
static void sequencer_slip_strips(Scene *scene, SlipData *data, int delta, float subframe_delta)
|
||||
{
|
||||
for (int i = data->num_seq - 1; i >= 0; i--) {
|
||||
Sequence *seq = data->seq_array[i];
|
||||
@@ -552,7 +553,7 @@ static void sequencer_slip_strips(Scene *scene, SlipData *data, int delta)
|
||||
continue;
|
||||
}
|
||||
|
||||
SEQ_time_slip_strip(scene, seq, delta);
|
||||
SEQ_time_slip_strip(scene, seq, delta, subframe_delta);
|
||||
}
|
||||
|
||||
for (int i = data->num_seq - 1; i >= 0; i--) {
|
||||
@@ -592,7 +593,6 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene);
|
||||
int offset = RNA_int_get(op->ptr, "offset");
|
||||
|
||||
/* Count the amount of elements to trim. */
|
||||
int num_seq = slip_count_sequences(ed->seqbasep);
|
||||
@@ -608,8 +608,17 @@ static int sequencer_slip_exec(bContext *C, wmOperator *op)
|
||||
|
||||
slip_add_sequences(ed->seqbasep, data->seq_array);
|
||||
|
||||
float offset_fl = RNA_float_get(op->ptr, "offset");
|
||||
int offset = round_fl_to_int(offset_fl);
|
||||
|
||||
float subframe_delta = 0.0f;
|
||||
if (std::trunc(offset_fl) != offset_fl) {
|
||||
/* Only apply subframe offsets if the input is not an integer. */
|
||||
subframe_delta = offset_fl - offset;
|
||||
}
|
||||
|
||||
sequencer_slip_apply_limits(scene, data, &offset);
|
||||
sequencer_slip_strips(scene, data, offset);
|
||||
sequencer_slip_strips(scene, data, offset, subframe_delta);
|
||||
|
||||
MEM_freeN(data->seq_array);
|
||||
MEM_freeN(data);
|
||||
@@ -638,6 +647,37 @@ static void sequencer_slip_update_header(Scene *scene, ScrArea *area, SlipData *
|
||||
ED_area_status_text(area, msg);
|
||||
}
|
||||
|
||||
static void handle_number_input(
|
||||
bContext *C, wmOperator *op, ScrArea *area, SlipData *data, Scene *scene)
|
||||
{
|
||||
float offset_fl;
|
||||
applyNumInput(&data->num_input, &offset_fl);
|
||||
int offset = round_fl_to_int(offset_fl);
|
||||
|
||||
const int delta_offset = sequencer_slip_apply_limits(scene, data, &offset);
|
||||
sequencer_slip_update_header(scene, area, data, offset);
|
||||
|
||||
RNA_float_set(op->ptr, "offset", offset_fl);
|
||||
|
||||
float subframe_delta = 0.0f;
|
||||
if (data->subframe_restore != 0.0f) {
|
||||
/* Always remove the previous subframe adjustments we have potentially made with the mouse
|
||||
* input when the user starts enterning values by hand.
|
||||
*/
|
||||
subframe_delta = -data->subframe_restore;
|
||||
data->subframe_restore = 0.0f;
|
||||
}
|
||||
if (std::trunc(offset_fl) != offset_fl) {
|
||||
/* Only apply subframe offsets if the input is not an integer. */
|
||||
subframe_delta = offset_fl - data->previous_subframe_offset - delta_offset;
|
||||
data->subframe_restore += subframe_delta;
|
||||
}
|
||||
data->previous_subframe_offset = offset_fl;
|
||||
sequencer_slip_strips(scene, data, delta_offset, subframe_delta);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
}
|
||||
|
||||
static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
@@ -648,19 +688,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
|
||||
|
||||
/* Modal numinput active, try to handle numeric inputs. */
|
||||
if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
|
||||
float offset_fl;
|
||||
applyNumInput(&data->num_input, &offset_fl);
|
||||
int offset = round_fl_to_int(offset_fl);
|
||||
|
||||
const int delta_offset = sequencer_slip_apply_limits(scene, data, &offset);
|
||||
sequencer_slip_update_header(scene, area, data, offset);
|
||||
|
||||
RNA_int_set(op->ptr, "offset", offset);
|
||||
|
||||
sequencer_slip_strips(scene, data, delta_offset);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
|
||||
handle_number_input(C, op, area, data, scene);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
@@ -669,7 +697,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
|
||||
if (!has_numInput) {
|
||||
float mouseloc[2];
|
||||
int offset;
|
||||
int mouse_x;
|
||||
float mouse_x;
|
||||
View2D *v2d = UI_view2d_fromcontext(C);
|
||||
|
||||
if (data->slow) {
|
||||
@@ -683,14 +711,28 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
|
||||
|
||||
/* Choose the side based on which side of the current frame the mouse is. */
|
||||
UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
|
||||
offset = mouseloc[0] - data->init_mouseloc[0];
|
||||
float offset_fl = mouseloc[0] - data->init_mouseloc[0];
|
||||
offset = offset_fl;
|
||||
|
||||
const int delta_offset = sequencer_slip_apply_limits(scene, data, &offset);
|
||||
sequencer_slip_update_header(scene, area, data, offset);
|
||||
|
||||
RNA_int_set(op->ptr, "offset", offset);
|
||||
|
||||
sequencer_slip_strips(scene, data, delta_offset);
|
||||
if (!data->slow) {
|
||||
RNA_float_set(op->ptr, "offset", offset);
|
||||
}
|
||||
float subframe_delta = 0.0f;
|
||||
if (data->slow) {
|
||||
RNA_float_set(op->ptr, "offset", offset_fl);
|
||||
subframe_delta = offset_fl - data->previous_subframe_offset - delta_offset;
|
||||
data->subframe_restore += subframe_delta;
|
||||
}
|
||||
else if (data->subframe_restore != 0.0f) {
|
||||
/* If we exit slow mode, make sure we undo the fractional adjustments we have done. */
|
||||
subframe_delta = -data->subframe_restore;
|
||||
data->subframe_restore = 0.0f;
|
||||
}
|
||||
data->previous_subframe_offset = offset_fl;
|
||||
sequencer_slip_strips(scene, data, delta_offset, subframe_delta);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
}
|
||||
@@ -713,8 +755,9 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
|
||||
|
||||
case EVT_ESCKEY:
|
||||
case RIGHTMOUSE: {
|
||||
int offset = RNA_int_get(op->ptr, "offset");
|
||||
sequencer_slip_strips(scene, data, -offset);
|
||||
int offset = data->previous_offset;
|
||||
float subframe_delta = data->subframe_restore;
|
||||
sequencer_slip_strips(scene, data, -offset, -subframe_delta);
|
||||
|
||||
MEM_freeN(data->seq_array);
|
||||
MEM_freeN(data);
|
||||
@@ -749,18 +792,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
|
||||
|
||||
/* Modal numinput inactive, try to handle numeric inputs. */
|
||||
if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
|
||||
float offset_fl;
|
||||
applyNumInput(&data->num_input, &offset_fl);
|
||||
int offset = round_fl_to_int(offset_fl);
|
||||
|
||||
const int delta_offset = sequencer_slip_apply_limits(scene, data, &offset);
|
||||
sequencer_slip_update_header(scene, area, data, offset);
|
||||
|
||||
RNA_int_set(op->ptr, "offset", offset);
|
||||
|
||||
sequencer_slip_strips(scene, data, delta_offset);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
||||
handle_number_input(C, op, area, data, scene);
|
||||
}
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
@@ -782,15 +814,19 @@ void SEQUENCER_OT_slip(wmOperatorType *ot)
|
||||
/* Flags. */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
RNA_def_int(ot->srna,
|
||||
"offset",
|
||||
0,
|
||||
INT32_MIN,
|
||||
INT32_MAX,
|
||||
"Offset",
|
||||
"Offset to the data of the strip",
|
||||
INT32_MIN,
|
||||
INT32_MAX);
|
||||
/* Properties. */
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_float(ot->srna,
|
||||
"offset",
|
||||
0,
|
||||
-FLT_MAX,
|
||||
FLT_MAX,
|
||||
"Offset",
|
||||
"Offset to the data of the strip",
|
||||
-FLT_MAX,
|
||||
FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 100, 0);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -192,34 +192,22 @@ static StripDrawContext strip_draw_context_get(TimelineDrawContext *ctx, Sequenc
|
||||
strip_ctx.seq = seq;
|
||||
strip_ctx.bottom = seq->machine + SEQ_STRIP_OFSBOTTOM;
|
||||
strip_ctx.top = seq->machine + SEQ_STRIP_OFSTOP;
|
||||
strip_ctx.content_start = SEQ_time_left_handle_frame_get(scene, seq);
|
||||
strip_ctx.content_end = SEQ_time_right_handle_frame_get(scene, seq);
|
||||
if (SEQ_time_has_left_still_frames(scene, seq)) {
|
||||
strip_ctx.content_start = SEQ_time_start_frame_get(seq);
|
||||
}
|
||||
if (SEQ_time_has_right_still_frames(scene, seq)) {
|
||||
strip_ctx.content_end = SEQ_time_content_end_frame_get(scene, seq);
|
||||
}
|
||||
strip_ctx.left_handle = SEQ_time_left_handle_frame_get(scene, seq);
|
||||
strip_ctx.right_handle = SEQ_time_right_handle_frame_get(scene, seq);
|
||||
strip_ctx.content_start = SEQ_time_start_frame_get(seq);
|
||||
strip_ctx.content_end = SEQ_time_content_end_frame_get(scene, seq);
|
||||
|
||||
if (seq->type == SEQ_TYPE_SOUND_RAM && seq->sound != nullptr) {
|
||||
/* Visualize subframe sound offsets */
|
||||
const double sound_offset = seq->sound->offset_time + seq->sound_offset;
|
||||
if (sound_offset >= 0.0f) {
|
||||
strip_ctx.content_start += sound_offset * FPS;
|
||||
}
|
||||
else {
|
||||
strip_ctx.content_end += sound_offset * FPS;
|
||||
}
|
||||
const double sound_offset = (seq->sound->offset_time + seq->sound_offset) * FPS;
|
||||
strip_ctx.content_start += sound_offset;
|
||||
strip_ctx.content_end += sound_offset;
|
||||
}
|
||||
|
||||
/* Limit body to strip bounds. Meta strip can end up with content outside of strip range. */
|
||||
strip_ctx.content_start = min_ff(strip_ctx.content_start,
|
||||
SEQ_time_right_handle_frame_get(scene, seq));
|
||||
strip_ctx.content_end = max_ff(strip_ctx.content_end,
|
||||
SEQ_time_left_handle_frame_get(scene, seq));
|
||||
/* Limit body to strip bounds. */
|
||||
strip_ctx.content_start = min_ff(strip_ctx.content_start, strip_ctx.right_handle);
|
||||
strip_ctx.content_end = max_ff(strip_ctx.content_end, strip_ctx.left_handle);
|
||||
|
||||
strip_ctx.left_handle = SEQ_time_left_handle_frame_get(scene, seq);
|
||||
strip_ctx.right_handle = SEQ_time_right_handle_frame_get(scene, seq);
|
||||
strip_ctx.strip_length = strip_ctx.right_handle - strip_ctx.left_handle;
|
||||
|
||||
strip_draw_context_set_text_overlay_visibility(ctx, &strip_ctx);
|
||||
|
||||
@@ -3042,8 +3042,10 @@ static void rna_def_sound(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 3);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */
|
||||
RNA_def_property_ui_text(prop, "Sound Offset", "Sound offset in seconds");
|
||||
// TODO do we need to create any extra translation stuff for this?
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Sound Offset",
|
||||
"Offset of the sound from the beginning of the strip, expressed in seconds");
|
||||
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_audio_update");
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ void SEQ_time_update_meta_strip_range(const Scene *scene, Sequence *seq_meta);
|
||||
/**
|
||||
* Move contents of a strip without moving the strip handles.
|
||||
*/
|
||||
void SEQ_time_slip_strip(const Scene *scene, Sequence *seq, int delta);
|
||||
void SEQ_time_slip_strip(const Scene *scene, Sequence *seq, int delta, float subframe_delta);
|
||||
/**
|
||||
* Get difference between scene and movie strip frame-rate.
|
||||
*/
|
||||
|
||||
@@ -575,8 +575,13 @@ 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));
|
||||
}
|
||||
|
||||
static void seq_time_slip_strip_ex(const Scene *scene, Sequence *seq, int delta, bool recursed)
|
||||
static void seq_time_slip_strip_ex(
|
||||
const Scene *scene, Sequence *seq, int delta, float subframe_delta, bool recursed)
|
||||
{
|
||||
if (seq->type == SEQ_TYPE_SOUND_RAM && subframe_delta != 0.0f) {
|
||||
seq->sound_offset += subframe_delta / FPS;
|
||||
}
|
||||
|
||||
if (delta == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -600,7 +605,7 @@ static void seq_time_slip_strip_ex(const Scene *scene, Sequence *seq, int delta,
|
||||
return;
|
||||
}
|
||||
LISTBASE_FOREACH (Sequence *, seq_child, &seq->seqbase) {
|
||||
seq_time_slip_strip_ex(scene, seq_child, delta, true);
|
||||
seq_time_slip_strip_ex(scene, seq_child, delta, subframe_delta, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,9 +623,9 @@ static void seq_time_slip_strip_ex(const Scene *scene, Sequence *seq, int delta,
|
||||
seq_time_update_effects_strip_range(scene, effects);
|
||||
}
|
||||
|
||||
void SEQ_time_slip_strip(const Scene *scene, Sequence *seq, int delta)
|
||||
void SEQ_time_slip_strip(const Scene *scene, Sequence *seq, int delta, float subframe_delta)
|
||||
{
|
||||
seq_time_slip_strip_ex(scene, seq, delta, false);
|
||||
seq_time_slip_strip_ex(scene, seq, delta, subframe_delta, false);
|
||||
}
|
||||
|
||||
int SEQ_time_get_rounded_sound_offset(const Scene *scene, const Sequence *seq)
|
||||
|
||||
Reference in New Issue
Block a user