VSE: Timeline strip visual design updates

Design updates as per #118288:
- Tweak text labels (colors, drop shadows)
- Strip border colors, inset outlines
- Muted strips are mostly gray, and their thumbnails are faded
- Overlapping strips are not semitransparent anymore
- Locked stripes only in content area
- Missing data blocks
- Updates to meta strips w/ missing data blocks

Pull Request: https://projects.blender.org/blender/blender/pulls/118581
This commit is contained in:
Aras Pranckevicius
2024-04-24 12:37:38 +02:00
committed by Aras Pranckevicius
parent 848571ff01
commit c64050ecd2
12 changed files with 285 additions and 134 deletions

View File

@@ -674,7 +674,7 @@ const bTheme U_theme_default = {
.meta = RGBA(0x5b4d91ff),
.text_strip = RGBA(0x824c8fff),
.color_strip = RGBA(0x8f8f8fff),
.active_strip = RGBA(0xd9d9d9ff),
.active_strip = RGBA(0xffffffff),
.selected_strip = RGBA(0xff8f0dff),
.gp_vertex_size = 3,
.gp_vertex_select = RGBA(0xff8500ff),

View File

@@ -823,7 +823,7 @@
meta_strip="#5b4d91"
mask_strip="#8f5656"
text_strip="#824c8f"
active_strip="#d9d9d9"
active_strip="#ffffff"
selected_strip="#ff6a00"
frame_current="#5680c2"
time_scrub_background="#292929e6"

View File

@@ -113,6 +113,14 @@ void UI_icon_draw_ex(float x,
bool mono_border,
const IconTextOverlay *text_overlay);
/**
* Draw an monochrome icon into a given coordinate rectangle. The rectangle is used as-is,
* and the icon image fills it. Icon is tinted with indicated color. If icon
* is not found or the icon type is not monochrome, the function does nothing.
*/
void UI_icon_draw_mono_rect(
float x, float y, float width, float height, int icon_id, const uchar color[4]);
void UI_icons_free();
void UI_icons_free_drawinfo(void *drawinfo);

View File

@@ -1650,7 +1650,6 @@ static void icon_draw_rect(float x,
float y,
int w,
int h,
float /*aspect*/,
int rw,
int rh,
const uint8_t *rect,
@@ -2014,8 +2013,7 @@ static void icon_draw_size(float x,
const ImBuf *ibuf = static_cast<const ImBuf *>(icon->obj);
GPU_blend(GPU_BLEND_ALPHA_PREMULT);
icon_draw_rect(
x, y, w, h, aspect, ibuf->x, ibuf->y, ibuf->byte_buffer.data, alpha, desaturate);
icon_draw_rect(x, y, w, h, ibuf->x, ibuf->y, ibuf->byte_buffer.data, alpha, desaturate);
GPU_blend(GPU_BLEND_ALPHA);
}
else if (di->type == ICON_TYPE_VECTOR) {
@@ -2055,7 +2053,7 @@ static void icon_draw_size(float x,
}
GPU_blend(GPU_BLEND_ALPHA_PREMULT);
icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->byte_buffer.data, alpha, desaturate);
icon_draw_rect(x, y, w, h, w, h, ibuf->byte_buffer.data, alpha, desaturate);
GPU_blend(GPU_BLEND_ALPHA);
}
else if (di->type == ICON_TYPE_EVENT) {
@@ -2125,7 +2123,7 @@ static void icon_draw_size(float x,
return;
}
icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, desaturate);
icon_draw_rect(x, y, w, h, iimg->w, iimg->h, iimg->rect, alpha, desaturate);
}
else if (di->type == ICON_TYPE_PREVIEW) {
PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) :
@@ -2144,7 +2142,6 @@ static void icon_draw_size(float x,
y,
w,
h,
aspect,
pi->w[size],
pi->h[size],
reinterpret_cast<const uint8_t *>(pi->rect[size]),
@@ -2696,6 +2693,35 @@ void UI_icon_draw_ex(float x,
text_overlay);
}
void UI_icon_draw_mono_rect(
float x, float y, float width, float height, int icon_id, const uchar color[4])
{
Icon *icon = BKE_icon_get(icon_id);
if (icon == nullptr) {
return;
}
DrawInfo *di = icon_ensure_drawinfo(icon);
if (di->type != ICON_TYPE_MONO_TEXTURE) {
return;
}
float fcolor[4];
straight_uchar_to_premul_float(fcolor, color);
icon_draw_texture(x,
y,
width,
height,
di->data.texture.x,
di->data.texture.y,
di->data.texture.w,
di->data.texture.h,
fcolor[3],
fcolor,
false,
nullptr);
}
void UI_icon_text_overlay_init_from_count(IconTextOverlay *text_overlay,
const int icon_indicator_number)
{

View File

@@ -2156,7 +2156,7 @@ void UI_view2d_text_cache_draw(ARegion *region)
}
if (col_pack_prev != v2s->col.pack) {
BLF_color3ubv(font_id, v2s->col.ub);
BLF_color4ubv(font_id, v2s->col.ub);
col_pack_prev = v2s->col.pack;
}

