Files
test/source/blender/editors/mask/mask_draw.c
Julian Eisel 65166e145b Cleanup: Remove scene frame macros (CFRA et al.)
Removes the following macros for scene/render frame values:
- `CFRA`
- `SUBFRA`
- `SFRA`
- `EFRA`

These macros don't add much, other than saving a few characters when typing.
It's not immediately clear what they refer to, they just hide what they
actually access. Just be explicit and clear about that.
Plus these macros gave read and write access to the variables, so eyesores like
this would be done (eyesore because it looks like assigning to a constant):
```
CFRA = some_frame_nbr;
```

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D15311
2022-06-30 18:38:44 +02:00

814 lines
23 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2012 Blender Foundation. All rights reserved. */
/** \file
* \ingroup edmask
*/
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_mask.h"
#include "DNA_mask_types.h"
#include "DNA_object_types.h" /* SELECT */
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "ED_clip.h"
#include "ED_mask.h" /* own include */
#include "ED_screen.h"
#include "ED_space_api.h"
#include "BIF_glutil.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_state.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "DEG_depsgraph_query.h"
static void mask_spline_color_get(MaskLayer *mask_layer,
MaskSpline *spline,
const bool is_sel,
uchar r_rgb[4])
{
if (is_sel) {
if (mask_layer->act_spline == spline) {
r_rgb[0] = r_rgb[1] = r_rgb[2] = 255;
}
else {
r_rgb[0] = 255;
r_rgb[1] = r_rgb[2] = 0;
}
}
else {
r_rgb[0] = 128;
r_rgb[1] = r_rgb[2] = 0;
}
r_rgb[3] = 255;
}
static void mask_spline_feather_color_get(MaskLayer *UNUSED(mask_layer),
MaskSpline *UNUSED(spline),
const bool is_sel,
uchar r_rgb[4])
{
if (is_sel) {
r_rgb[1] = 255;
r_rgb[0] = r_rgb[2] = 0;
}
else {
r_rgb[1] = 128;
r_rgb[0] = r_rgb[2] = 0;
}
r_rgb[3] = 255;
}
static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2])
{
BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
ED_clip_point_undistorted_pos(sc, r_co, r_co);
BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
}
static void draw_single_handle(const MaskLayer *mask_layer,
const MaskSplinePoint *point,
const eMaskWhichHandle which_handle,
const int draw_type,
const float handle_size,
const float point_pos[2],
const float handle_pos[2])
{
const BezTriple *bezt = &point->bezt;
char handle_type;
if (ELEM(which_handle, MASK_WHICH_HANDLE_STICK, MASK_WHICH_HANDLE_LEFT)) {
handle_type = bezt->h1;
}
else {
handle_type = bezt->h2;
}
if (handle_type == HD_VECT) {
return;
}
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
const uchar rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3ubv(rgb_gray);
/* this could be split into its own loop */
if (draw_type == MASK_DT_OUTLINE) {
GPU_line_width(3.0f);
immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(pos, point_pos);
immVertex2fv(pos, handle_pos);
immEnd();
}
switch (handle_type) {
case HD_FREE:
immUniformThemeColor(TH_HANDLE_FREE);
break;
case HD_AUTO:
immUniformThemeColor(TH_HANDLE_AUTO);
break;
case HD_ALIGN:
case HD_ALIGN_DOUBLESIDE:
immUniformThemeColor(TH_HANDLE_ALIGN);
break;
}
GPU_line_width(1.0f);
immBegin(GPU_PRIM_LINES, 2);
immVertex2fv(pos, point_pos);
immVertex2fv(pos, handle_pos);
immEnd();
immUnbindProgram();
/* draw handle points */
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
immUniform1f("size", handle_size);
immUniform1f("outlineWidth", 1.5f);
float point_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; /* active color by default */
if (MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
if (point != mask_layer->act_point) {
UI_GetThemeColor3fv(TH_HANDLE_VERTEX_SELECT, point_color);
}
}
else {
UI_GetThemeColor3fv(TH_HANDLE_VERTEX, point_color);
}
immUniform4fv("outlineColor", point_color);
immUniformColor3fvAlpha(point_color, 0.25f);
immBegin(GPU_PRIM_POINTS, 1);
immVertex2fv(pos, handle_pos);
immEnd();
immUnbindProgram();
}
/* return non-zero if spline is selected */
static void draw_spline_points(const bContext *C,
MaskLayer *mask_layer,
MaskSpline *spline,
const char draw_type)
{
const bool is_spline_sel = (spline->flag & SELECT) &&
(mask_layer->visibility_flag & MASK_HIDE_SELECT) == 0;
uchar rgb_spline[4];
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
SpaceClip *sc = CTX_wm_space_clip(C);
bool undistort = false;
int tot_feather_point;
float(*feather_points)[2], (*fp)[2];
float min[2], max[2];
if (!spline->tot_point) {
return;
}
if (sc) {
undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
}
/* TODO: add this to sequence editor. */
float handle_size = 2.0f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
mask_spline_color_get(mask_layer, spline, is_spline_sel, rgb_spline);
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immUniform1f("size", 0.7f * handle_size);
/* feather points */
feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
for (int i = 0; i < spline->tot_point; i++) {
/* watch it! this is intentionally not the deform array, only check for sel */
MaskSplinePoint *point = &spline->points[i];
for (int j = 0; j <= point->tot_uw; j++) {
float feather_point[2];
bool sel = false;
copy_v2_v2(feather_point, *fp);
if (undistort) {
mask_point_undistort_pos(sc, feather_point, feather_point);
}
if (j == 0) {
sel = MASKPOINT_ISSEL_ANY(point);
}
else {
sel = (point->uw[j - 1].flag & SELECT) != 0;
}
if (sel) {
if (point == mask_layer->act_point) {
immUniformColor3f(1.0f, 1.0f, 1.0f);
}
else {
immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX_SELECT, 0, 255);
}
}
else {
immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX, 0, 255);
}
immBegin(GPU_PRIM_POINTS, 1);
immVertex2fv(pos, feather_point);
immEnd();
fp++;
}
}
MEM_freeN(feather_points);
immUnbindProgram();
GPU_line_smooth(true);
/* control points */
INIT_MINMAX2(min, max);
for (int i = 0; i < spline->tot_point; i++) {
/* watch it! this is intentionally not the deform array, only check for sel */
MaskSplinePoint *point = &spline->points[i];
MaskSplinePoint *point_deform = &points_array[i];
BezTriple *bezt = &point_deform->bezt;
float vert[2];
copy_v2_v2(vert, bezt->vec[1]);
if (undistort) {
mask_point_undistort_pos(sc, vert, vert);
}
/* draw handle segment */
if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
float handle[2];
BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_STICK, handle);
if (undistort) {
mask_point_undistort_pos(sc, handle, handle);
}
draw_single_handle(
mask_layer, point, MASK_WHICH_HANDLE_STICK, draw_type, handle_size, vert, handle);
}
else {
float handle_left[2], handle_right[2];
BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_LEFT, handle_left);
BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_RIGHT, handle_right);
if (undistort) {
mask_point_undistort_pos(sc, handle_left, handle_left);
mask_point_undistort_pos(sc, handle_left, handle_left);
}
draw_single_handle(
mask_layer, point, MASK_WHICH_HANDLE_LEFT, draw_type, handle_size, vert, handle_left);
draw_single_handle(
mask_layer, point, MASK_WHICH_HANDLE_RIGHT, draw_type, handle_size, vert, handle_right);
}
/* bind program in loop so it does not interfere with draw_single_handle */
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
/* draw CV point */
if (MASKPOINT_ISSEL_KNOT(point)) {
if (point == mask_layer->act_point) {
immUniformColor3f(1.0f, 1.0f, 1.0f);
}
else {
immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX_SELECT, 0, 255);
}
}
else {
immUniformThemeColorShadeAlpha(TH_HANDLE_VERTEX, 0, 255);
}
immBegin(GPU_PRIM_POINTS, 1);
immVertex2fv(pos, vert);
immEnd();
immUnbindProgram();
minmax_v2v2_v2(min, max, vert);
}
GPU_line_smooth(false);
if (is_spline_sel) {
float x = (min[0] + max[0]) * 0.5f;
float y = (min[1] + max[1]) * 0.5f;
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
immUniform1f("outlineWidth", 1.5f);
if (mask_layer->act_spline == spline) {
immUniformColor3f(1.0f, 1.0f, 1.0f);
}
else {
immUniformColor3f(1.0f, 1.0f, 0.0f);
}
immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 1.0f);
immUniform1f("size", 12.0f);
immBegin(GPU_PRIM_POINTS, 1);
immVertex2f(pos, x, y);
immEnd();
immUnbindProgram();
}
}
static void mask_color_active_tint(uchar r_rgb[4], const uchar rgb[4], const bool is_active)
{
if (!is_active) {
r_rgb[0] = (uchar)((((int)(rgb[0])) + 128) / 2);
r_rgb[1] = (uchar)((((int)(rgb[1])) + 128) / 2);
r_rgb[2] = (uchar)((((int)(rgb[2])) + 128) / 2);
r_rgb[3] = rgb[3];
}
else {
*(uint *)r_rgb = *(const uint *)rgb;
}
}
static void mask_draw_array(uint pos,
GPUPrimType prim_type,
const float (*points)[2],
uint vertex_len)
{
immBegin(prim_type, vertex_len);
for (uint i = 0; i < vertex_len; i++) {
immVertex2fv(pos, points[i]);
}
immEnd();
}
static void mask_draw_curve_type(const bContext *C,
MaskSpline *spline,
float (*orig_points)[2],
int tot_point,
const bool is_feather,
const bool is_active,
const uchar rgb_spline[4],
const char draw_type)
{
const GPUPrimType draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GPU_PRIM_LINE_LOOP :
GPU_PRIM_LINE_STRIP;
const uchar rgb_black[4] = {0x00, 0x00, 0x00, 0xff};
uchar rgb_tmp[4];
SpaceClip *sc = CTX_wm_space_clip(C);
float(*points)[2] = orig_points;
if (sc) {
const bool undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
if (undistort) {
points = MEM_callocN(2 * tot_point * sizeof(float), "undistorthed mask curve");
for (int i = 0; i < tot_point; i++) {
mask_point_undistort_pos(sc, points[i], orig_points[i]);
}
}
}
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
switch (draw_type) {
case MASK_DT_OUTLINE:
/* TODO(merwin): use fancy line shader here
* probably better with geometry shader (after core profile switch)
*/
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
GPU_line_width(3.0f);
mask_color_active_tint(rgb_tmp, rgb_black, is_active);
immUniformColor4ubv(rgb_tmp);
mask_draw_array(pos, draw_method, points, tot_point);
GPU_line_width(1.0f);
mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
immUniformColor4ubv(rgb_tmp);
mask_draw_array(pos, draw_method, points, tot_point);
immUnbindProgram();
break;
case MASK_DT_BLACK:
case MASK_DT_WHITE:
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
GPU_line_width(1.0f);
if (draw_type == MASK_DT_BLACK) {
rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0;
}
else {
rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255;
}
/* alpha values seem too low but gl draws many points that compensate for it */
if (is_feather) {
rgb_tmp[3] = 64;
}
else {
rgb_tmp[3] = 128;
}
if (is_feather) {
rgb_tmp[0] = (uchar)(((short)rgb_tmp[0] + (short)rgb_spline[0]) / 2);
rgb_tmp[1] = (uchar)(((short)rgb_tmp[1] + (short)rgb_spline[1]) / 2);
rgb_tmp[2] = (uchar)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2);
}
mask_color_active_tint(rgb_tmp, rgb_tmp, is_active);
immUniformColor4ubv(rgb_tmp);
mask_draw_array(pos, draw_method, points, tot_point);
immUnbindProgram();
break;
case MASK_DT_DASH: {
float colors[2][4];
mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
rgba_uchar_to_float(colors[0], rgb_tmp);
mask_color_active_tint(rgb_tmp, rgb_black, is_active);
rgba_uchar_to_float(colors[1], rgb_tmp);
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
immUniform1i("colors_len", 2); /* "advanced" mode */
immUniform4fv("color", colors[0]);
immUniform4fv("color2", colors[1]);
immUniform1f("dash_width", 4.0f);
immUniform1f("dash_factor", 0.5f);
GPU_line_width(1.0f);
mask_draw_array(pos, draw_method, points, tot_point);
immUnbindProgram();
break;
}
default:
BLI_assert(false);
}
if (points != orig_points) {
MEM_freeN(points);
}
}
static void draw_spline_curve(const bContext *C,
MaskLayer *mask_layer,
MaskSpline *spline,
const char draw_type,
const bool is_active,
const int width,
const int height)
{
const uint resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height),
BKE_mask_spline_resolution(spline, width, height));
uchar rgb_tmp[4];
const bool is_spline_sel = (spline->flag & SELECT) &&
(mask_layer->visibility_flag & MASK_HIDE_SELECT) == 0;
const bool is_fill = (spline->flag & MASK_SPLINE_NOFILL) == 0;
uint tot_diff_point;
float(*diff_points)[2];
uint tot_feather_point;
float(*feather_points)[2];
diff_points = BKE_mask_spline_differentiate_with_resolution(spline, resol, &tot_diff_point);
if (!diff_points) {
return;
}
GPU_line_smooth(true);
feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(
spline, resol, (is_fill != false), &tot_feather_point);
/* draw feather */
mask_spline_feather_color_get(mask_layer, spline, is_spline_sel, rgb_tmp);
mask_draw_curve_type(
C, spline, feather_points, tot_feather_point, true, is_active, rgb_tmp, draw_type);
if (!is_fill) {
const float *fp = &diff_points[0][0];
float *fp_feather = &feather_points[0][0];
BLI_assert(tot_diff_point == tot_feather_point);
for (int i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) {
float tvec[2];
sub_v2_v2v2(tvec, fp, fp_feather);
add_v2_v2v2(fp_feather, fp, tvec);
}
/* same as above */
mask_draw_curve_type(
C, spline, feather_points, tot_feather_point, true, is_active, rgb_tmp, draw_type);
}
MEM_freeN(feather_points);
/* draw main curve */
mask_spline_color_get(mask_layer, spline, is_spline_sel, rgb_tmp);
mask_draw_curve_type(
C, spline, diff_points, tot_diff_point, false, is_active, rgb_tmp, draw_type);
MEM_freeN(diff_points);
GPU_line_smooth(false);
}
static void draw_layer_splines(const bContext *C,
MaskLayer *layer,
const char draw_type,
const int width,
const int height,
const bool is_active)
{
LISTBASE_FOREACH (MaskSpline *, spline, &layer->splines) {
/* draw curve itself first... */
draw_spline_curve(C, layer, spline, draw_type, is_active, width, height);
if (!(layer->visibility_flag & MASK_HIDE_SELECT)) {
/* ...and then handles over the curve so they're nicely visible */
draw_spline_points(C, layer, spline, draw_type);
}
/* show undeform for testing */
if (0) {
void *back = spline->points_deform;
spline->points_deform = NULL;
draw_spline_curve(C, layer, spline, draw_type, is_active, width, height);
draw_spline_points(C, layer, spline, draw_type);
spline->points_deform = back;
}
}
}
static void draw_mask_layers(
const bContext *C, Mask *mask, const char draw_type, const int width, const int height)
{
GPU_blend(GPU_BLEND_ALPHA);
GPU_program_point_size(true);
MaskLayer *mask_layer;
int i;
MaskLayer *active = NULL;
for (mask_layer = mask->masklayers.first, i = 0; mask_layer != NULL;
mask_layer = mask_layer->next, i++) {
const bool is_active = (i == mask->masklay_act);
if (mask_layer->visibility_flag & MASK_HIDE_VIEW) {
continue;
}
if (is_active) {
active = mask_layer;
continue;
}
draw_layer_splines(C, mask_layer, draw_type, width, height, is_active);
}
if (active != NULL) {
draw_layer_splines(C, active, draw_type, width, height, true);
}
GPU_program_point_size(false);
GPU_blend(GPU_BLEND_NONE);
}
static float *mask_rasterize(Mask *mask, const int width, const int height)
{
MaskRasterHandle *handle;
float *buffer = MEM_mallocN(sizeof(float) * height * width, "rasterized mask buffer");
/* Initialize rasterization handle. */
handle = BKE_maskrasterize_handle_new();
BKE_maskrasterize_handle_init(handle, mask, width, height, true, true, true);
BKE_maskrasterize_buffer(handle, width, height, buffer);
/* Free memory. */
BKE_maskrasterize_handle_free(handle);
return buffer;
}
void ED_mask_draw_region(
Depsgraph *depsgraph,
Mask *mask_,
ARegion *region,
const char draw_flag,
const char draw_type,
const eMaskOverlayMode overlay_mode,
const float blend_factor,
/* convert directly into aspect corrected vars */
const int width_i,
const int height_i,
const float aspx,
const float aspy,
const bool do_scale_applied,
const bool do_draw_cb,
/* optional - only used by clip */
float stabmat[4][4],
/* optional - only used when do_post_draw is set or called from clip editor */
const bContext *C)
{
struct View2D *v2d = &region->v2d;
Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_->id);
/* aspect always scales vertically in movie and image spaces */
const float width = width_i, height = (float)height_i * (aspy / aspx);
int x, y;
/* int w, h; */
float zoomx, zoomy;
/* frame image */
float maxdim;
float xofs, yofs;
/* find window pixel coordinates of origin */
UI_view2d_view_to_region(&region->v2d, 0.0f, 0.0f, &x, &y);
// w = BLI_rctf_size_x(&v2d->tot);
// h = BLI_rctf_size_y(&v2d->tot);
zoomx = (float)(BLI_rcti_size_x(&region->winrct) + 1) / BLI_rctf_size_x(&region->v2d.cur);
zoomy = (float)(BLI_rcti_size_y(&region->winrct) + 1) / BLI_rctf_size_y(&region->v2d.cur);
if (do_scale_applied) {
zoomx /= width;
zoomy /= height;
}
x += v2d->tot.xmin * zoomx;
y += v2d->tot.ymin * zoomy;
/* frame the image */
maxdim = max_ff(width, height);
if (width == height) {
xofs = yofs = 0;
}
else if (width < height) {
xofs = ((height - width) / -2.0f) * zoomx;
yofs = 0.0f;
}
else { /* (width > height) */
xofs = 0.0f;
yofs = ((width - height) / -2.0f) * zoomy;
}
if (draw_flag & MASK_DRAWFLAG_OVERLAY) {
float buf_col[4] = {1.0f, 0.0f, 0.0f, 0.0f};
float *buffer = mask_rasterize(mask_eval, width, height);
if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
/* More blending types could be supported in the future. */
GPU_blend(GPU_BLEND_ALPHA);
buf_col[0] = -1.0f;
buf_col[3] = 1.0f;
}
GPU_matrix_push();
GPU_matrix_translate_2f(x, y);
GPU_matrix_scale_2f(zoomx, zoomy);
if (stabmat) {
GPU_matrix_mul(stabmat);
}
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, buf_col);
if (overlay_mode == MASK_OVERLAY_COMBINED) {
const float blend_col[4] = {0.0f, 0.0f, 0.0f, blend_factor};
immDrawPixelsTexTiled(
&state, 0.0f, 0.0f, width, height, GPU_R16F, false, buffer, 1.0f, 1.0f, blend_col);
}
else {
immDrawPixelsTexTiled(
&state, 0.0f, 0.0f, width, height, GPU_R16F, false, buffer, 1.0f, 1.0f, NULL);
}
GPU_matrix_pop();
if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
GPU_blend(GPU_BLEND_NONE);
}
MEM_freeN(buffer);
}
/* apply transformation so mask editing tools will assume drawing from the
* origin in normalized space */
GPU_matrix_push();
GPU_matrix_translate_2f(x + xofs, y + yofs);
GPU_matrix_scale_2f(zoomx, zoomy);
if (stabmat) {
GPU_matrix_mul(stabmat);
}
GPU_matrix_scale_2f(maxdim, maxdim);
if (do_draw_cb) {
ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW);
}
/* draw! */
if (draw_flag & MASK_DRAWFLAG_SPLINE) {
draw_mask_layers(C, mask_eval, draw_type, width, height);
}
if (do_draw_cb) {
ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
}
GPU_matrix_pop();
}
void ED_mask_draw_frames(
Mask *mask, ARegion *region, const int cfra, const int sfra, const int efra)
{
const float framelen = region->winx / (float)(efra - sfra + 1);
MaskLayer *mask_layer = BKE_mask_layer_active(mask);
if (mask_layer == NULL) {
return;
}
uint num_lines = BLI_listbase_count(&mask_layer->splines_shapes);
if (num_lines == 0) {
return;
}
/* Local coordinate visible rect inside region, to accommodate overlapping ui. */
const rcti *rect_visible = ED_region_visible_rect(region);
const int region_bottom = rect_visible->ymin;
uint pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ub(255, 175, 0, 255);
immBegin(GPU_PRIM_LINES, 2 * num_lines);
for (MaskLayerShape *mask_layer_shape = mask_layer->splines_shapes.first;
mask_layer_shape != NULL;
mask_layer_shape = mask_layer_shape->next) {
int frame = mask_layer_shape->frame;
// draw_keyframe(i, scene->r.cfra, sfra, framelen, 1);
int height = (frame == cfra) ? 22 : 10;
int x = (frame - sfra) * framelen;
immVertex2i(pos, x, region_bottom);
immVertex2i(pos, x, region_bottom + height * UI_DPI_FAC);
}
immEnd();
immUnbindProgram();
}