VSE UX: Make Speed Effect strips more user friendly.

**Drawing Changes:**
- F-curve drawing for Stretch, Multiply, Length and Frame Number.
- Value drawing when no keyframes for Stretch, Length and Frame Numbers.

General view of the new drawing for each speed effect mode:
{F9796642, size=full}

Detail of the horizontal zero (blue) line in the new `Multiply` mode:
{F9798520, size=full}

Nice to have (but I don't know how):
- Auto adjusting of endframe when using Multiply or Boost.

Differential Revision: https://developer.blender.org/D6110
This commit is contained in:
Germano Cavalcante 2021-07-23 10:02:33 -03:00 committed by Germano Cavalcante
parent 5e3d0840a3
commit a092baa7f9
Notes: blender-bot 2023-02-13 11:53:23 +01:00
Referenced by commit 8031326262, Revert "VSE UX: Make Speed Effect strips more user friendly."
3 changed files with 133 additions and 7 deletions

View File

@ -92,6 +92,8 @@
#include "MEM_guardedalloc.h"
#include "intern/effects.h"
/* Own include. */
#include "sequencer_intern.h"
@ -1008,12 +1010,41 @@ static void fcurve_batch_add_verts(GPUVertBuf *vbo,
* - Volume for sound strips.
* - Opacity for the other types.
*/
static void draw_seq_fcurve_overlay(
Scene *scene, View2D *v2d, Sequence *seq, float x1, float y1, float x2, float y2, float pixelx)
static void draw_seq_fcurve_overlay(Scene *scene,
View2D *v2d,
Sequence *seq,
float x1,
float y1,
float x2,
float y2,
float pixelx,
float pixely)
{
SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
FCurve *fcu;
double curve_val;
if (seq->type == SEQ_TYPE_SOUND_RAM) {
if (seq->type == SEQ_TYPE_SPEED) {
switch (v->speed_control_type) {
case SEQ_SPEED_MULTIPLY: {
fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL);
break;
}
case SEQ_SPEED_FRAME_NUMBER: {
fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_frame_number", 0, NULL);
break;
}
case SEQ_SPEED_LENGTH: {
fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_length", 0, NULL);
break;
}
case SEQ_SPEED_STRETCH: {
fcu = NULL;
break;
}
}
}
else if (seq->type == SEQ_TYPE_SOUND_RAM) {
fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, NULL);
}
else {
@ -1041,13 +1072,66 @@ static void draw_seq_fcurve_overlay(
uint vert_count = 0;
const float y_height = y2 - y1;
float curve_val;
float prev_val = INT_MIN;
bool skip = false;
double ymax = 1.0;
double ymin = 0.0;
if (seq->type == SEQ_TYPE_SPEED) {
SEQ_effect_handle_get(seq);
switch (v->speed_control_type) {
case SEQ_SPEED_LENGTH: {
ymin = 0.0;
ymax = 100.0;
break;
}
case SEQ_SPEED_FRAME_NUMBER: {
ymin = 0;
ymax = seq_effect_speed_get_strip_content_length(seq->seq1);
break;
}
case SEQ_SPEED_MULTIPLY: {
ymin = 0.0;
ymax = 0.0;
/* Get range. */
for (int timeline_frame = eval_start; timeline_frame <= eval_end;
timeline_frame += eval_step) {
curve_val = evaluate_fcurve(fcu, timeline_frame);
if (curve_val > ymax) {
ymax = curve_val;
}
if (curve_val < ymin) {
ymin = curve_val;
}
}
if (ymin < 0) {
ymax = ymax + fabs(ymin);
ymin = fabs(ymin);
}
else {
ymax = ymax - ymin;
ymin = -ymin;
}
}
}
}
for (int timeline_frame = eval_start; timeline_frame <= eval_end;
timeline_frame += eval_step) {
curve_val = evaluate_fcurve(fcu, timeline_frame);
if (seq->type == SEQ_TYPE_SPEED) {
curve_val = evaluate_fcurve(fcu, timeline_frame);
if (v->speed_control_type == SEQ_SPEED_MULTIPLY) {
curve_val = (((curve_val + ymin) / (ymax + ymin)) * v->globalSpeed);
}
else {
curve_val = ((curve_val / (ymax - ymin)) * v->globalSpeed);
}
}
else {
curve_val = evaluate_fcurve(fcu, timeline_frame);
}
CLAMP(curve_val, 0.0f, 1.0f);
/* Avoid adding adjacent verts that have the same value. */
@ -1079,6 +1163,47 @@ static void draw_seq_fcurve_overlay(
GPU_blend(GPU_BLEND_NONE);
GPU_batch_discard(batch);
if ((v->speed_control_type == SEQ_SPEED_MULTIPLY) && (ymin > 0.0f)) {
/* Draw line at zero. */
uint pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPU_blend(GPU_BLEND_ALPHA);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShade(TH_CFRAME, -10);
immRectf(
pos, x1, (ymin / (ymax + ymin)) + y1, x2, (ymin / (ymax + ymin)) + y1 + (2 * pixely));
immUnbindProgram();
}
}
else {
/* Draw the values without f-curves. */
if (seq->type == SEQ_TYPE_SPEED) {
if (v->speed_control_type == SEQ_SPEED_FRAME_NUMBER) {
curve_val = ((float)v->speed_fader_frame_number /
(float)seq_effect_speed_get_strip_content_length(seq->seq1));
}
else if (v->speed_control_type == SEQ_SPEED_LENGTH) {
curve_val = (v->speed_fader_length / 100);
}
else if (v->speed_control_type == SEQ_SPEED_STRETCH) {
const int target_strip_length = seq_effect_speed_get_strip_content_length(seq->seq1);
if ((seq->seq1->enddisp != seq->seq1->start) && (target_strip_length != 0)) {
curve_val = (float)target_strip_length / (float)(seq->seq1->enddisp - seq->seq1->start);
}
}
else {
curve_val = 0;
}
CLAMP(curve_val, 0.0f, 1.0f);
uint pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPU_blend(GPU_BLEND_ALPHA);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ub(0, 0, 0, 51);
immRectf(pos, x1, ((y2 - y1) * curve_val) + y1, x2, y2);
immUnbindProgram();
}
}
}
@ -1154,7 +1279,7 @@ static void draw_seq_strip(const bContext *C,
}
if ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY) && (sseq->flag & SEQ_SHOW_FCURVES)) {
draw_seq_fcurve_overlay(scene, v2d, seq, x1, y1, x2, y2, pixelx);
draw_seq_fcurve_overlay(scene, v2d, seq, x1, y1, x2, y2, pixelx, pixely);
}
/* Draw sound strip waveform. */

View File

@ -3136,7 +3136,7 @@ static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(facf0), float UNU
* useful to use speed effect on these strips because they can be animated. This can be done by
* using their length as is on timeline as content length. See T82698.
*/
static int seq_effect_speed_get_strip_content_length(const Sequence *seq)
int seq_effect_speed_get_strip_content_length(const Sequence *seq)
{
if ((seq->type & SEQ_TYPE_EFFECT) != 0 && SEQ_effect_get_num_inputs(seq->type) == 0) {
return seq->enddisp - seq->startdisp;

View File

@ -39,6 +39,7 @@ struct Sequence;
*/
struct SeqEffectHandle seq_effect_get_sequence_blend(struct Sequence *seq);
int seq_effect_speed_get_strip_content_length(const struct Sequence *seq);
void seq_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, bool force);
float seq_speed_effect_target_frame_get(const struct SeqRenderData *context,
struct Sequence *seq,