View File

@@ -41,7 +41,6 @@ struct Editing;
struct ListBase;
#define DEFAULT_IMG_STRIP_LENGTH 25 /* XXX arbitrary but ok for now. */
#define OVERLAP_ALPHA 180
namespace blender::ed::seq {

View File

@@ -20,6 +20,7 @@
#include "BIF_glutil.hh"
#include "SEQ_channels.hh"
#include "SEQ_relations.hh"
#include "SEQ_render.hh"
#include "SEQ_sequencer.hh"
@@ -464,6 +465,9 @@ void draw_seq_strip_thumbnail(View2D *v2d,
return;
}
Editing *ed = SEQ_editing_get(scene);
ListBase *channels = ed ? SEQ_channels_displayed_get(ed) : nullptr;
const float thumb_height = y2 - y1;
seq_get_thumb_image_dimensions(
seq, pixelx, pixely, &thumb_width, thumb_height, &image_width, &image_height);
@@ -479,7 +483,6 @@ void draw_seq_strip_thumbnail(View2D *v2d,
}
float timeline_frame = SEQ_render_thumbnail_first_frame_get(scene, seq, thumb_width, &v2d->cur);
float thumb_x_end;
GSet *last_displayed_thumbnails = last_displayed_thumbnails_list_ensure(C, seq);
/* Cleanup thumbnail list outside of rendered range, which is cleaned up one by one to prevent
@@ -490,7 +493,7 @@ void draw_seq_strip_thumbnail(View2D *v2d,
/* Start drawing. */
while (timeline_frame < upper_thumb_bound) {
thumb_x_end = timeline_frame + thumb_width;
float thumb_x_end = timeline_frame + thumb_width;
clipped = false;
/* Checks to make sure that thumbs are loaded only when in view and within the confines of the
@@ -510,20 +513,17 @@ void draw_seq_strip_thumbnail(View2D *v2d,
if (thumb_x_end > (upper_thumb_bound)) {
thumb_x_end = upper_thumb_bound;
clipped = true;
if (thumb_x_end - timeline_frame < 1) {
break;
}
}
float zoom_x = thumb_width / image_width;
float zoom_y = thumb_height / image_height;
float cropx_min = (cut_off / pixelx) / (zoom_y / pixely);
float cropx_max = ((thumb_x_end - timeline_frame) / pixelx) / (zoom_y / pixely);
if (cropx_max == (thumb_x_end - timeline_frame)) {
cropx_max = cropx_max + 1;
int cropx_min = int((cut_off / pixelx) / (zoom_y / pixely));
int cropx_max = int(((thumb_x_end - timeline_frame) / pixelx) / (zoom_y / pixely));
if (cropx_max < 1) {
break;
}
BLI_rcti_init(&crop, int(cropx_min), int(cropx_max), 0, int(image_height) - 1);
BLI_rcti_init(&crop, cropx_min, cropx_max - 1, 0, int(image_height) - 1);
/* Get the image. */
ImBuf *ibuf = SEQ_get_thumbnail(&context, seq, timeline_frame, &crop, clipped);
@@ -548,19 +548,21 @@ void draw_seq_strip_thumbnail(View2D *v2d,
break;
}
/* Transparency on overlap. */
if (seq->flag & SEQ_OVERLAP) {
/* Transparency on mute. */
bool muted = channels ? SEQ_render_is_muted(channels, seq) : false;
if (muted) {
const uchar alpha = 120;
GPU_blend(GPU_BLEND_ALPHA);
if (ibuf->byte_buffer.data) {
uchar *buf = ibuf->byte_buffer.data;
for (int pixel = ibuf->x * ibuf->y; pixel--; buf += 4) {
buf[3] = OVERLAP_ALPHA;
buf[3] = alpha;
}
}
else if (ibuf->float_buffer.data) {
float *buf = ibuf->float_buffer.data;
for (int pixel = ibuf->x * ibuf->y; pixel--; buf += ibuf->channels) {
buf[3] = (OVERLAP_ALPHA / 255.0f);
buf[3] = (alpha / 255.0f);
}
}
}

View File

@@ -1,4 +1,5 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
@@ -48,6 +49,7 @@
#include "SEQ_transform.hh"
#include "SEQ_utils.hh"
#include "UI_interface_icons.hh"
#include "UI_resources.hh"
#include "UI_view2d.hh"
@@ -67,6 +69,8 @@
#define SEQ_HANDLE_SIZE 8.0f
#define MUTE_ALPHA 120
constexpr float MISSING_ICON_SIZE = 16.0f;
struct StripDrawContext {
Sequence *seq;
/* Strip boundary in timeline space. Content start/end is clamped by left/right handle. */
@@ -82,6 +86,7 @@ struct StripDrawContext {
bool is_active_strip;
bool is_single_image; /* Strip has single frame of content. */
bool show_strip_color_tag;
bool missing_data_block;
};
struct TimelineDrawContext {
@@ -177,6 +182,25 @@ static void strip_draw_context_set_strip_content_visibility(TimelineDrawContext
threshold;
}
static bool meta_strip_has_missing_data(const Sequence *seq)
{
if (seq->type != SEQ_TYPE_META) {
return false;
}
const ListBase *seqbase = &seq->seqbase;
if (!seqbase || BLI_listbase_is_empty(seqbase)) {
return false;
}
LISTBASE_FOREACH (const Sequence *, sub, seqbase) {
if (!SEQ_sequence_has_source(sub)) {
return true;
}
}
return false;
}
static StripDrawContext strip_draw_context_get(TimelineDrawContext *ctx, Sequence *seq)
{
StripDrawContext strip_ctx;
@@ -211,6 +235,7 @@ static StripDrawContext strip_draw_context_get(TimelineDrawContext *ctx, Sequenc
strip_ctx.handle_width = sequence_handle_size_get_clamped(ctx->scene, seq, ctx->pixelx);
strip_ctx.show_strip_color_tag = (ctx->sseq->timeline_overlay.flag &
SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG);
strip_ctx.missing_data_block = !SEQ_sequence_has_source(seq) || meta_strip_has_missing_data(seq);
if (strip_ctx.can_draw_text_overlay) {
strip_ctx.strip_content_top = strip_ctx.top - min_ff(0.40f, 20 * UI_SCALE_FAC * ctx->pixely);
@@ -570,14 +595,14 @@ static void drawmeta_contents(TimelineDrawContext *timeline_ctx, const StripDraw
return;
}
Scene *scene = timeline_ctx->scene;
const Scene *scene = timeline_ctx->scene;
uchar col[4];
int chan_min = MAXSEQ;
int chan_max = 0;
int chan_range = 0;
float draw_range = strip_ctx->top - strip_ctx->bottom;
float draw_range = strip_ctx->strip_content_top - strip_ctx->bottom;
float draw_height;
Editing *ed = SEQ_editing_get(scene);
@@ -635,6 +660,12 @@ static void drawmeta_contents(TimelineDrawContext *timeline_ctx, const StripDraw
col[3] = 196;
}
if (!SEQ_sequence_has_source(seq)) {
col[0] = 112;
col[1] = 0;
col[2] = 0;
}
/* Clamp within parent sequence strip bounds. */
if (x1_chan < strip_ctx->left_handle) {
x1_chan = strip_ctx->left_handle;
@@ -667,7 +698,7 @@ static void draw_seq_handle(TimelineDrawContext *timeline_ctx,
const StripDrawContext *strip_ctx,
const short direction)
{
Sequence *seq = strip_ctx->seq;
const Sequence *seq = strip_ctx->seq;
if (SEQ_transform_is_locked(timeline_ctx->channels, seq)) {
return;
}
@@ -745,17 +776,16 @@ static void draw_seq_handle(TimelineDrawContext *timeline_ctx,
}
}
/* Strip border, and outline for selected/active strips. */
static void draw_seq_outline(TimelineDrawContext *timeline_ctx, const StripDrawContext *strip_ctx)
{
Sequence *seq = strip_ctx->seq;
const Sequence *seq = strip_ctx->seq;
const bool selected = seq->flag & SELECT;
/* Get the color for the outline. */
/* Outline color. */
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);
if (selected) {
UI_GetThemeColor3ubv(strip_ctx->is_active_strip ? TH_SEQ_ACTIVE : TH_SEQ_SELECTED, col);
}
else {
/* Color for unselected strips is a bit darker than the background. */
@@ -765,12 +795,9 @@ static void draw_seq_outline(TimelineDrawContext *timeline_ctx, const StripDrawC
/* Outline while translating strips:
* - Slightly lighter.
* - Red when overlapping with other strips.
*/
* - 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 ((G.moving & G_TRANSFORM_SEQ) && selected && overlap_mode != SEQ_OVERLAP_OVERWRITE) {
if (seq->flag & SEQ_OVERLAP) {
col[0] = 255;
col[1] = col[2] = 33;
@@ -780,44 +807,35 @@ static void draw_seq_outline(TimelineDrawContext *timeline_ctx, const StripDrawC
}
}
/* 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;
/* Selected outline: 2px wide outline, plus 1px wide background inset. */
const float x0 = strip_ctx->left_handle;
const float x1 = strip_ctx->right_handle;
const float y0 = strip_ctx->bottom;
const float y1 = strip_ctx->top;
if (selected) {
const float dx = timeline_ctx->pixelx;
const float dy = timeline_ctx->pixely;
/* 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);
/* Left, right, bottom, top. */
timeline_ctx->quads->add_quad(x0 - dx, y0, x0 + dx, y1, col);
timeline_ctx->quads->add_quad(x1 - dx, y0, x1 + dx, y1, col);
timeline_ctx->quads->add_quad(x0, y0, x1, y0 + dy * 2, col);
timeline_ctx->quads->add_quad(x0, y1 - dy * 2, x1, y1, col);
/* Inset. */
UI_GetThemeColor3ubv(TH_BACK, col);
timeline_ctx->quads->add_quad(x0 + dx, y0 + dy * 2, x0 + dx * 2, y1 - dy * 2, col);
timeline_ctx->quads->add_quad(x1 - dx * 2, y0 + dy * 2, x1 - dx, y1 - dy * 2, col);
timeline_ctx->quads->add_quad(x0 + dx, y0 + dy * 2, x1 - dx, y0 + dy * 3, col);
timeline_ctx->quads->add_quad(x0 + dx, y1 - dy * 3, x1 - dx, y1 - dy * 2, 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);
/* Thin wireframe outline for unselected strips. */
timeline_ctx->quads->add_wire_quad(x0, y0, x1, y1, col);
}
}
static const char *draw_seq_text_get_name(Sequence *seq)
static const char *draw_seq_text_get_name(const Sequence *seq)
{
const char *name = seq->name + 2;
if (name[0] == '\0') {
@@ -826,7 +844,7 @@ static const char *draw_seq_text_get_name(Sequence *seq)
return name;
}
static void draw_seq_text_get_source(Sequence *seq, char *r_source, size_t source_maxncpy)
static void draw_seq_text_get_source(const Sequence *seq, char *r_source, size_t source_maxncpy)
{
*r_source = '\0';
@@ -888,7 +906,7 @@ static size_t draw_seq_text_get_overlay_string(TimelineDrawContext *timeline_ctx
char *r_overlay_string,
size_t overlay_string_len)
{
Sequence *seq = strip_ctx->seq;
const Sequence *seq = strip_ctx->seq;
const char *text_sep = " | ";
const char *text_array[5];
@@ -923,6 +941,95 @@ static size_t draw_seq_text_get_overlay_string(TimelineDrawContext *timeline_ctx
return BLI_string_join_array(r_overlay_string, overlay_string_len, text_array, i);
}
static void get_strip_text_color(const TimelineDrawContext *ctx,
const StripDrawContext *strip,
uchar r_col[4])
{
/* Text: 75% opacity, fully opaque when selected/active. */
const Sequence *seq = strip->seq;
const bool active_or_selected = (seq->flag & SELECT) || strip->is_active_strip;
if (active_or_selected) {
UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, r_col);
r_col[3] = 255;
}
else {
r_col[0] = r_col[1] = r_col[2] = 224;
r_col[3] = 192;
}
/* Muted strips: gray color, reduce opacity. */
if (SEQ_render_is_muted(ctx->channels, seq)) {
r_col[0] = r_col[1] = r_col[2] = 192;
r_col[3] *= 0.66f;
}
}
static void draw_icon_centered(TimelineDrawContext &ctx,
const rctf &rect,
int icon_id,
const uchar color[4])
{
const float icon_size_x = MISSING_ICON_SIZE * ctx.pixelx * UI_SCALE_FAC;
const float icon_size_y = MISSING_ICON_SIZE * ctx.pixely * UI_SCALE_FAC;
if (BLI_rctf_size_x(&rect) * 1.1f < icon_size_x || BLI_rctf_size_y(&rect) * 1.1f < icon_size_y) {
return;
}
UI_icon_draw_mono_rect(BLI_rctf_cent_x(&rect) - icon_size_x * 0.5f,
BLI_rctf_cent_y(&rect) - icon_size_y * 0.5f,
icon_size_x,
icon_size_y,
icon_id,
color);
}
static void draw_strip_icons(TimelineDrawContext *timeline_ctx,
const blender::Vector<StripDrawContext> &strips)
{
timeline_ctx->quads->draw();
GPU_blend(GPU_BLEND_ALPHA);
UI_icon_draw_cache_begin();
const float icon_size_x = MISSING_ICON_SIZE * timeline_ctx->pixelx * UI_SCALE_FAC;
for (const StripDrawContext &strip : strips) {
if (!strip.missing_data_block) {
continue;
}
/* Draw icon in the title bar area. */
if ((timeline_ctx->sseq->flag & SEQ_SHOW_OVERLAY) != 0 && !strip.strip_is_too_small &&
strip.can_draw_text_overlay)
{
uchar col[4];
get_strip_text_color(timeline_ctx, &strip, col);
float icon_indent = 2.0f * strip.handle_width - 4 * timeline_ctx->pixelx * UI_SCALE_FAC;
rctf rect;
rect.xmin = max_ff(strip.left_handle, timeline_ctx->v2d->cur.xmin) + icon_indent;
rect.xmax = min_ff(strip.right_handle - strip.handle_width, rect.xmin + icon_size_x);
rect.ymin = strip.strip_content_top;
rect.ymax = strip.top;
draw_icon_centered(*timeline_ctx, rect, ICON_LIBRARY_DATA_BROKEN, col);
}
/* Draw icon in center of content. */
if (strip.can_draw_strip_content && strip.seq->type != SEQ_TYPE_META) {
rctf rect;
rect.xmin = strip.left_handle + strip.handle_width;
rect.xmax = strip.right_handle - strip.handle_width;
rect.ymin = strip.bottom;
rect.ymax = strip.strip_content_top;
uchar col[4] = {112, 0, 0, 255};
draw_icon_centered(*timeline_ctx, rect, ICON_LIBRARY_DATA_BROKEN, col);
}
}
UI_icon_draw_cache_end();
GPU_blend(GPU_BLEND_NONE);
}
/* Draw info text on a sequence strip. */
static void draw_seq_text_overlay(TimelineDrawContext *timeline_ctx,
const StripDrawContext *strip_ctx)
@@ -945,30 +1052,23 @@ static void draw_seq_text_overlay(TimelineDrawContext *timeline_ctx,
return;
}
/* White text for the active strip. */
uchar col[4];
col[0] = col[1] = col[2] = strip_ctx->is_active_strip ? 255 : 10;
col[3] = 255;
/* Make the text duller when the strip is muted. */
if (SEQ_render_is_muted(timeline_ctx->channels, strip_ctx->seq)) {
if (strip_ctx->is_active_strip) {
UI_GetColorPtrShade3ubv(col, col, -70);
}
else {
UI_GetColorPtrShade3ubv(col, col, 15);
}
}
get_strip_text_color(timeline_ctx, strip_ctx, col);
float text_margin = 2.0f * strip_ctx->handle_width;
rctf rect;
rect.xmin = strip_ctx->left_handle + 2.0f * strip_ctx->handle_width;
rect.xmax = strip_ctx->right_handle - 2.0f * strip_ctx->handle_width;
rect.xmin = strip_ctx->left_handle + text_margin;
rect.xmax = strip_ctx->right_handle - text_margin;
rect.ymax = strip_ctx->top;
/* Depending on the vertical space, draw text on top or in the center of strip. */
rect.ymin = !strip_ctx->can_draw_strip_content ? strip_ctx->bottom :
strip_ctx->strip_content_top;
CLAMP(rect.xmin, timeline_ctx->v2d->cur.xmin + text_margin, timeline_ctx->v2d->cur.xmax);
rect.xmin = max_ff(rect.xmin, timeline_ctx->v2d->cur.xmin + text_margin);
if (strip_ctx->missing_data_block) {
rect.xmin += MISSING_ICON_SIZE * timeline_ctx->pixelx * UI_SCALE_FAC;
}
rect.xmin = min_ff(rect.xmin, timeline_ctx->v2d->cur.xmax);
CLAMP(rect.xmax, timeline_ctx->v2d->cur.xmin + text_margin, timeline_ctx->v2d->cur.xmax);
UI_view2d_text_cache_add_rectf(
@@ -978,7 +1078,7 @@ static void draw_seq_text_overlay(TimelineDrawContext *timeline_ctx,
static void draw_strip_offsets(TimelineDrawContext *timeline_ctx,
const StripDrawContext *strip_ctx)
{
Sequence *seq = strip_ctx->seq;
const Sequence *seq = strip_ctx->seq;
if ((timeline_ctx->sseq->flag & SEQ_SHOW_OVERLAY) == 0) {
return;
}
@@ -991,8 +1091,8 @@ static void draw_strip_offsets(TimelineDrawContext *timeline_ctx,
return;
}
Scene *scene = timeline_ctx->scene;
ListBase *channels = timeline_ctx->channels;
const Scene *scene = timeline_ctx->scene;
const ListBase *channels = timeline_ctx->channels;
uchar col[4], blend_col[4];
color3ubv_from_seq(scene, seq, strip_ctx->show_strip_color_tag, col);
@@ -1032,23 +1132,19 @@ static void draw_strip_offsets(TimelineDrawContext *timeline_ctx,
}
}
static uchar mute_overlap_alpha_factor_get(const ListBase *channels, const Sequence *seq)
static uchar mute_alpha_factor_get(const ListBase *channels, const Sequence *seq)
{
/* Draw muted strips semi-transparent. */
if (SEQ_render_is_muted(channels, seq)) {
return MUTE_ALPHA;
}
/* Draw background semi-transparent when overlapping strips. */
if (seq->flag & SEQ_OVERLAP) {
return OVERLAP_ALPHA;
}
return 255;
}
static void draw_strip_color_band(TimelineDrawContext *timeline_ctx,
const StripDrawContext *strip_ctx)
{
Sequence *seq = strip_ctx->seq;
const Sequence *seq = strip_ctx->seq;
if ((timeline_ctx->sseq->flag & SEQ_SHOW_OVERLAY) == 0 || (seq->type != SEQ_TYPE_COLOR)) {
return;
}
@@ -1056,7 +1152,7 @@ static void draw_strip_color_band(TimelineDrawContext *timeline_ctx,
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);
col[3] = mute_alpha_factor_get(timeline_ctx->channels, seq);
timeline_ctx->quads->add_quad(strip_ctx->left_handle,
strip_ctx->bottom,
@@ -1076,12 +1172,17 @@ static void draw_strip_color_band(TimelineDrawContext *timeline_ctx,
static void draw_strip_background(TimelineDrawContext *timeline_ctx,
const StripDrawContext *strip_ctx)
{
Scene *scene = timeline_ctx->scene;
Sequence *seq = strip_ctx->seq;
const Scene *scene = timeline_ctx->scene;
const Sequence *seq = strip_ctx->seq;
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);
col[3] = mute_alpha_factor_get(timeline_ctx->channels, seq);
/* Muted strips: turn almost gray. */
if (col[3] == MUTE_ALPHA) {
uchar muted_color[3] = {128, 128, 128};
UI_GetColorPtrBlendShade3ubv(col, muted_color, col, 0.8f, 0);
}
/* Draw the main strip body. */
float x1 = strip_ctx->is_single_image ? strip_ctx->left_handle : strip_ctx->content_start;
@@ -1132,7 +1233,7 @@ static void draw_seq_transition_strip_half(TimelineDrawContext *timeline_ctx,
}
}
col[3] = mute_overlap_alpha_factor_get(timeline_ctx->channels, strip_ctx->seq);
col[3] = mute_alpha_factor_get(timeline_ctx->channels, strip_ctx->seq);
float tri[3][2];
@@ -1179,12 +1280,12 @@ static void draw_seq_locked(TimelineDrawContext *timeline_ctx,
immUniform1i("size1", 8);
immUniform1i("size2", 4);
for (const StripDrawContext &strip_ctx : strips) {
if (!SEQ_transform_is_locked(timeline_ctx->channels, strip_ctx.seq)) {
for (const StripDrawContext &strip : strips) {
if (!SEQ_transform_is_locked(timeline_ctx->channels, strip.seq)) {
continue;
}
immRectf(pos, strip_ctx.left_handle, strip_ctx.bottom, strip_ctx.right_handle, strip_ctx.top);
immRectf(pos, strip.left_handle, strip.bottom, strip.right_handle, strip.strip_content_top);
}
immUnbindProgram();
@@ -1194,15 +1295,27 @@ static void draw_seq_locked(TimelineDrawContext *timeline_ctx,
static void draw_seq_invalid(TimelineDrawContext *timeline_ctx, const StripDrawContext *strip_ctx)
{
if (SEQ_sequence_has_source(strip_ctx->seq)) {
if (!strip_ctx->missing_data_block) {
return;
}
uchar color[4] = {255, 0, 0, 230};
timeline_ctx->quads->add_quad(strip_ctx->left_handle,
strip_ctx->top,
strip_ctx->right_handle,
strip_ctx->strip_content_top,
color);
/* Do not tint title area for muted strips; we want to see gray for them. */
if (!SEQ_render_is_muted(timeline_ctx->channels, strip_ctx->seq)) {
uchar col_top[4] = {112, 0, 0, 230};
timeline_ctx->quads->add_quad(strip_ctx->left_handle,
strip_ctx->top,
strip_ctx->right_handle,
strip_ctx->strip_content_top,
col_top);
}
/* Do not tint content area for meta strips; we want to display children. */
if (strip_ctx->seq->type != SEQ_TYPE_META) {
uchar col_main[4] = {64, 0, 0, 230};
timeline_ctx->quads->add_quad(strip_ctx->left_handle,
strip_ctx->strip_content_top,
strip_ctx->right_handle,
strip_ctx->bottom,
col_main);
}
}
/**
@@ -1422,6 +1535,8 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx,
return;
}
UI_view2d_view_ortho(timeline_ctx->v2d);
/* Draw parts of strips below thumbnails. */
GPU_blend(GPU_BLEND_ALPHA);
for (const StripDrawContext &strip_ctx : strips) {
@@ -1451,6 +1566,7 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx,
for (const StripDrawContext &strip_ctx : strips) {
draw_seq_fcurve_overlay(timeline_ctx, &strip_ctx);
draw_seq_waveform_overlay(timeline_ctx, &strip_ctx);
draw_seq_invalid(timeline_ctx, &strip_ctx);
}
timeline_ctx->quads->draw();
GPU_blend(GPU_BLEND_NONE);
@@ -1461,15 +1577,27 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx,
/* Draw the rest. */
GPU_blend(GPU_BLEND_ALPHA);
for (const StripDrawContext &strip_ctx : strips) {
draw_seq_invalid(timeline_ctx, &strip_ctx);
draw_effect_inputs_highlight(timeline_ctx, &strip_ctx);
draw_multicam_highlight(timeline_ctx, &strip_ctx);
draw_seq_solo_highlight(timeline_ctx, &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);
}
/* Draw icons separately (different shader). */
draw_strip_icons(timeline_ctx, strips);
timeline_ctx->quads->draw();
/* Draw text labels with a drop shadow. */
const int font_id = BLF_default();
BLF_enable(font_id, BLF_SHADOW);
BLF_shadow(font_id, 3, blender::float4{0.0f, 0.0f, 0.0f, 1.0f});
BLF_shadow_offset(font_id, 1, -1);
UI_view2d_text_cache_draw(timeline_ctx->region);
BLF_disable(font_id, BLF_SHADOW);
GPU_blend(GPU_BLEND_NONE);
}
@@ -1483,18 +1611,6 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx)
visible_strips_ordered_get(timeline_ctx, unselected, selected);
draw_seq_strips(timeline_ctx, unselected);
draw_seq_strips(timeline_ctx, selected);
/* Draw text overlay parts in the opposite order: first selected set, then
* unselected (UI_view2d_text_cache_add_rectf adds new text in front of
* other entries!). This is to make sure selected strip labels are on top
* of others while they are being dragged over. */
for (const StripDrawContext &strip_ctx : selected) {
draw_seq_text_overlay(timeline_ctx, &strip_ctx);
}
for (const StripDrawContext &strip_ctx : unselected) {
draw_seq_text_overlay(timeline_ctx, &strip_ctx);
}
UI_view2d_text_cache_draw(timeline_ctx->region);
}
static void draw_timeline_sfra_efra(TimelineDrawContext *ctx)
@@ -1570,7 +1686,7 @@ static void draw_timeline_sfra_efra(TimelineDrawContext *ctx)
}
struct CacheDrawData {
View2D *v2d;
const View2D *v2d;
float stripe_ofs_y;
float stripe_ht;
int cache_flag;
@@ -1651,8 +1767,8 @@ static void draw_cache_stripe(const Scene *scene,
static void draw_cache_background(const bContext *C, CacheDrawData *draw_data)
{
using blender::uchar4;
Scene *scene = CTX_data_scene(C);
View2D *v2d = UI_view2d_fromcontext(C);
const Scene *scene = CTX_data_scene(C);
const View2D *v2d = UI_view2d_fromcontext(C);
const uchar4 bg_final{255, 102, 51, 25};
const uchar4 bg_raw{255, 25, 5, 25};
@@ -1694,7 +1810,7 @@ static void draw_cache_background(const bContext *C, CacheDrawData *draw_data)
static void draw_cache_view(const bContext *C)
{
Scene *scene = CTX_data_scene(C);
View2D *v2d = UI_view2d_fromcontext(C);
const View2D *v2d = UI_view2d_fromcontext(C);
if ((scene->ed->cache_flag & SEQ_CACHE_VIEW_ENABLE) == 0) {
return;

View File

@@ -71,7 +71,7 @@ void SEQ_transform_offset_after_frame(Scene *scene,
* Check if `seq` can be moved.
* This function also checks `SeqTimelineChannel` flag.
*/
bool SEQ_transform_is_locked(ListBase *channels, Sequence *seq);
bool SEQ_transform_is_locked(ListBase *channels, const Sequence *seq);
/* Image transformation. */

View File

@@ -17,7 +17,7 @@ struct Sequence;
struct StripElem;
void SEQ_sequence_base_unique_name_recursive(Scene *scene, ListBase *seqbasep, Sequence *seq);
const char *SEQ_sequence_give_name(Sequence *seq);
const char *SEQ_sequence_give_name(const Sequence *seq);
ListBase *SEQ_get_seqbase_from_sequence(Sequence *seq, ListBase **channels, int *r_offset);
const Sequence *SEQ_get_topmost_sequence(const Scene *scene, int frame);
/**

View File

@@ -599,7 +599,7 @@ void SEQ_transform_offset_after_frame(Scene *scene,
}
}
bool SEQ_transform_is_locked(ListBase *channels, Sequence *seq)
bool SEQ_transform_is_locked(ListBase *channels, const Sequence *seq)
{
const SeqTimelineChannel *channel = SEQ_channel_get_by_index(channels, seq->machine);
return seq->flag & SEQ_LOCK ||

View File

@@ -161,7 +161,7 @@ static const char *give_seqname_by_type(int type)
}
}
const char *SEQ_sequence_give_name(Sequence *seq)
const char *SEQ_sequence_give_name(const Sequence *seq)
{
const char *name = give_seqname_by_type(seq->type);