VSE: Smooth transition for retiming tool #107197
|
@ -224,7 +224,7 @@ static void gizmo_retime_handle_add_draw(const bContext *C, wmGizmo *gz)
|
|||
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);
|
||||
|
||||
if (SEQ_retiming_handle_is_transition_type(handle)) {
|
||||
if (handle != nullptr && SEQ_retiming_handle_is_transition_type(handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -347,7 +347,7 @@ static void retime_handle_draw(const bContext *C,
|
|||
const float handle_x = handle_x_get(scene, seq, handle);
|
||||
|
||||
if (handle_x == SEQ_time_left_handle_frame_get(scene, seq)) {
|
||||
// return;
|
||||
return;
|
||||
}
|
||||
if (handle_x == SEQ_time_right_handle_frame_get(scene, seq)) {
|
||||
return;
|
||||
|
@ -460,7 +460,7 @@ static void gizmo_retime_handle_draw(const bContext *C, wmGizmo *gz)
|
|||
retime_speed_text_draw(C, seq, &handle);
|
||||
|
||||
if (&handle == handles.begin()) {
|
||||
// continue; /* Ignore first handle. */
|
||||
continue; /* Ignore first handle. */
|
||||
}
|
||||
retime_handle_draw(C, gizmo, pos, seq, &handle);
|
||||
}
|
||||
|
|
|
@ -198,20 +198,48 @@ static int sequencer_retiming_handle_move_modal(bContext *C, wmOperator *op, con
|
|||
|
||||
/* Add retiming gradient and move handle. */
|
||||
if (op->customdata) {
|
||||
SeqRetimingHandle *gradient_handle = SEQ_retiming_add_transition(
|
||||
SeqRetimingHandle *transition_handle = SEQ_retiming_add_transition(
|
||||
scene, seq, handle, abs(offset));
|
||||
/* New gradient handle was created - update operator properties. */
|
||||
if (gradient_handle != nullptr) {
|
||||
if (transition_handle != nullptr) {
|
||||
if (offset < 0) {
|
||||
handle = gradient_handle;
|
||||
handle = transition_handle;
|
||||
}
|
||||
else {
|
||||
handle = gradient_handle + 1;
|
||||
handle = transition_handle + 1;
|
||||
}
|
||||
RNA_int_set(op->ptr, "handle_index", SEQ_retiming_handle_index_get(seq, handle));
|
||||
}
|
||||
}
|
||||
|
||||
bool handle_is_transition = SEQ_retiming_handle_is_transition_type(handle);
|
||||
bool prev_handle_is_transition = SEQ_retiming_handle_is_transition_type(handle - 1);
|
||||
|
||||
/* When working with transiton, change handles when moving past pivot point. */
|
||||
if (handle_is_transition || prev_handle_is_transition) {
|
||||
SeqRetimingHandle *transition_start, *transition_end;
|
||||
if (handle_is_transition) {
|
||||
transition_start = handle;
|
||||
transition_end = handle + 1;
|
||||
}
|
||||
else {
|
||||
transition_start = handle - 1;
|
||||
transition_end = handle;
|
||||
}
|
||||
int offset_l = mouse_x -
|
||||
SEQ_retiming_handle_timeline_frame_get(scene, seq, transition_start);
|
||||
int offset_r = mouse_x -
|
||||
SEQ_retiming_handle_timeline_frame_get(scene, seq, transition_end);
|
||||
|
||||
if (prev_handle_is_transition && offset_l < 0) {
|
||||
RNA_int_set(
|
||||
op->ptr, "handle_index", SEQ_retiming_handle_index_get(seq, transition_start));
|
||||
}
|
||||
if (handle_is_transition && offset_r > 0) {
|
||||
RNA_int_set(op->ptr, "handle_index", SEQ_retiming_handle_index_get(seq, transition_end));
|
||||
}
|
||||
}
|
||||
|
||||
SEQ_retiming_offset_handle(scene, seq, handle, offset);
|
||||
|
||||
SEQ_relations_invalidate_cache_raw(scene, seq);
|
||||
|
|
|
@ -200,6 +200,17 @@ static bool seq_retiming_transition_is_linear(const Sequence *seq, const SeqReti
|
|||
|
||||
return abs(prev_speed - next_speed) < 0.01f;
|
||||
}
|
||||
|
||||
static float seq_retiming_evaluate_arc_segment(const SeqRetimingHandle *handle,
|
||||
const float frame_index)
|
||||
{
|
||||
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));
|
||||
return y;
|
||||
}
|
||||
|
||||
float seq_retiming_evaluate(const Sequence *seq, const float frame_index)
|
||||
{
|
||||
const SeqRetimingHandle *start_handle = SEQ_retiming_find_segment_start_handle(seq, frame_index);
|
||||
|
@ -219,17 +230,12 @@ float seq_retiming_evaluate(const Sequence *seq, const float frame_index)
|
|||
return start_handle->retiming_factor + segment_step * segment_frame_index;
|
||||
}
|
||||
|
||||
double c[2], r;
|
||||
seq_retiming_line_segments_tangent_circle(start_handle, c, &r);
|
||||
|
||||
/* Gradual speed change. */
|
||||
BLI_assert(start_handle_index > 0);
|
||||
BLI_assert(start_handle_index < seq->retiming_handle_num - 1);
|
||||
UNUSED_VARS_NDEBUG(start_handle_index);
|
||||
|
||||
const int side = c[1] > start_handle->retiming_factor ? -1 : 1;
|
||||
const float y = c[1] + side * sqrt(pow(r, 2) - pow((frame_index - c[0]), 2));
|
||||
return y;
|
||||
return seq_retiming_evaluate_arc_segment(start_handle, frame_index);
|
||||
}
|
||||
|
||||
SeqRetimingHandle *SEQ_retiming_add_handle(const Scene *scene,
|
||||
|
@ -283,8 +289,27 @@ static void seq_retiming_offset_linear_handle(const Scene *scene,
|
|||
const int offset)
|
||||
{
|
||||
MutableSpan handles = SEQ_retiming_handles_get(seq);
|
||||
for (; handle < handles.end(); handle++) {
|
||||
handle->strip_frame_index += offset * seq_time_media_playback_rate_factor_get(scene, 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);
|
||||
}
|
||||
|
||||
/* One solution is to find where in arc segment the y val is closest to `handle` retiming factor,
|
||||
* then trim arc segment to that point.
|
||||
* Alternative is quite destructive, but easiest - remove and re-create transition. This way
|
||||
* transition won't change length.
|
||||
*/
|
||||
if (SEQ_retiming_handle_is_transition_type(handle - 2)) {
|
||||
SeqRetimingHandle *transition_handle = handle - 2;
|
||||
|
||||
const int transition_offset = transition_handle->strip_frame_index -
|
||||
transition_handle->original_strip_frame_index;
|
||||
|
||||
const int transition_handle_index = SEQ_retiming_handle_index_get(seq, transition_handle);
|
||||
|
||||
SEQ_retiming_remove_handle(scene, seq, transition_handle);
|
||||
SeqRetimingHandle *orig_handle = seq->retiming_handles + transition_handle_index;
|
||||
SEQ_retiming_add_transition(scene, seq, orig_handle, -transition_offset);
|
||||
}
|
||||
|
||||
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
|
||||
|
@ -351,8 +376,14 @@ void SEQ_retiming_offset_handle(const Scene *scene,
|
|||
int handle_frame = SEQ_retiming_handle_timeline_frame_get(scene, seq, handle);
|
||||
int offset_min = SEQ_retiming_handle_timeline_frame_get(scene, seq, prev_handle) + 1 -
|
||||
handle_frame;
|
||||
int offset_max = SEQ_retiming_handle_timeline_frame_get(scene, seq, next_handle) - 1 -
|
||||
handle_frame;
|
||||
int offset_max;
|
||||
if (SEQ_retiming_handle_index_get(seq, handle) == seq->retiming_handle_num - 1) {
|
||||
offset_max = INT_MAX;
|
||||
}
|
||||
else {
|
||||
offset_max = SEQ_retiming_handle_timeline_frame_get(scene, seq, next_handle) - 1 -
|
||||
handle_frame;
|
||||
}
|
||||
corrected_offset = max_ii(corrected_offset, offset_min);
|
||||
corrected_offset = min_ii(corrected_offset, offset_max);
|
||||
|
||||
|
|
Loading…
Reference in New Issue