Fix: VSE strip shape is not rounded when dragging file into timeline area

Strips still have sharp corners when you're dragging them from file browser and
switch to rounded when dropped. Fix by using the same drawing code (and shader)
as regular timeline drawing path.

Pull Request: https://projects.blender.org/blender/blender/pulls/123013
This commit is contained in:
Aras Pranckevicius 2024-06-11 11:55:49 +02:00 committed by Aras Pranckevicius
parent 12ff1ffe5b
commit 57f1d11163
7 changed files with 288 additions and 212 deletions

@ -39,6 +39,7 @@ set(SRC
sequencer_retiming_draw.cc
sequencer_scopes.cc
sequencer_select.cc
sequencer_strips_batch.cc
sequencer_thumbnails.cc
sequencer_timeline_draw.cc
sequencer_view.cc
@ -47,6 +48,7 @@ set(SRC
sequencer_intern.hh
sequencer_quads_batch.hh
sequencer_scopes.hh
sequencer_strips_batch.hh
)
set(LIB

@ -28,7 +28,6 @@
#include "UI_resources.hh"
#include "UI_view2d.hh"
#include "GPU_immediate.hh"
#include "GPU_matrix.hh"
#include "ED_screen.hh"
@ -49,6 +48,7 @@
/* Own include. */
#include "sequencer_intern.hh"
#include "sequencer_strips_batch.hh"
struct SeqDropCoords {
float start_frame, channel;
@ -362,6 +362,7 @@ static void get_drag_path(const bContext *C, wmDrag *drag, char r_path[FILE_MAX]
static void draw_seq_in_view(bContext *C, wmWindow * /*win*/, wmDrag *drag, const int xy[2])
{
using namespace blender::ed::seq;
SeqDropCoords *coords = &g_drop_coords;
if (!coords->in_use) {
return;
@ -389,20 +390,19 @@ static void draw_seq_in_view(bContext *C, wmWindow * /*win*/, wmDrag *drag, cons
}
/* Init GPU drawing. */
GPU_line_width(2.0f);
GPU_blend(GPU_BLEND_ALPHA);
GPU_line_smooth(true);
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_PREMULT);
/* Draw strips. The code here is taken from sequencer_draw. */
float x1 = coords->start_frame;
float x2 = coords->start_frame + floorf(strip_len);
float strip_color[3];
uchar strip_color[4];
strip_color[3] = 255;
uchar text_color[4] = {255, 255, 255, 255};
float pixelx = BLI_rctf_size_x(&region->v2d.cur) / BLI_rcti_size_x(&region->v2d.mask);
float pixely = BLI_rctf_size_y(&region->v2d.cur) / BLI_rcti_size_y(&region->v2d.mask);
StripsDrawBatch batch(pixelx, pixely);
for (int i = 0; i < coords->channel_len; i++) {
float y1 = floorf(coords->channel) + i + SEQ_STRIP_OFSBOTTOM;
float y2 = floorf(coords->channel) + i + SEQ_STRIP_OFSTOP;
@ -412,42 +412,36 @@ static void draw_seq_in_view(bContext *C, wmWindow * /*win*/, wmDrag *drag, cons
* One for video and the other for audio.
* The audio channel is added first.
*/
UI_GetThemeColor3fv(TH_SEQ_AUDIO, strip_color);
UI_GetThemeColor3ubv(TH_SEQ_AUDIO, strip_color);
}
else {
UI_GetThemeColor3fv(coords->type, strip_color);
UI_GetThemeColor3ubv(coords->type, strip_color);
}
immUniformColor3fvAlpha(strip_color, 0.8f);
immRectf(pos, x1, y1, x2, y2);
SeqStripDrawData &data = batch.add_strip(x1, x2, y2, y1, y2, x1, x2, 0, true);
data.flags |= GPU_SEQ_FLAG_BACKGROUND | GPU_SEQ_FLAG_BORDER | GPU_SEQ_FLAG_SELECTED;
data.col_background = color_pack(strip_color);
if (coords->is_intersecting) {
strip_color[0] = 1.0f;
strip_color[1] = strip_color[2] = 0.3f;
strip_color[0] = 255;
strip_color[1] = strip_color[2] = 33;
}
else {
if (coords->channel_len - 1 == i) {
text_color[0] = text_color[1] = text_color[2] = 255;
UI_GetThemeColor3fv(TH_SEQ_ACTIVE, strip_color);
UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, strip_color);
data.flags |= GPU_SEQ_FLAG_ACTIVE;
}
else {
text_color[0] = text_color[1] = text_color[2] = 10;
UI_GetThemeColor3fv(TH_SEQ_SELECTED, strip_color);
UI_GetThemeColor3ubv(TH_SEQ_SELECTED, strip_color);
}
}
strip_color[3] = 204;
data.col_outline = color_pack(strip_color);
/* Draw a 2 pixel border around the strip. */
immUniformColor3fvAlpha(strip_color, 0.8f);
/* Left */
immRectf(pos, x1 - pixelx, y1, x1 + pixelx, y2);
/* Bottom */
immRectf(pos, x1 - pixelx, y1, x2 + pixelx, y1 + 2 * pixely);
/* Right */
immRectf(pos, x2 - pixelx, y1, x2 + pixelx, y2);
/* Top */
immRectf(pos, x1 - pixelx, y2 - 2 * pixely, x2 + pixelx, y2);
float handle_size = 8.0f; /* SEQ_HANDLE_SIZE */
const bool use_thin_handle = (U.sequencer_editor_flag & USER_SEQ_ED_SIMPLE_TWEAKING) != 0;
const float handle_size = use_thin_handle ? 5.0f : 8.0f;
/* Calculate height needed for drawing text on strip. */
float text_margin_y = y2 - min_ff(0.40f, 20 * UI_SCALE_FAC * pixely);
@ -502,13 +496,12 @@ static void draw_seq_in_view(bContext *C, wmWindow * /*win*/, wmDrag *drag, cons
UI_view2d_text_cache_add_rectf(
&region->v2d, &rect, text_display, strlen(text_display), text_color);
}
batch.flush_batch();
/* Clean after drawing up. */
UI_Theme_Restore(&theme_state);
GPU_matrix_pop();
immUnbindProgram();
GPU_blend(GPU_BLEND_NONE);
GPU_line_smooth(false);
UI_view2d_text_cache_draw(region);
}

@ -0,0 +1,122 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spseq
*/
#include "sequencer_strips_batch.hh"
#include "GPU_batch.hh"
#include "GPU_batch_presets.hh"
#include "GPU_shader_shared.hh"
#include "GPU_uniform_buffer.hh"
#include "UI_resources.hh"
namespace blender::ed::seq {
uint color_pack(const uchar rgba[4])
{
return rgba[0] | (rgba[1] << 8u) | (rgba[2] << 16u) | (rgba[3] << 24u);
}
float calc_strip_round_radius(float pixely)
{
float height_pixels = 1.0f / pixely;
if (height_pixels < 16.0f) {
return 0.0f;
}
if (height_pixels < 64.0f) {
return 4.0f;
}
if (height_pixels < 128.0f) {
return 6.0f;
}
return 8.0f;
}
StripsDrawBatch::StripsDrawBatch(float pixelx, float pixely) : strips_(GPU_SEQ_STRIP_DRAW_DATA_LEN)
{
context_.pixelx = pixelx;
context_.pixely = pixely;
context_.inv_pixelx = 1.0f / pixelx;
context_.inv_pixely = 1.0f / pixely;
context_.round_radius = calc_strip_round_radius(pixely);
uchar col[4];
UI_GetThemeColor3ubv(TH_BACK, col);
col[3] = 255;
context_.col_back = color_pack(col);
shader_ = GPU_shader_get_builtin_shader(GPU_SHADER_SEQUENCER_STRIPS);
binding_strips_ = GPU_shader_get_ubo_binding(shader_, "strip_data");
binding_context_ = GPU_shader_get_ubo_binding(shader_, "context_data");
ubo_context_ = GPU_uniformbuf_create_ex(sizeof(SeqContextDrawData), &context_, __func__);
ubo_strips_ = GPU_uniformbuf_create(sizeof(SeqStripDrawData) * GPU_SEQ_STRIP_DRAW_DATA_LEN);
batch_ = GPU_batch_preset_quad();
}
StripsDrawBatch::~StripsDrawBatch()
{
flush_batch();
GPU_uniformbuf_unbind(ubo_strips_);
GPU_uniformbuf_free(ubo_strips_);
GPU_uniformbuf_unbind(ubo_context_);
GPU_uniformbuf_free(ubo_context_);
}
SeqStripDrawData &StripsDrawBatch::add_strip(float content_start,
float content_end,
float top,
float bottom,
float content_top,
float left_handle,
float right_handle,
float handle_width,
bool single_image)
{
if (strips_count_ == GPU_SEQ_STRIP_DRAW_DATA_LEN) {
flush_batch();
}
SeqStripDrawData &res = strips_[strips_count_];
strips_count_++;
memset(&res, 0, sizeof(res));
res.content_start = content_start;
res.content_end = content_end;
res.top = top;
res.bottom = bottom;
res.strip_content_top = content_top;
res.left_handle = left_handle;
res.right_handle = right_handle;
res.handle_width = handle_width;
if (single_image) {
res.flags |= GPU_SEQ_FLAG_SINGLE_IMAGE;
}
return res;
}
void StripsDrawBatch::flush_batch()
{
if (strips_count_ == 0) {
return;
}
GPU_uniformbuf_update(ubo_strips_, strips_.data());
GPU_shader_bind(shader_);
GPU_uniformbuf_bind(ubo_strips_, binding_strips_);
GPU_uniformbuf_bind(ubo_context_, binding_context_);
GPU_batch_set_shader(batch_, shader_);
GPU_batch_draw_instance_range(batch_, 0, strips_count_);
strips_count_ = 0;
}
} // namespace blender::ed::seq

@ -0,0 +1,54 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spseq
*/
#pragma once
#include "BLI_array.hh"
#include "GPU_shader_shared.hh"
struct GPUShader;
struct GPUUniformBuf;
namespace blender::gpu {
class Batch;
}
namespace blender::ed::seq {
class StripsDrawBatch {
SeqContextDrawData context_;
Array<SeqStripDrawData> strips_;
GPUUniformBuf *ubo_context_ = nullptr;
GPUUniformBuf *ubo_strips_ = nullptr;
GPUShader *shader_ = nullptr;
gpu::Batch *batch_ = nullptr;
int binding_context_ = 0;
int binding_strips_ = 0;
int strips_count_ = 0;
public:
StripsDrawBatch(float pixelx, float pixely);
~StripsDrawBatch();
SeqStripDrawData &add_strip(float content_start,
float content_end,
float top,
float bottom,
float content_top,
float left_handle,
float right_handle,
float handle_width,
bool single_image);
void flush_batch();
};
uint color_pack(const uchar rgba[4]);
float calc_strip_round_radius(float pixely);
} // namespace blender::ed::seq

@ -27,11 +27,7 @@
#include "BKE_global.hh"
#include "BKE_sound.h"
#include "GPU_batch.hh"
#include "GPU_batch_presets.hh"
#include "GPU_immediate.hh"
#include "GPU_shader_shared.hh"
#include "GPU_uniform_buffer.hh"
#include "GPU_viewport.hh"
#include "ED_anim_api.hh"
@ -68,8 +64,10 @@
/* Own include. */
#include "sequencer_intern.hh"
#include "sequencer_quads_batch.hh"
#include "sequencer_strips_batch.hh"
using namespace blender;
using namespace blender::ed::seq;
#define MUTE_ALPHA 120
@ -1276,115 +1274,8 @@ static void visible_strips_ordered_get(TimelineDrawContext *timeline_ctx,
}
}
static uint color_pack(const uchar rgba[4])
{
return rgba[0] | (rgba[1] << 8u) | (rgba[2] << 16u) | (rgba[3] << 24u);
}
static float calc_strip_round_radius(float pixely)
{
float height_pixels = 1.0f / pixely;
if (height_pixels < 16.0f) {
return 0.0f;
}
if (height_pixels < 64.0f) {
return 4.0f;
}
if (height_pixels < 128.0f) {
return 6.0f;
}
return 8.0f;
}
class SeqStripsBatch {
SeqContextDrawData context_;
Array<SeqStripDrawData> strips_;
GPUUniformBuf *ubo_context_ = nullptr;
GPUUniformBuf *ubo_strips_ = nullptr;
GPUShader *shader_ = nullptr;
gpu::Batch *batch_ = nullptr;
int binding_context_ = 0;
int binding_strips_ = 0;
int strips_count_ = 0;
public:
SeqStripsBatch(float pixelx, float pixely) : strips_(GPU_SEQ_STRIP_DRAW_DATA_LEN)
{
context_.pixelx = pixelx;
context_.pixely = pixely;
context_.inv_pixelx = 1.0f / pixelx;
context_.inv_pixely = 1.0f / pixely;
context_.round_radius = calc_strip_round_radius(pixely);
uchar col[4];
UI_GetThemeColor3ubv(TH_BACK, col);
col[3] = 255;
context_.col_back = color_pack(col);
shader_ = GPU_shader_get_builtin_shader(GPU_SHADER_SEQUENCER_STRIPS);
binding_strips_ = GPU_shader_get_ubo_binding(shader_, "strip_data");
binding_context_ = GPU_shader_get_ubo_binding(shader_, "context_data");
ubo_context_ = GPU_uniformbuf_create_ex(sizeof(SeqContextDrawData), &context_, __func__);
ubo_strips_ = GPU_uniformbuf_create(sizeof(SeqStripDrawData) * GPU_SEQ_STRIP_DRAW_DATA_LEN);
batch_ = GPU_batch_preset_quad();
}
~SeqStripsBatch()
{
flush_batch();
GPU_uniformbuf_unbind(ubo_strips_);
GPU_uniformbuf_free(ubo_strips_);
GPU_uniformbuf_unbind(ubo_context_);
GPU_uniformbuf_free(ubo_context_);
}
SeqStripDrawData &add_strip(const StripDrawContext &strip)
{
if (strips_count_ == GPU_SEQ_STRIP_DRAW_DATA_LEN) {
flush_batch();
}
SeqStripDrawData &res = strips_[strips_count_];
strips_count_++;
memset(&res, 0, sizeof(res));
res.content_start = strip.content_start;
res.content_end = strip.content_end;
res.top = strip.top;
res.bottom = strip.bottom;
res.strip_content_top = strip.strip_content_top;
res.left_handle = strip.left_handle;
res.right_handle = strip.right_handle;
res.handle_width = strip.handle_width;
if (strip.is_single_image) {
res.flags |= GPU_SEQ_FLAG_SINGLE_IMAGE;
}
return res;
}
void flush_batch()
{
if (strips_count_ == 0) {
return;
}
GPU_uniformbuf_update(ubo_strips_, strips_.data());
GPU_shader_bind(shader_);
GPU_uniformbuf_bind(ubo_strips_, binding_strips_);
GPU_uniformbuf_bind(ubo_context_, binding_context_);
GPU_batch_set_shader(batch_, shader_);
GPU_batch_draw_instance_range(batch_, 0, strips_count_);
strips_count_ = 0;
}
};
static void draw_strips_background(TimelineDrawContext *timeline_ctx,
SeqStripsBatch &strips_batch,
StripsDrawBatch &strips_batch,
const Vector<StripDrawContext> &strips)
{
GPU_blend(GPU_BLEND_ALPHA_PREMULT);
@ -1392,12 +1283,19 @@ static void draw_strips_background(TimelineDrawContext *timeline_ctx,
const bool show_overlay = (timeline_ctx->sseq->flag & SEQ_SHOW_OVERLAY) != 0;
const Scene *scene = timeline_ctx->scene;
for (const StripDrawContext &strip : strips) {
SeqStripDrawData &data = strips_batch.add_strip(strip);
data.flags |= GPU_SEQ_FLAG_BACKGROUND_PART;
SeqStripDrawData &data = strips_batch.add_strip(strip.content_start,
strip.content_end,
strip.top,
strip.bottom,
strip.strip_content_top,
strip.left_handle,
strip.right_handle,
strip.handle_width,
strip.is_single_image);
/* Background color. */
uchar col[4];
data.flags |= GPU_SEQ_FLAG_BACKGROUND;
color3ubv_from_seq(scene, strip.seq, strip.show_strip_color_tag, col);
col[3] = mute_alpha_factor_get(timeline_ctx->channels, strip.seq);
/* Muted strips: turn almost gray. */
@ -1452,7 +1350,7 @@ static void draw_strips_background(TimelineDrawContext *timeline_ctx,
}
static void draw_strips_foreground(TimelineDrawContext *timeline_ctx,
SeqStripsBatch &strips_batch,
StripsDrawBatch &strips_batch,
const Vector<StripDrawContext> &strips)
{
GPU_blend(GPU_BLEND_ALPHA_PREMULT);
@ -1463,7 +1361,16 @@ static void draw_strips_foreground(TimelineDrawContext *timeline_ctx,
uchar col[4];
for (const StripDrawContext &strip : strips) {
SeqStripDrawData &data = strips_batch.add_strip(strip);
SeqStripDrawData &data = strips_batch.add_strip(strip.content_start,
strip.content_end,
strip.top,
strip.bottom,
strip.strip_content_top,
strip.left_handle,
strip.right_handle,
strip.handle_width,
strip.is_single_image);
data.flags |= GPU_SEQ_FLAG_BORDER;
/* Missing media state. */
if (strip.missing_data_block || strip.missing_media) {
@ -1562,7 +1469,7 @@ static void draw_strips_foreground(TimelineDrawContext *timeline_ctx,
}
static void draw_seq_strips(TimelineDrawContext *timeline_ctx,
SeqStripsBatch &strips_batch,
StripsDrawBatch &strips_batch,
const Vector<StripDrawContext> &strips)
{
if (strips.is_empty()) {
@ -1624,7 +1531,7 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx,
GPU_blend(GPU_BLEND_NONE);
}
static void draw_seq_strips(TimelineDrawContext *timeline_ctx, SeqStripsBatch &strips_batch)
static void draw_seq_strips(TimelineDrawContext *timeline_ctx, StripsDrawBatch &strips_batch)
{
if (timeline_ctx->ed == nullptr) {
return;
@ -1982,7 +1889,7 @@ void draw_timeline_seq(const bContext *C, ARegion *region)
{
SeqQuadsBatch quads_batch;
TimelineDrawContext ctx = timeline_draw_context_get(C, &quads_batch);
SeqStripsBatch strips_batch(ctx.pixelx, ctx.pixely);
StripsDrawBatch strips_batch(ctx.pixelx, ctx.pixely);
draw_timeline_pre_view_callbacks(&ctx);
UI_ThemeClearColor(TH_BACK);

@ -93,7 +93,7 @@ BLI_STATIC_ASSERT_ALIGN(MultiIconCallData, 16)
#define GPU_SEQ_STRIP_DRAW_DATA_LEN 256
enum eGPUSeqFlags : uint32_t {
GPU_SEQ_FLAG_BACKGROUND_PART = (1u << 0u),
GPU_SEQ_FLAG_BACKGROUND = (1u << 0u),
GPU_SEQ_FLAG_SINGLE_IMAGE = (1u << 1u),
GPU_SEQ_FLAG_COLOR_BAND = (1u << 2u),
GPU_SEQ_FLAG_TRANSITION = (1u << 3u),
@ -104,6 +104,7 @@ enum eGPUSeqFlags : uint32_t {
GPU_SEQ_FLAG_ACTIVE = (1u << 8u),
GPU_SEQ_FLAG_HIGHLIGHT = (1u << 9u),
GPU_SEQ_FLAG_HANDLES = (1u << 10u),
GPU_SEQ_FLAG_BORDER = (1u << 11u),
};
/* VSE per-strip data for timeline rendering. */

@ -61,10 +61,8 @@ void main()
vec4 col = vec4(0.0);
bool back_part = (strip.flags & GPU_SEQ_FLAG_BACKGROUND_PART) != 0;
if (back_part) {
/* Background. */
if ((strip.flags & GPU_SEQ_FLAG_BACKGROUND) != 0) {
col = unpackUnorm4x8(strip.col_background);
/* Darker background for multi-image strip hold still regions. */
if ((strip.flags & GPU_SEQ_FLAG_SINGLE_IMAGE) == 0) {
@ -72,80 +70,79 @@ void main()
col.rgb = color_shade(col.rgb, -35.0);
}
}
/* Color band. */
if ((strip.flags & GPU_SEQ_FLAG_COLOR_BAND) != 0) {
if (co.y < strip.strip_content_top) {
col.rgb = unpackUnorm4x8(strip.col_color_band).rgb;
/* Darker line to better separate the color band. */
if (co.y > strip.strip_content_top - context_data.pixely) {
col.rgb = color_shade(col.rgb, -20.0);
}
}
}
/* Transition. */
if ((strip.flags & GPU_SEQ_FLAG_TRANSITION) != 0) {
if (co.x >= strip.content_start && co.x <= strip.content_end &&
co.y < strip.strip_content_top)
{
float diag_y = strip.strip_content_top - (strip.strip_content_top - strip.bottom) *
(co.x - strip.content_start) /
(strip.content_end - strip.content_start);
uint transition_color = co.y <= diag_y ? strip.col_transition_in :
strip.col_transition_out;
col.rgb = unpackUnorm4x8(transition_color).rgb;
}
}
col.rgb *= col.a; /* Premultiply alpha. */
}
else {
/* Missing media. */
if ((strip.flags & GPU_SEQ_FLAG_MISSING_TITLE) != 0) {
if (co.y > strip.strip_content_top) {
col = blend_color(col, vec4(112.0 / 255.0, 0.0, 0.0, 230.0 / 255.0));
}
}
if ((strip.flags & GPU_SEQ_FLAG_MISSING_CONTENT) != 0) {
if (co.y <= strip.strip_content_top) {
col = blend_color(col, vec4(64.0 / 255.0, 0.0, 0.0, 230.0 / 255.0));
}
}
/* Locked. */
if ((strip.flags & GPU_SEQ_FLAG_LOCKED) != 0) {
if (co.y <= strip.strip_content_top) {
float phase = mod(gl_FragCoord.x + gl_FragCoord.y, 12.0);
if (phase >= 8.0) {
col = blend_color(col, vec4(0.0, 0.0, 0.0, 0.25));
}
/* Color band. */
if ((strip.flags & GPU_SEQ_FLAG_COLOR_BAND) != 0) {
if (co.y < strip.strip_content_top) {
col.rgb = unpackUnorm4x8(strip.col_color_band).rgb;
/* Darker line to better separate the color band. */
if (co.y > strip.strip_content_top - context_data.pixely) {
col.rgb = color_shade(col.rgb, -20.0);
}
}
}
/* Highlight. */
if ((strip.flags & GPU_SEQ_FLAG_HIGHLIGHT) != 0) {
col = blend_color(col, vec4(1.0, 1.0, 1.0, 48.0 / 255.0));
/* Transition. */
if ((strip.flags & GPU_SEQ_FLAG_TRANSITION) != 0) {
if (co.x >= strip.content_start && co.x <= strip.content_end && co.y < strip.strip_content_top)
{
float diag_y = strip.strip_content_top - (strip.strip_content_top - strip.bottom) *
(co.x - strip.content_start) /
(strip.content_end - strip.content_start);
uint transition_color = co.y <= diag_y ? strip.col_transition_in : strip.col_transition_out;
col.rgb = unpackUnorm4x8(transition_color).rgb;
}
}
/* Handles. */
if ((strip.flags & GPU_SEQ_FLAG_HANDLES) != 0) {
if (co.x >= strip.left_handle && co.x < strip.left_handle + strip.handle_width) {
col = blend_color(col, unpackUnorm4x8(strip.col_handle_left));
}
if (co.x > strip.right_handle - strip.handle_width && co.x <= strip.right_handle) {
col = blend_color(col, unpackUnorm4x8(strip.col_handle_right));
/* Previous parts were all assigning color (not blending it),
* make sure from now on alpha is premultiplied. */
col.rgb *= col.a;
/* Missing media. */
if ((strip.flags & GPU_SEQ_FLAG_MISSING_TITLE) != 0) {
if (co.y > strip.strip_content_top) {
col = blend_color(col, vec4(112.0 / 255.0, 0.0, 0.0, 230.0 / 255.0));
}
}
if ((strip.flags & GPU_SEQ_FLAG_MISSING_CONTENT) != 0) {
if (co.y <= strip.strip_content_top) {
col = blend_color(col, vec4(64.0 / 255.0, 0.0, 0.0, 230.0 / 255.0));
}
}
/* Locked. */
if ((strip.flags & GPU_SEQ_FLAG_LOCKED) != 0) {
if (co.y <= strip.strip_content_top) {
float phase = mod(gl_FragCoord.x + gl_FragCoord.y, 12.0);
if (phase >= 8.0) {
col = blend_color(col, vec4(0.0, 0.0, 0.0, 0.25));
}
}
}
/* Highlight. */
if ((strip.flags & GPU_SEQ_FLAG_HIGHLIGHT) != 0) {
col = blend_color(col, vec4(1.0, 1.0, 1.0, 48.0 / 255.0));
}
/* Handles. */
if ((strip.flags & GPU_SEQ_FLAG_HANDLES) != 0) {
if (co.x >= strip.left_handle && co.x < strip.left_handle + strip.handle_width) {
col = blend_color(col, unpackUnorm4x8(strip.col_handle_left));
}
if (co.x > strip.right_handle - strip.handle_width && co.x <= strip.right_handle) {
col = blend_color(col, unpackUnorm4x8(strip.col_handle_right));
}
}
/* Outside of strip rounded rectangle? */
if (sdf > 0.0) {
col = vec4(0.0);
}
/* Outline. */
if (!back_part) {
/* Outline / border. */
if ((strip.flags & GPU_SEQ_FLAG_BORDER) != 0) {
bool selected = (strip.flags & GPU_SEQ_FLAG_SELECTED) != 0;
vec4 col_outline = unpackUnorm4x8(strip.col_outline);
if (selected) {