VSE: speedup timeline drawing, and improve waveform display #115311
|
@ -35,6 +35,7 @@ set(SRC
|
|||
sequencer_preview.cc
|
||||
sequencer_preview_draw.cc
|
||||
sequencer_proxy.cc
|
||||
sequencer_quads_batch.cc
|
||||
sequencer_retiming.cc
|
||||
sequencer_retiming_draw.cc
|
||||
sequencer_scopes.cc
|
||||
|
@ -45,6 +46,7 @@ set(SRC
|
|||
space_sequencer.cc
|
||||
|
||||
sequencer_intern.hh
|
||||
sequencer_quads_batch.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
/* Internal exports only. */
|
||||
|
||||
class SeqQuadsBatch;
|
||||
struct ARegion;
|
||||
struct ARegionType;
|
||||
struct Depsgraph;
|
||||
|
@ -317,7 +318,7 @@ int sequencer_retiming_select_all_exec(bContext *C, wmOperator *op);
|
|||
int sequencer_retiming_box_select_exec(bContext *C, wmOperator *op);
|
||||
|
||||
/* `sequencer_retiming_draw.cc` */
|
||||
void sequencer_draw_retiming(const bContext *C);
|
||||
void sequencer_draw_retiming(const bContext *C, SeqQuadsBatch *quads);
|
||||
blender::Vector<Sequence *> sequencer_visible_strips_get(const bContext *C);
|
||||
SeqRetimingKey *try_to_realize_virtual_key(const bContext *C, Sequence *seq, const int mval[2]);
|
||||
SeqRetimingKey *retiming_mousover_key_get(const bContext *C, const int mval[2], Sequence **r_seq);
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spseq
|
||||
*/
|
||||
|
||||
#include "sequencer_quads_batch.hh"
|
||||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "GPU_batch.h"
|
||||
#include "GPU_index_buffer.h"
|
||||
#include "GPU_vertex_buffer.h"
|
||||
|
||||
struct ColorVertex {
|
||||
blender::float2 pos;
|
||||
blender::ColorTheme4b color;
|
||||
};
|
||||
static_assert(sizeof(ColorVertex) == 12);
|
||||
|
||||
static GPUIndexBuf *create_quads_index_buffer(int quads_count)
|
||||
{
|
||||
GPUIndexBufBuilder elb;
|
||||
GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, quads_count * 2, quads_count * 4);
|
||||
for (int i = 0; i < quads_count; i++) {
|
||||
const uint i0 = i * 4 + 0;
|
||||
const uint i1 = i * 4 + 1;
|
||||
const uint i2 = i * 4 + 2;
|
||||
const uint i3 = i * 4 + 3;
|
||||
GPU_indexbuf_add_tri_verts(&elb, i0, i1, i2);
|
||||
GPU_indexbuf_add_tri_verts(&elb, i2, i1, i3);
|
||||
}
|
||||
return GPU_indexbuf_build(&elb);
|
||||
}
|
||||
|
||||
SeqQuadsBatch::SeqQuadsBatch()
|
||||
{
|
||||
ibo_quads = create_quads_index_buffer(MAX_QUADS);
|
||||
|
||||
GPUVertFormat format;
|
||||
GPU_vertformat_clear(&format);
|
||||
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
GPU_vertformat_attr_add(&format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
|
||||
vbo_quads = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STREAM);
|
||||
GPU_vertbuf_data_alloc(vbo_quads, MAX_QUADS * 4);
|
||||
|
||||
vbo_lines = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STREAM);
|
||||
GPU_vertbuf_data_alloc(vbo_lines, MAX_LINES * 2);
|
||||
|
||||
batch_quads = GPU_batch_create_ex(
|
||||
GPU_PRIM_TRIS, vbo_quads, ibo_quads, GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
|
||||
GPU_batch_program_set_builtin(batch_quads, GPU_SHADER_3D_FLAT_COLOR);
|
||||
|
||||
batch_lines = GPU_batch_create_ex(GPU_PRIM_LINES, vbo_lines, nullptr, GPU_BATCH_OWNS_VBO);
|
||||
GPU_batch_program_set_builtin(batch_lines, GPU_SHADER_3D_FLAT_COLOR);
|
||||
}
|
||||
|
||||
SeqQuadsBatch::~SeqQuadsBatch()
|
||||
{
|
||||
BLI_assert_msg(quads_num == 0 && lines_num == 0,
|
||||
"SeqQuadsBatch is being destroyed without drawing quads/lines it contains");
|
||||
GPU_batch_discard(batch_quads);
|
||||
GPU_batch_discard(batch_lines);
|
||||
}
|
||||
|
||||
void SeqQuadsBatch::draw()
|
||||
{
|
||||
if (quads_num > 0) {
|
||||
GPU_vertbuf_tag_dirty(vbo_quads);
|
||||
GPU_vertbuf_data_len_set(vbo_quads, quads_num * 4);
|
||||
GPU_vertbuf_use(vbo_quads);
|
||||
GPU_batch_draw_range(batch_quads, 0, quads_num * 6);
|
||||
quads_num = 0;
|
||||
verts_quads = nullptr;
|
||||
}
|
||||
if (lines_num > 0) {
|
||||
GPU_vertbuf_tag_dirty(vbo_lines);
|
||||
GPU_vertbuf_data_len_set(vbo_lines, lines_num * 4);
|
||||
GPU_vertbuf_use(vbo_lines);
|
||||
GPU_batch_draw_range(batch_lines, 0, lines_num * 2);
|
||||
lines_num = 0;
|
||||
verts_lines = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SeqQuadsBatch::add_quad(float x1, float y1, float x2, float y2, const uchar color[4])
|
||||
{
|
||||
if (quads_num >= MAX_QUADS) {
|
||||
draw();
|
||||
}
|
||||
if (quads_num == 0) {
|
||||
/* Don't actually need this, but it's the only way to clear GPU_VERTBUF_DATA_UPLOADED flag. */
|
||||
GPUVertBufRaw attr_data;
|
||||
GPU_vertbuf_attr_get_raw_data(vbo_quads, 0, &attr_data);
|
||||
|
||||
verts_quads = (ColorVertex *)GPU_vertbuf_get_data(vbo_quads);
|
||||
BLI_assert(verts_quads != nullptr);
|
||||
}
|
||||
|
||||
ColorVertex v0 = {blender::float2(x1, y1), color};
|
||||
aras_p marked this conversation as resolved
|
||||
ColorVertex v1 = {blender::float2(x1, y2), color};
|
||||
ColorVertex v2 = {blender::float2(x2, y1), color};
|
||||
ColorVertex v3 = {blender::float2(x2, y2), color};
|
||||
|
||||
aras_p marked this conversation as resolved
Outdated
Richard Antalik
commented
Use Use `static_cast` for casting types, see https://wiki.blender.org/wiki/Style_Guide/C_Cpp#C.2B.2B_Type_Cast
|
||||
*verts_quads++ = v0;
|
||||
*verts_quads++ = v1;
|
||||
*verts_quads++ = v2;
|
||||
*verts_quads++ = v3;
|
||||
|
||||
quads_num++;
|
||||
}
|
||||
|
||||
void SeqQuadsBatch::add_wire_quad(float x1, float y1, float x2, float y2, const uchar color[4])
|
||||
{
|
||||
if (lines_num + 4 > MAX_LINES) {
|
||||
draw();
|
||||
}
|
||||
if (lines_num == 0) {
|
||||
/* Don't actually need this, but it's the only way to clear GPU_VERTBUF_DATA_UPLOADED flag. */
|
||||
GPUVertBufRaw attr_data;
|
||||
GPU_vertbuf_attr_get_raw_data(vbo_lines, 0, &attr_data);
|
||||
|
||||
verts_lines = (ColorVertex *)GPU_vertbuf_get_data(vbo_lines);
|
||||
BLI_assert(verts_lines != nullptr);
|
||||
}
|
||||
|
||||
ColorVertex v0 = {blender::float2(x1, y1), color};
|
||||
ColorVertex v1 = {blender::float2(x1, y2), color};
|
||||
ColorVertex v2 = {blender::float2(x2, y1), color};
|
||||
ColorVertex v3 = {blender::float2(x2, y2), color};
|
||||
|
||||
/* Left */
|
||||
*verts_lines++ = v0;
|
||||
*verts_lines++ = v1;
|
||||
/* Right */
|
||||
*verts_lines++ = v2;
|
||||
*verts_lines++ = v3;
|
||||
/* Bottom */
|
||||
*verts_lines++ = v0;
|
||||
*verts_lines++ = v2;
|
||||
/* Top */
|
||||
*verts_lines++ = v1;
|
||||
*verts_lines++ = v3;
|
||||
|
||||
lines_num += 4;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spseq
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
struct GPUVertBuf;
|
||||
struct GPUIndexBuf;
|
||||
struct GPUBatch;
|
||||
struct ColorVertex;
|
||||
|
||||
class SeqQuadsBatch {
|
||||
public:
|
||||
SeqQuadsBatch();
|
||||
~SeqQuadsBatch();
|
||||
|
||||
void draw();
|
||||
void add_quad(float x1, float y1, float x2, float y2, const uchar color[4]);
|
||||
void add_wire_quad(float x1, float y1, float x2, float y2, const uchar color[4]);
|
||||
|
||||
private:
|
||||
static constexpr int MAX_QUADS = 1024;
|
||||
static constexpr int MAX_LINES = 4096;
|
||||
|
||||
GPUVertBuf *vbo_quads = nullptr;
|
||||
GPUIndexBuf *ibo_quads = nullptr;
|
||||
GPUBatch *batch_quads = nullptr;
|
||||
ColorVertex *verts_quads = nullptr;
|
||||
int quads_num = 0;
|
||||
|
||||
GPUVertBuf *vbo_lines = nullptr;
|
||||
GPUBatch *batch_lines = nullptr;
|
||||
ColorVertex *verts_lines = nullptr;
|
||||
int lines_num = 0;
|
||||
};
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
/* Own include. */
|
||||
#include "sequencer_intern.hh"
|
||||
#include "sequencer_quads_batch.hh"
|
||||
|
||||
#define KEY_SIZE (10 * U.pixelsize)
|
||||
#define KEY_CENTER (UI_view2d_view_to_region_y(v2d, strip_y_rescale(seq, 0.0f)) + 4 + KEY_SIZE / 2)
|
||||
|
@ -261,7 +262,13 @@ SeqRetimingKey *retiming_mousover_key_get(const bContext *C, const int mval[2],
|
|||
/** \name Retiming Key
|
||||
* \{ */
|
||||
|
||||
static void retime_key_draw(const bContext *C, const Sequence *seq, const SeqRetimingKey *key)
|
||||
constexpr int MAX_KEYS_IN_BATCH = 1024;
|
||||
|
||||
static void retime_key_draw(const bContext *C,
|
||||
const Sequence *seq,
|
||||
const SeqRetimingKey *key,
|
||||
const KeyframeShaderBindings *sh_bindings,
|
||||
int *r_point_counter)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const float key_x = key_x_get(scene, seq, key);
|
||||
|
@ -272,24 +279,6 @@ static void retime_key_draw(const bContext *C, const Sequence *seq, const SeqRet
|
|||
return; /* Key out of the strip bounds. */
|
||||
}
|
||||
|
||||
GPUVertFormat *format = immVertexFormat();
|
||||
KeyframeShaderBindings sh_bindings;
|
||||
|
||||
sh_bindings.pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
sh_bindings.size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
sh_bindings.color_id = GPU_vertformat_attr_add(
|
||||
format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
sh_bindings.outline_color_id = GPU_vertformat_attr_add(
|
||||
format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
sh_bindings.flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
|
||||
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
GPU_program_point_size(true);
|
||||
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_SHAPE);
|
||||
immUniform1f("outline_scale", 1.0f);
|
||||
immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
|
||||
immBegin(GPU_PRIM_POINTS, 1);
|
||||
|
||||
eBezTriple_KeyframeType key_type = BEZT_KEYTYPE_KEYFRAME;
|
||||
if (SEQ_retiming_key_is_freeze_frame(key)) {
|
||||
key_type = BEZT_KEYTYPE_BREAKDOWN;
|
||||
|
@ -313,6 +302,12 @@ static void retime_key_draw(const bContext *C, const Sequence *seq, const SeqRet
|
|||
CLAMP(key_position, left_pos_min, right_pos_max);
|
||||
const float alpha = SEQ_retiming_data_is_editable(seq) ? 1.0f : 0.3f;
|
||||
|
||||
if (*r_point_counter >= MAX_KEYS_IN_BATCH) {
|
||||
immEnd();
|
||||
aras_p marked this conversation as resolved
Outdated
Richard Antalik
commented
Bit nitpicky, but to me this feels bit out of place here. This could be done in loop in Bit nitpicky, but to me this feels bit out of place here. This could be done in loop in `retime_keys_draw()`. That way you don't have to pass `point_counter` around. You can assume, that `fake_keys_draw()` draws 2 vertices, and `retime_key_draw()` draws 1.
|
||||
immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH);
|
||||
*r_point_counter = 0;
|
||||
}
|
||||
|
||||
draw_keyframe_shape(key_position,
|
||||
bottom,
|
||||
size,
|
||||
|
@ -320,16 +315,16 @@ static void retime_key_draw(const bContext *C, const Sequence *seq, const SeqRet
|
|||
key_type,
|
||||
KEYFRAME_SHAPE_BOTH,
|
||||
alpha,
|
||||
&sh_bindings,
|
||||
sh_bindings,
|
||||
aras_p marked this conversation as resolved
Outdated
Richard Antalik
commented
Sorry, I have noticed this only now, you should avoid passing pointers to objects, pass reference instead. So argument would be Sorry, I have noticed this only now, you should avoid passing pointers to objects, pass reference instead.
So argument would be `const blender::Set<const SeqRetimingKey *> &selection`
|
||||
0,
|
||||
0);
|
||||
immEnd();
|
||||
GPU_program_point_size(false);
|
||||
immUnbindProgram();
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
*r_point_counter = *r_point_counter + 1;
|
||||
}
|
||||
|
||||
static void draw_continuity(const bContext *C, const Sequence *seq, const SeqRetimingKey *key)
|
||||
static void draw_continuity(const bContext *C,
|
||||
const Sequence *seq,
|
||||
const SeqRetimingKey *key,
|
||||
SeqQuadsBatch *quads)
|
||||
{
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
|
@ -358,26 +353,30 @@ static void draw_continuity(const bContext *C, const Sequence *seq, const SeqRet
|
|||
const float bottom = y_center - size * width_fac;
|
||||
const float top = y_center + size * width_fac;
|
||||
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
|
||||
uchar color[4];
|
||||
if (SEQ_retiming_data_is_editable(seq) &&
|
||||
(SEQ_retiming_selection_contains(ed, key) || SEQ_retiming_selection_contains(ed, key - 1)))
|
||||
{
|
||||
immUniform4f("color", 0.65f, 0.5f, 0.2f, 1.0f);
|
||||
color[0] = 166;
|
||||
color[1] = 127;
|
||||
color[2] = 51;
|
||||
color[3] = 255;
|
||||
}
|
||||
else {
|
||||
immUniform4f("color", 0.0f, 0.0f, 0.0f, 0.1f);
|
||||
color[0] = 0;
|
||||
color[1] = 0;
|
||||
color[2] = 0;
|
||||
color[3] = 25;
|
||||
}
|
||||
immRectf(pos, prev_key_position, bottom, key_position, top);
|
||||
immUnbindProgram();
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
quads->add_quad(prev_key_position, bottom, key_position, top, color);
|
||||
}
|
||||
|
||||
/* If there are no keys, draw fake keys and create real key when they are selected. */
|
||||
/* TODO: would be nice to draw continuity between fake keys. */
|
||||
static void fake_keys_draw(const bContext *C, Sequence *seq)
|
||||
static void fake_keys_draw(const bContext *C,
|
||||
Sequence *seq,
|
||||
const KeyframeShaderBindings *sh_bindings,
|
||||
int *r_point_counter)
|
||||
{
|
||||
if (!SEQ_retiming_is_active(seq) && !SEQ_retiming_data_is_editable(seq)) {
|
||||
return;
|
||||
|
@ -391,18 +390,18 @@ static void fake_keys_draw(const bContext *C, Sequence *seq)
|
|||
SeqRetimingKey fake_key;
|
||||
fake_key.strip_frame_index = left_key_frame - SEQ_time_start_frame_get(seq);
|
||||
fake_key.flag = 0;
|
||||
retime_key_draw(C, seq, &fake_key);
|
||||
retime_key_draw(C, seq, &fake_key, sh_bindings, r_point_counter);
|
||||
}
|
||||
|
||||
if (SEQ_retiming_key_get_by_timeline_frame(scene, seq, right_key_frame) == nullptr) {
|
||||
SeqRetimingKey fake_key;
|
||||
fake_key.strip_frame_index = right_key_frame - SEQ_time_start_frame_get(seq);
|
||||
fake_key.flag = 0;
|
||||
retime_key_draw(C, seq, &fake_key);
|
||||
retime_key_draw(C, seq, &fake_key, sh_bindings, r_point_counter);
|
||||
}
|
||||
}
|
||||
|
||||
static void retime_keys_draw(const bContext *C)
|
||||
static void retime_keys_draw(const bContext *C, SeqQuadsBatch *quads)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
if (scene->ed == nullptr) {
|
||||
|
@ -415,20 +414,58 @@ static void retime_keys_draw(const bContext *C)
|
|||
|
||||
wmOrtho2_region_pixelspace(CTX_wm_region(C));
|
||||
|
||||
for (Sequence *seq : sequencer_visible_strips_get(C)) {
|
||||
blender::Vector<Sequence *> strips = sequencer_visible_strips_get(C);
|
||||
|
||||
aras_p marked this conversation as resolved
Outdated
Richard Antalik
commented
Can't you just pass map returnd by Can't you just pass map returnd by `SEQ_retiming_selection_get()` and use `contains()` method? This seems like unnecessary code duplication.
Aras Pranckevicius
commented
That's what I tried initially, but SEQ_retiming_selection_get returns non-const Sequence pointers as map keys, and my C++-fu is not strong enough to find the magic incantation, how to use That's what I tried initially, but SEQ_retiming_selection_get returns non-const Sequence pointers as map keys, and my C++-fu is not strong enough to find the magic incantation, how to use `contains()` when I have a const-Sequence pointer. `contains_as()` with const pointer does not compile, at least on visual studio.
Richard Antalik
commented
I am not great with C++ either, but you can use non-const There is also I am not great with C++ either, but you can use non-const `SeqRetimingKey` for iteration.
There is also `const_cast` which seems to work, but not sure if it is good idea to use it in this case.
|
||||
/* Draw all continuity sections. */
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
for (Sequence *seq : strips) {
|
||||
if (!SEQ_retiming_is_allowed(seq)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) {
|
||||
draw_continuity(C, seq, &key);
|
||||
}
|
||||
|
||||
fake_keys_draw(C, seq);
|
||||
for (const SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) {
|
||||
retime_key_draw(C, seq, &key);
|
||||
draw_continuity(C, seq, &key, quads);
|
||||
}
|
||||
}
|
||||
quads->draw();
|
||||
|
||||
/* Draw all keys. */
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
|
||||
GPUVertFormat *format = immVertexFormat();
|
||||
KeyframeShaderBindings sh_bindings;
|
||||
|
||||
sh_bindings.pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
sh_bindings.size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
sh_bindings.color_id = GPU_vertformat_attr_add(
|
||||
format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
sh_bindings.outline_color_id = GPU_vertformat_attr_add(
|
||||
format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
||||
sh_bindings.flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
|
||||
|
||||
GPU_program_point_size(true);
|
||||
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_SHAPE);
|
||||
immUniform1f("outline_scale", 1.0f);
|
||||
immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
|
||||
immBeginAtMost(GPU_PRIM_POINTS, MAX_KEYS_IN_BATCH);
|
||||
|
||||
int point_counter = 0;
|
||||
for (Sequence *seq : strips) {
|
||||
if (!SEQ_retiming_is_allowed(seq)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fake_keys_draw(C, seq, &sh_bindings, &point_counter);
|
||||
for (const SeqRetimingKey &key : SEQ_retiming_keys_get(seq)) {
|
||||
retime_key_draw(C, seq, &key, &sh_bindings, &point_counter);
|
||||
}
|
||||
}
|
||||
if (point_counter != 0) {
|
||||
aras_p marked this conversation as resolved
Outdated
Richard Antalik
commented
I could have specified this a bit more, you can have just 1 condition This way batch should never be overfilled, and from what I read, with I could have specified this a bit more, you can have just 1 condition
`if (point_counter + 3 > MAX_KEYS_IN_BATCH) {` after `retime_key_draw()`
This way batch should never be overfilled, and from what I read, with `immBeginAtMost()` you can always draw less vertices.
|
||||
immEnd();
|
||||
}
|
||||
GPU_program_point_size(false);
|
||||
immUnbindProgram();
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -550,8 +587,8 @@ static void retime_speed_draw(const bContext *C)
|
|||
|
||||
/** \} */
|
||||
|
||||
void sequencer_draw_retiming(const bContext *C)
|
||||
void sequencer_draw_retiming(const bContext *C, SeqQuadsBatch *quads)
|
||||
{
|
||||
retime_keys_draw(C);
|
||||
retime_keys_draw(C, quads);
|
||||
retime_speed_draw(C);
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
|
||||
/* Own include. */
|
||||
#include "sequencer_intern.hh"
|
||||
#include "sequencer_quads_batch.hh"
|
||||
|
||||
#define SEQ_LEFTHANDLE 1
|
||||
#define SEQ_RIGHTHANDLE 2
|
||||
|
@ -105,6 +106,8 @@ struct TimelineDrawContext {
|
|||
GPUViewport *viewport;
|
||||
GPUFrameBuffer *framebuffer_overlay;
|
||||
float pixelx, pixely; /* Width and height of pixel in timeline space. */
|
||||
|
||||
SeqQuadsBatch *quads;
|
||||
};
|
||||
|
||||
static TimelineDrawContext timeline_draw_context_get(const bContext *C)
|
||||
|
@ -147,7 +150,8 @@ static bool seq_draw_waveforms_poll(const bContext * /*C*/, SpaceSeq *sseq, Sequ
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool strip_hides_text_overlay_first(TimelineDrawContext *ctx, StripDrawContext *strip_ctx)
|
||||
static bool strip_hides_text_overlay_first(TimelineDrawContext *ctx,
|
||||
const StripDrawContext *strip_ctx)
|
||||
{
|
||||
return seq_draw_waveforms_poll(ctx->C, ctx->sseq, strip_ctx->seq) ||
|
||||
strip_ctx->seq->type == SEQ_TYPE_COLOR;
|
||||
|
@ -527,7 +531,7 @@ static size_t waveform_append_sample(WaveVizData *waveform_data,
|
|||
}
|
||||
|
||||
static void draw_seq_waveform_overlay(TimelineDrawContext *timeline_ctx,
|
||||
StripDrawContext *strip_ctx)
|
||||
const StripDrawContext *strip_ctx)
|
||||
{
|
||||
if (!seq_draw_waveforms_poll(timeline_ctx->C, timeline_ctx->sseq, strip_ctx->seq) ||
|
||||
strip_ctx->strip_is_too_small)
|
||||
|
@ -650,7 +654,7 @@ static void draw_seq_waveform_overlay(TimelineDrawContext *timeline_ctx,
|
|||
MEM_freeN(waveform_data);
|
||||
}
|
||||
|
||||
static void drawmeta_contents(TimelineDrawContext *timeline_ctx, StripDrawContext *strip_ctx)
|
||||
static void drawmeta_contents(TimelineDrawContext *timeline_ctx, const StripDrawContext *strip_ctx)
|
||||
{
|
||||
Sequence *seq_meta = strip_ctx->seq;
|
||||
if (!strip_ctx->can_draw_strip_content || (timeline_ctx->sseq->flag & SEQ_SHOW_OVERLAY) == 0) {
|
||||
|
@ -765,168 +769,173 @@ float sequence_handle_size_get_clamped(const Scene *scene, Sequence *seq, const
|
|||
4.0f));
|
||||
}
|
||||
|
||||
/* Draw a handle, on left or right side of strip. */
|
||||
/* Draw handles, on left or right side of the strips. */
|
||||
static void draw_seq_handle(TimelineDrawContext *timeline_ctx,
|
||||
StripDrawContext *strip_ctx,
|
||||
const blender::Vector<StripDrawContext> &strips,
|
||||
const short direction)
|
||||
{
|
||||
Sequence *seq = strip_ctx->seq;
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
if (SEQ_transform_is_locked(timeline_ctx->channels, seq)) {
|
||||
return;
|
||||
}
|
||||
for (const StripDrawContext &strip_ctx : strips) {
|
||||
Sequence *seq = strip_ctx.seq;
|
||||
if (SEQ_transform_is_locked(timeline_ctx->channels, seq)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint whichsel = 0;
|
||||
uchar col[4];
|
||||
uint whichsel = 0;
|
||||
uchar col[4];
|
||||
|
||||
/* Set up co-ordinates and dimensions for either left or right handle. */
|
||||
rctf handle = {0, 0, strip_ctx->bottom, strip_ctx->top};
|
||||
if (direction == SEQ_LEFTHANDLE) {
|
||||
handle.xmin = strip_ctx->left_handle;
|
||||
handle.xmax = strip_ctx->left_handle + strip_ctx->handle_width;
|
||||
whichsel = SEQ_LEFTSEL;
|
||||
}
|
||||
else if (direction == SEQ_RIGHTHANDLE) {
|
||||
handle.xmin = strip_ctx->right_handle - strip_ctx->handle_width;
|
||||
handle.xmax = strip_ctx->right_handle;
|
||||
whichsel = SEQ_RIGHTSEL;
|
||||
}
|
||||
/* Set up co-ordinates and dimensions for either left or right handle. */
|
||||
rctf handle = {0, 0, strip_ctx.bottom, strip_ctx.top};
|
||||
if (direction == SEQ_LEFTHANDLE) {
|
||||
handle.xmin = strip_ctx.left_handle;
|
||||
handle.xmax = strip_ctx.left_handle + strip_ctx.handle_width;
|
||||
whichsel = SEQ_LEFTSEL;
|
||||
}
|
||||
else if (direction == SEQ_RIGHTHANDLE) {
|
||||
handle.xmin = strip_ctx.right_handle - strip_ctx.handle_width;
|
||||
handle.xmax = strip_ctx.right_handle;
|
||||
whichsel = SEQ_RIGHTSEL;
|
||||
}
|
||||
|
||||
if (!(seq->type & SEQ_TYPE_EFFECT) || SEQ_effect_get_num_inputs(seq->type) == 0) {
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
if (!(seq->type & SEQ_TYPE_EFFECT) || SEQ_effect_get_num_inputs(seq->type) == 0) {
|
||||
|
||||
if (seq->flag & whichsel) {
|
||||
if (strip_ctx->is_active_strip) {
|
||||
UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col);
|
||||
if (seq->flag & whichsel) {
|
||||
if (strip_ctx.is_active_strip) {
|
||||
UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col);
|
||||
}
|
||||
else {
|
||||
UI_GetThemeColor3ubv(TH_SEQ_SELECTED, col);
|
||||
/* Make handles slightly brighter than the outlines. */
|
||||
UI_GetColorPtrShade3ubv(col, col, 50);
|
||||
}
|
||||
col[3] = 255;
|
||||
}
|
||||
else {
|
||||
UI_GetThemeColor3ubv(TH_SEQ_SELECTED, col);
|
||||
/* Make handles slightly brighter than the outlines. */
|
||||
UI_GetColorPtrShade3ubv(col, col, 50);
|
||||
col[0] = col[1] = col[2] = 0;
|
||||
col[3] = 50;
|
||||
}
|
||||
col[3] = 255;
|
||||
immUniformColor4ubv(col);
|
||||
}
|
||||
else {
|
||||
immUniformColor4ub(0, 0, 0, 50);
|
||||
|
||||
timeline_ctx->quads->add_quad(handle.xmin, handle.ymin, handle.xmax, handle.ymax, col);
|
||||
}
|
||||
|
||||
immRectf(pos, handle.xmin, handle.ymin, handle.xmax, handle.ymax);
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
immUnbindProgram();
|
||||
/* Draw numbers for start and end of the strip next to its handles. */
|
||||
if (!strip_ctx.can_draw_strip_content ||
|
||||
!(((seq->flag & SELECT) && (G.moving & G_TRANSFORM_SEQ)) || (seq->flag & whichsel)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
char numstr[64];
|
||||
size_t numstr_len;
|
||||
const int fontid = BLF_default();
|
||||
BLF_set_default();
|
||||
|
||||
/* Calculate if strip is wide enough for showing the labels. */
|
||||
numstr_len = SNPRINTF_RLEN(
|
||||
numstr, "%d%d", int(strip_ctx.left_handle), int(strip_ctx.right_handle));
|
||||
float tot_width = BLF_width(fontid, numstr, numstr_len);
|
||||
|
||||
if (strip_ctx.strip_length / timeline_ctx->pixelx > 20 + tot_width) {
|
||||
col[0] = col[1] = col[2] = col[3] = 255;
|
||||
float text_margin = 1.2f * strip_ctx.handle_width;
|
||||
|
||||
float text_x = strip_ctx.left_handle;
|
||||
const float text_y = strip_ctx.bottom + 0.09f;
|
||||
if (direction == SEQ_LEFTHANDLE) {
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "%d", int(strip_ctx.left_handle));
|
||||
text_x += text_margin;
|
||||
}
|
||||
else {
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "%d", int(strip_ctx.right_handle - 1));
|
||||
text_x = strip_ctx.right_handle -
|
||||
(text_margin + timeline_ctx->pixelx * BLF_width(fontid, numstr, numstr_len));
|
||||
}
|
||||
UI_view2d_text_cache_add(timeline_ctx->v2d, text_x, text_y, numstr, numstr_len, col);
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw numbers for start and end of the strip next to its handles. */
|
||||
if (!strip_ctx->can_draw_strip_content ||
|
||||
!(((seq->flag & SELECT) && (G.moving & G_TRANSFORM_SEQ)) || (seq->flag & whichsel)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char numstr[64];
|
||||
size_t numstr_len;
|
||||
const int fontid = BLF_default();
|
||||
BLF_set_default();
|
||||
|
||||
/* Calculate if strip is wide enough for showing the labels. */
|
||||
numstr_len = SNPRINTF_RLEN(
|
||||
numstr, "%d%d", int(strip_ctx->left_handle), int(strip_ctx->right_handle));
|
||||
float tot_width = BLF_width(fontid, numstr, numstr_len);
|
||||
|
||||
if (strip_ctx->strip_length / timeline_ctx->pixelx > 20 + tot_width) {
|
||||
col[0] = col[1] = col[2] = col[3] = 255;
|
||||
float text_margin = 1.2f * strip_ctx->handle_width;
|
||||
|
||||
float text_x = strip_ctx->left_handle;
|
||||
const float text_y = strip_ctx->bottom + 0.09f;
|
||||
if (direction == SEQ_LEFTHANDLE) {
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "%d", int(strip_ctx->left_handle));
|
||||
text_x += text_margin;
|
||||
}
|
||||
else {
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "%d", int(strip_ctx->right_handle - 1));
|
||||
text_x = strip_ctx->right_handle -
|
||||
(text_margin + timeline_ctx->pixelx * BLF_width(fontid, numstr, numstr_len));
|
||||
}
|
||||
UI_view2d_text_cache_add(timeline_ctx->v2d, text_x, text_y, numstr, numstr_len, col);
|
||||
}
|
||||
timeline_ctx->quads->draw();
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
static void draw_seq_outline(TimelineDrawContext *timeline_ctx, StripDrawContext *strip_ctx)
|
||||
static void draw_seq_outline(TimelineDrawContext *timeline_ctx,
|
||||
const blender::Vector<StripDrawContext> &strips)
|
||||
{
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
for (const StripDrawContext &strip_ctx : strips) {
|
||||
Sequence *seq = strip_ctx.seq;
|
||||
|
||||
Sequence *seq = strip_ctx->seq;
|
||||
uchar col[3];
|
||||
|
||||
/* Get the color for the outline. */
|
||||
if (strip_ctx->is_active_strip && (seq->flag & SELECT)) {
|
||||
UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col);
|
||||
}
|
||||
else if (seq->flag & SELECT) {
|
||||
UI_GetThemeColor3ubv(TH_SEQ_SELECTED, col);
|
||||
}
|
||||
else {
|
||||
/* Color for unselected strips is a bit darker than the background. */
|
||||
UI_GetThemeColorShade3ubv(TH_BACK, -40, col);
|
||||
}
|
||||
|
||||
/* Outline while translating strips:
|
||||
* - Slightly lighter.
|
||||
* - Red when overlapping with other strips.
|
||||
*/
|
||||
const eSeqOverlapMode overlap_mode = SEQ_tool_settings_overlap_mode_get(timeline_ctx->scene);
|
||||
if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT) &&
|
||||
overlap_mode != SEQ_OVERLAP_OVERWRITE) {
|
||||
if (seq->flag & SEQ_OVERLAP) {
|
||||
col[0] = 255;
|
||||
col[1] = col[2] = 33;
|
||||
/* Get the color for the outline. */
|
||||
uchar col[4];
|
||||
if (strip_ctx.is_active_strip && (seq->flag & SELECT)) {
|
||||
UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col);
|
||||
}
|
||||
else if (seq->flag & SELECT) {
|
||||
UI_GetThemeColor3ubv(TH_SEQ_SELECTED, col);
|
||||
}
|
||||
else {
|
||||
UI_GetColorPtrShade3ubv(col, col, 70);
|
||||
/* Color for unselected strips is a bit darker than the background. */
|
||||
UI_GetThemeColorShade3ubv(TH_BACK, -40, col);
|
||||
}
|
||||
col[3] = 255;
|
||||
|
||||
/* Outline while translating strips:
|
||||
* - Slightly lighter.
|
||||
* - Red when overlapping with other strips.
|
||||
*/
|
||||
const eSeqOverlapMode overlap_mode = SEQ_tool_settings_overlap_mode_get(timeline_ctx->scene);
|
||||
if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT) &&
|
||||
overlap_mode != SEQ_OVERLAP_OVERWRITE) {
|
||||
if (seq->flag & SEQ_OVERLAP) {
|
||||
col[0] = 255;
|
||||
col[1] = col[2] = 33;
|
||||
}
|
||||
else {
|
||||
UI_GetColorPtrShade3ubv(col, col, 70);
|
||||
}
|
||||
}
|
||||
|
||||
/* 2px wide outline for selected strips: draw as four quads. */
|
||||
if (seq->flag & SELECT) {
|
||||
float delta_x = timeline_ctx->pixelx;
|
||||
float delta_y = timeline_ctx->pixely * 2;
|
||||
|
||||
/* Left */
|
||||
timeline_ctx->quads->add_quad(strip_ctx.left_handle - delta_x,
|
||||
strip_ctx.bottom,
|
||||
strip_ctx.left_handle + delta_x,
|
||||
strip_ctx.top,
|
||||
col);
|
||||
/* Bottom */
|
||||
timeline_ctx->quads->add_quad(strip_ctx.left_handle - delta_x,
|
||||
strip_ctx.bottom,
|
||||
strip_ctx.right_handle + delta_x,
|
||||
strip_ctx.bottom + delta_y,
|
||||
col);
|
||||
/* Right */
|
||||
timeline_ctx->quads->add_quad(strip_ctx.right_handle - delta_x,
|
||||
strip_ctx.bottom,
|
||||
strip_ctx.right_handle + delta_x,
|
||||
strip_ctx.top,
|
||||
col);
|
||||
/* Top */
|
||||
timeline_ctx->quads->add_quad(strip_ctx.left_handle - delta_x,
|
||||
strip_ctx.top - delta_y,
|
||||
strip_ctx.right_handle + delta_x,
|
||||
strip_ctx.top,
|
||||
col);
|
||||
}
|
||||
else {
|
||||
/* 1px wide outline for unselected strips. */
|
||||
timeline_ctx->quads->add_wire_quad(
|
||||
strip_ctx.left_handle, strip_ctx.bottom, strip_ctx.right_handle, strip_ctx.top, col);
|
||||
}
|
||||
}
|
||||
immUniformColor3ubv(col);
|
||||
|
||||
/* 2px wide outline for selected strips. */
|
||||
/* XXX: some platforms don't support OpenGL lines wider than 1px (see #57570),
|
||||
* draw outline as four boxes instead. */
|
||||
if (seq->flag & SELECT) {
|
||||
/* Left */
|
||||
immRectf(pos,
|
||||
strip_ctx->left_handle - timeline_ctx->pixelx,
|
||||
strip_ctx->bottom,
|
||||
strip_ctx->left_handle + timeline_ctx->pixelx,
|
||||
strip_ctx->top);
|
||||
/* Bottom */
|
||||
immRectf(pos,
|
||||
strip_ctx->left_handle - timeline_ctx->pixelx,
|
||||
strip_ctx->bottom,
|
||||
strip_ctx->right_handle + timeline_ctx->pixelx,
|
||||
strip_ctx->bottom + 2 * timeline_ctx->pixely);
|
||||
/* Right */
|
||||
immRectf(pos,
|
||||
strip_ctx->right_handle - timeline_ctx->pixelx,
|
||||
strip_ctx->bottom,
|
||||
strip_ctx->right_handle + timeline_ctx->pixelx,
|
||||
strip_ctx->top);
|
||||
/* Top */
|
||||
immRectf(pos,
|
||||
strip_ctx->left_handle - timeline_ctx->pixelx,
|
||||
strip_ctx->top - 2 * timeline_ctx->pixely,
|
||||
strip_ctx->right_handle + timeline_ctx->pixelx,
|
||||
strip_ctx->top);
|
||||
}
|
||||
else {
|
||||
/* 1px wide outline for unselected strips. */
|
||||
imm_draw_box_wire_2d(
|
||||
pos, strip_ctx->left_handle, strip_ctx->bottom, strip_ctx->right_handle, strip_ctx->top);
|
||||
}
|
||||
immUnbindProgram();
|
||||
timeline_ctx->quads->draw();
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
static const char *draw_seq_text_get_name(Sequence *seq)
|
||||
|
@ -996,7 +1005,7 @@ static void draw_seq_text_get_source(Sequence *seq, char *r_source, size_t sourc
|
|||
}
|
||||
|
||||
static size_t draw_seq_text_get_overlay_string(TimelineDrawContext *timeline_ctx,
|
||||
StripDrawContext *strip_ctx,
|
||||
const StripDrawContext *strip_ctx,
|
||||
char *r_overlay_string,
|
||||
size_t overlay_string_len)
|
||||
{
|
||||
|
@ -1036,7 +1045,8 @@ static size_t draw_seq_text_get_overlay_string(TimelineDrawContext *timeline_ctx
|
|||
}
|
||||
|
||||
/* Draw info text on a sequence strip. */
|
||||
static void draw_seq_text_overlay(TimelineDrawContext *timeline_ctx, StripDrawContext *strip_ctx)
|
||||
static void draw_seq_text_overlay(TimelineDrawContext *timeline_ctx,
|
||||
const StripDrawContext *strip_ctx)
|
||||
{
|
||||
if ((timeline_ctx->sseq->flag & SEQ_SHOW_OVERLAY) == 0) {
|
||||
return;
|
||||
|
@ -1086,7 +1096,8 @@ static void draw_seq_text_overlay(TimelineDrawContext *timeline_ctx, StripDrawCo
|
|||
timeline_ctx->v2d, &rect, overlay_string, overlay_string_len, col);
|
||||
}
|
||||
|
||||
static void draw_strip_offsets(TimelineDrawContext *timeline_ctx, StripDrawContext *strip_ctx)
|
||||
static void draw_strip_offsets(TimelineDrawContext *timeline_ctx,
|
||||
const StripDrawContext *strip_ctx)
|
||||
{
|
||||
Sequence *seq = strip_ctx->seq;
|
||||
|
||||
|
@ -1171,89 +1182,80 @@ static uchar mute_overlap_alpha_factor_get(const ListBase *channels, const Seque
|
|||
}
|
||||
}
|
||||
|
||||
static void draw_strip_color_band(TimelineDrawContext *timeline_ctx, StripDrawContext *strip_ctx)
|
||||
static void draw_strip_color_band(TimelineDrawContext *timeline_ctx,
|
||||
const blender::Vector<StripDrawContext> &strips)
|
||||
{
|
||||
Sequence *seq = strip_ctx->seq;
|
||||
|
||||
if ((timeline_ctx->sseq->flag & SEQ_SHOW_OVERLAY) == 0 || (seq->type != SEQ_TYPE_COLOR)) {
|
||||
if ((timeline_ctx->sseq->flag & SEQ_SHOW_OVERLAY) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
|
||||
uchar col[4];
|
||||
rgb_float_to_uchar(col, colvars->col);
|
||||
col[3] = mute_overlap_alpha_factor_get(timeline_ctx->channels, seq);
|
||||
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
immUniformColor4ubv(col);
|
||||
|
||||
immRectf(pos,
|
||||
strip_ctx->left_handle,
|
||||
strip_ctx->bottom,
|
||||
strip_ctx->right_handle,
|
||||
strip_ctx->strip_content_top);
|
||||
float halfpix_y = timeline_ctx->pixely * 0.5f;
|
||||
|
||||
/* 1px line to better separate the color band. */
|
||||
UI_GetColorPtrShade3ubv(col, col, -20);
|
||||
immUniformColor4ubv(col);
|
||||
for (const StripDrawContext &strip_ctx : strips) {
|
||||
Sequence *seq = strip_ctx.seq;
|
||||
if (seq->type != SEQ_TYPE_COLOR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
immBegin(GPU_PRIM_LINES, 2);
|
||||
immVertex2f(pos, strip_ctx->left_handle, strip_ctx->strip_content_top);
|
||||
immVertex2f(pos, strip_ctx->right_handle, strip_ctx->strip_content_top);
|
||||
immEnd();
|
||||
SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
|
||||
uchar col[4];
|
||||
rgb_float_to_uchar(col, colvars->col);
|
||||
col[3] = mute_overlap_alpha_factor_get(timeline_ctx->channels, seq);
|
||||
|
||||
timeline_ctx->quads->add_quad(strip_ctx.left_handle,
|
||||
strip_ctx.bottom,
|
||||
strip_ctx.right_handle,
|
||||
strip_ctx.strip_content_top,
|
||||
col);
|
||||
|
||||
/* 1px line to better separate the color band. */
|
||||
UI_GetColorPtrShade3ubv(col, col, -20);
|
||||
timeline_ctx->quads->add_quad(strip_ctx.left_handle,
|
||||
strip_ctx.strip_content_top - halfpix_y,
|
||||
strip_ctx.right_handle,
|
||||
strip_ctx.strip_content_top + halfpix_y,
|
||||
col);
|
||||
}
|
||||
timeline_ctx->quads->draw();
|
||||
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
immUnbindProgram();
|
||||
}
|
||||
|
||||
static void draw_strip_background(TimelineDrawContext *timeline_ctx, StripDrawContext *strip_ctx)
|
||||
static void draw_strip_background(TimelineDrawContext *timeline_ctx,
|
||||
const blender::Vector<StripDrawContext> &strips)
|
||||
{
|
||||
Scene *scene = timeline_ctx->scene;
|
||||
Sequence *seq = strip_ctx->seq;
|
||||
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
uchar col[4];
|
||||
color3ubv_from_seq(scene, seq, strip_ctx->show_strip_color_tag, col);
|
||||
col[3] = mute_overlap_alpha_factor_get(timeline_ctx->channels, seq);
|
||||
for (const StripDrawContext &strip_ctx : strips) {
|
||||
/* Draw main strip body. */
|
||||
uchar col[4];
|
||||
color3ubv_from_seq(scene, strip_ctx.seq, strip_ctx.show_strip_color_tag, col);
|
||||
col[3] = mute_overlap_alpha_factor_get(timeline_ctx->channels, strip_ctx.seq);
|
||||
|
||||
immUniformColor4ubv(col);
|
||||
float x1 = strip_ctx.is_single_image ? strip_ctx.left_handle : strip_ctx.content_start;
|
||||
float x2 = strip_ctx.is_single_image ? strip_ctx.right_handle : strip_ctx.content_end;
|
||||
timeline_ctx->quads->add_quad(x1, strip_ctx.bottom, x2, strip_ctx.top, col);
|
||||
|
||||
/* Draw the main strip body. */
|
||||
if (strip_ctx->is_single_image) {
|
||||
immRectf(
|
||||
pos, strip_ctx->left_handle, strip_ctx->bottom, strip_ctx->right_handle, strip_ctx->top);
|
||||
}
|
||||
else {
|
||||
immRectf(
|
||||
pos, strip_ctx->content_start, strip_ctx->bottom, strip_ctx->content_end, strip_ctx->top);
|
||||
}
|
||||
|
||||
/* Draw background for hold still regions. */
|
||||
if (strip_ctx->is_single_image) {
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
immUnbindProgram();
|
||||
return;
|
||||
}
|
||||
|
||||
UI_GetColorPtrShade3ubv(col, col, -35);
|
||||
immUniformColor4ubv(col);
|
||||
|
||||
if (SEQ_time_has_left_still_frames(scene, seq)) {
|
||||
immRectf(
|
||||
pos, strip_ctx->left_handle, strip_ctx->bottom, strip_ctx->content_start, strip_ctx->top);
|
||||
}
|
||||
if (SEQ_time_has_right_still_frames(scene, seq)) {
|
||||
immRectf(
|
||||
pos, strip_ctx->content_end, strip_ctx->bottom, strip_ctx->right_handle, strip_ctx->top);
|
||||
/* Draw backgrounds for hold still regions. */
|
||||
if (!strip_ctx.is_single_image) {
|
||||
UI_GetColorPtrShade3ubv(col, col, -35);
|
||||
if (SEQ_time_has_left_still_frames(scene, strip_ctx.seq)) {
|
||||
timeline_ctx->quads->add_quad(
|
||||
strip_ctx.left_handle, strip_ctx.bottom, strip_ctx.content_start, strip_ctx.top, col);
|
||||
}
|
||||
if (SEQ_time_has_right_still_frames(scene, strip_ctx.seq)) {
|
||||
timeline_ctx->quads->add_quad(
|
||||
strip_ctx.content_end, strip_ctx.bottom, strip_ctx.right_handle, strip_ctx.top, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
timeline_ctx->quads->draw();
|
||||
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
immUnbindProgram();
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
|
@ -1262,7 +1264,7 @@ typedef enum {
|
|||
} TransitionType;
|
||||
|
||||
static void draw_seq_transition_strip_half(TimelineDrawContext *timeline_ctx,
|
||||
StripDrawContext *strip_ctx,
|
||||
const StripDrawContext *strip_ctx,
|
||||
const TransitionType transition_type)
|
||||
{
|
||||
|
||||
|
@ -1320,7 +1322,7 @@ static void draw_seq_transition_strip_half(TimelineDrawContext *timeline_ctx,
|
|||
}
|
||||
|
||||
static void draw_seq_transition_strip(TimelineDrawContext *timeline_ctx,
|
||||
StripDrawContext *strip_ctx)
|
||||
const StripDrawContext *strip_ctx)
|
||||
{
|
||||
if (!strip_ctx->can_draw_strip_content || (timeline_ctx->sseq->flag & SEQ_SHOW_OVERLAY) == 0 ||
|
||||
!ELEM(strip_ctx->seq->type, SEQ_TYPE_CROSS, SEQ_TYPE_GAMCROSS, SEQ_TYPE_WIPE))
|
||||
|
@ -1332,7 +1334,7 @@ static void draw_seq_transition_strip(TimelineDrawContext *timeline_ctx,
|
|||
draw_seq_transition_strip_half(timeline_ctx, strip_ctx, STRIP_TRANSITION_OUT);
|
||||
}
|
||||
|
||||
static void draw_seq_locked(TimelineDrawContext *timeline_ctx, StripDrawContext *strip_ctx)
|
||||
static void draw_seq_locked(TimelineDrawContext *timeline_ctx, const StripDrawContext *strip_ctx)
|
||||
{
|
||||
if (!SEQ_transform_is_locked(timeline_ctx->channels, strip_ctx->seq)) {
|
||||
return;
|
||||
|
@ -1356,7 +1358,7 @@ static void draw_seq_locked(TimelineDrawContext *timeline_ctx, StripDrawContext
|
|||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
static void draw_seq_invalid(StripDrawContext *strip_ctx)
|
||||
static void draw_seq_invalid(const StripDrawContext *strip_ctx)
|
||||
{
|
||||
if (SEQ_sequence_has_source(strip_ctx->seq)) {
|
||||
return;
|
||||
|
@ -1400,7 +1402,8 @@ static void fcurve_batch_add_verts(GPUVertBuf *vbo,
|
|||
* - Volume for sound strips.
|
||||
* - Opacity for the other types.
|
||||
*/
|
||||
static void draw_seq_fcurve_overlay(TimelineDrawContext *timeline_ctx, StripDrawContext *strip_ctx)
|
||||
static void draw_seq_fcurve_overlay(TimelineDrawContext *timeline_ctx,
|
||||
const StripDrawContext *strip_ctx)
|
||||
{
|
||||
if (!strip_ctx->can_draw_strip_content || (timeline_ctx->sseq->flag & SEQ_SHOW_OVERLAY) == 0 ||
|
||||
(timeline_ctx->sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_FCURVES) == 0)
|
||||
|
@ -1493,7 +1496,8 @@ static void draw_seq_fcurve_overlay(TimelineDrawContext *timeline_ctx, StripDraw
|
|||
}
|
||||
|
||||
/* When active strip is a Multi-cam strip, highlight its source channel. */
|
||||
static void draw_multicam_highlight(TimelineDrawContext *timeline_ctx, StripDrawContext *strip_ctx)
|
||||
static void draw_multicam_highlight(TimelineDrawContext *timeline_ctx,
|
||||
const StripDrawContext *strip_ctx)
|
||||
{
|
||||
Sequence *act_seq = SEQ_select_active_get(timeline_ctx->scene);
|
||||
|
||||
|
@ -1524,7 +1528,7 @@ static void draw_multicam_highlight(TimelineDrawContext *timeline_ctx, StripDraw
|
|||
|
||||
/* Highlight strip if it is input of selected active strip. */
|
||||
static void draw_effect_inputs_highlight(TimelineDrawContext *timeline_ctx,
|
||||
StripDrawContext *strip_ctx)
|
||||
const StripDrawContext *strip_ctx)
|
||||
{
|
||||
Sequence *act_seq = SEQ_select_active_get(timeline_ctx->scene);
|
||||
|
||||
|
@ -1545,7 +1549,7 @@ static void draw_effect_inputs_highlight(TimelineDrawContext *timeline_ctx,
|
|||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
static void draw_seq_solo_highlight(StripDrawContext *strip_ctx)
|
||||
static void draw_seq_solo_highlight(const StripDrawContext *strip_ctx)
|
||||
{
|
||||
if (ED_sequencer_special_preview_get() == nullptr ||
|
||||
ED_sequencer_special_preview_get() != strip_ctx->seq)
|
||||
|
@ -1563,35 +1567,6 @@ static void draw_seq_solo_highlight(StripDrawContext *strip_ctx)
|
|||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
/* Draw visible strips. Bounds check are already made. */
|
||||
static void draw_seq_strip(TimelineDrawContext *timeline_ctx, StripDrawContext *strip_ctx)
|
||||
{
|
||||
draw_strip_background(timeline_ctx, strip_ctx);
|
||||
draw_strip_color_band(timeline_ctx, strip_ctx);
|
||||
draw_strip_offsets(timeline_ctx, strip_ctx);
|
||||
draw_seq_transition_strip(timeline_ctx, strip_ctx);
|
||||
drawmeta_contents(timeline_ctx, strip_ctx);
|
||||
draw_seq_strip_thumbnail(timeline_ctx->v2d,
|
||||
timeline_ctx->C,
|
||||
timeline_ctx->scene,
|
||||
strip_ctx->seq,
|
||||
strip_ctx->bottom,
|
||||
strip_ctx->strip_content_top,
|
||||
timeline_ctx->pixelx,
|
||||
timeline_ctx->pixely);
|
||||
draw_seq_fcurve_overlay(timeline_ctx, strip_ctx);
|
||||
draw_seq_waveform_overlay(timeline_ctx, strip_ctx);
|
||||
draw_seq_locked(timeline_ctx, strip_ctx);
|
||||
draw_seq_invalid(strip_ctx); /* Draw Red line on the top of invalid strip (Missing media). */
|
||||
draw_effect_inputs_highlight(timeline_ctx, strip_ctx);
|
||||
draw_multicam_highlight(timeline_ctx, strip_ctx);
|
||||
draw_seq_solo_highlight(strip_ctx);
|
||||
draw_seq_handle(timeline_ctx, strip_ctx, SEQ_LEFTHANDLE);
|
||||
draw_seq_handle(timeline_ctx, strip_ctx, SEQ_RIGHTHANDLE);
|
||||
draw_seq_outline(timeline_ctx, strip_ctx);
|
||||
draw_seq_text_overlay(timeline_ctx, strip_ctx);
|
||||
}
|
||||
|
||||
/* Force redraw, when prefetching and using cache view. */
|
||||
static void seq_prefetch_wm_notify(const bContext *C, Scene *scene)
|
||||
{
|
||||
|
@ -1629,6 +1604,7 @@ static blender::Vector<Sequence *> visible_strips_ordered_get(TimelineDrawContex
|
|||
Sequence *act_seq = SEQ_select_active_get(timeline_ctx->scene);
|
||||
blender::Vector<Sequence *> strips = sequencer_visible_strips_get(timeline_ctx->C);
|
||||
blender::Vector<Sequence *> strips_ordered;
|
||||
strips_ordered.reserve(strips.size());
|
||||
const bool act_seq_is_selected = act_seq != nullptr && (act_seq->flag & SELECT) != 0;
|
||||
|
||||
if (act_seq_is_selected) {
|
||||
|
@ -1658,9 +1634,45 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx)
|
|||
return;
|
||||
}
|
||||
|
||||
for (Sequence *seq : visible_strips_ordered_get(timeline_ctx)) {
|
||||
StripDrawContext strip_ctx = strip_draw_context_get(timeline_ctx, seq);
|
||||
draw_seq_strip(timeline_ctx, &strip_ctx);
|
||||
blender::Vector<Sequence *> strips = visible_strips_ordered_get(timeline_ctx);
|
||||
if (strips.is_empty()) {
|
||||
return;
|
||||
}
|
||||
blender::Vector<StripDrawContext> strip_contexts(strips.size());
|
||||
for (const int i : strips.index_range()) {
|
||||
strip_contexts[i] = strip_draw_context_get(timeline_ctx, strips[i]);
|
||||
}
|
||||
|
||||
draw_strip_background(timeline_ctx, strip_contexts);
|
||||
draw_strip_color_band(timeline_ctx, strip_contexts);
|
||||
for (const StripDrawContext &strip_ctx : strip_contexts) {
|
||||
// continue;
|
||||
draw_strip_offsets(timeline_ctx, &strip_ctx);
|
||||
draw_seq_transition_strip(timeline_ctx, &strip_ctx);
|
||||
drawmeta_contents(timeline_ctx, &strip_ctx);
|
||||
draw_seq_strip_thumbnail(timeline_ctx->v2d,
|
||||
timeline_ctx->C,
|
||||
timeline_ctx->scene,
|
||||
strip_ctx.seq,
|
||||
strip_ctx.bottom,
|
||||
strip_ctx.strip_content_top,
|
||||
timeline_ctx->pixelx,
|
||||
timeline_ctx->pixely);
|
||||
draw_seq_fcurve_overlay(timeline_ctx, &strip_ctx);
|
||||
draw_seq_waveform_overlay(timeline_ctx, &strip_ctx);
|
||||
draw_seq_locked(timeline_ctx, &strip_ctx);
|
||||
draw_seq_invalid(&strip_ctx); /* Draw Red line on the top of invalid strip (Missing media). */
|
||||
draw_effect_inputs_highlight(timeline_ctx, &strip_ctx);
|
||||
draw_multicam_highlight(timeline_ctx, &strip_ctx);
|
||||
draw_seq_solo_highlight(&strip_ctx);
|
||||
}
|
||||
|
||||
draw_seq_handle(timeline_ctx, strip_contexts, SEQ_LEFTHANDLE);
|
||||
draw_seq_handle(timeline_ctx, strip_contexts, SEQ_RIGHTHANDLE);
|
||||
draw_seq_outline(timeline_ctx, strip_contexts);
|
||||
for (const StripDrawContext &strip_ctx : strip_contexts) {
|
||||
// continue;
|
||||
draw_seq_text_overlay(timeline_ctx, &strip_ctx);
|
||||
}
|
||||
|
||||
UI_view2d_text_cache_draw(timeline_ctx->region);
|
||||
|
@ -2045,7 +2057,10 @@ static void draw_timeline_post_view_callbacks(TimelineDrawContext *ctx)
|
|||
|
||||
void draw_timeline_seq(const bContext *C, ARegion *region)
|
||||
{
|
||||
SeqQuadsBatch quads_batch;
|
||||
TimelineDrawContext ctx = timeline_draw_context_get(C);
|
||||
ctx.quads = &quads_batch;
|
||||
|
||||
draw_timeline_pre_view_callbacks(&ctx);
|
||||
UI_ThemeClearColor(TH_BACK);
|
||||
draw_seq_timeline_channels(&ctx);
|
||||
|
@ -2053,7 +2068,7 @@ void draw_timeline_seq(const bContext *C, ARegion *region)
|
|||
draw_timeline_backdrop(&ctx);
|
||||
draw_timeline_sfra_efra(&ctx);
|
||||
draw_seq_strips(&ctx);
|
||||
sequencer_draw_retiming(C);
|
||||
sequencer_draw_retiming(C, &quads_batch);
|
||||
draw_timeline_markers(&ctx);
|
||||
UI_view2d_view_ortho(ctx.v2d);
|
||||
ANIM_draw_previewrange(C, ctx.v2d, 1);
|
||||
|
|
Do you need to clear the flag, because you are reusing the buffer? I would expect that there is some function to handle this.
Here it seems to work when I remove call to
GPU_vertbuf_attr_get_raw_data()
. Would have to look how exactly this flag is used.