2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2012 Blender Foundation.
19 * All rights reserved.
22 * Contributor(s): Blender Foundation,
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/editors/mask/mask_draw.c
32 #include "MEM_guardedalloc.h"
34 #include "BLI_utildefines.h"
38 #include "BKE_context.h"
41 #include "DNA_mask_types.h"
42 #include "DNA_screen_types.h"
43 #include "DNA_object_types.h" /* SELECT */
45 #include "ED_mask.h" /* own include */
46 #include "ED_space_api.h"
49 #include "UI_resources.h"
50 #include "UI_view2d.h"
52 #include "mask_intern.h" /* own include */
54 static void mask_spline_color_get(MaskLayer *masklay, MaskSpline *spline, const int is_sel,
55 unsigned char r_rgb[4])
58 if (masklay->act_spline == spline) {
59 r_rgb[0] = r_rgb[1] = r_rgb[2] = 255;
63 r_rgb[1] = r_rgb[2] = 0;
68 r_rgb[1] = r_rgb[2] = 0;
74 static void mask_spline_feather_color_get(MaskLayer *UNUSED(masklay), MaskSpline *UNUSED(spline), const int is_sel,
75 unsigned char r_rgb[4])
79 r_rgb[0] = r_rgb[2] = 0;
83 r_rgb[0] = r_rgb[2] = 0;
90 static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline)
93 MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
95 if (!spline->tot_point)
99 glEnable(GL_LINE_STIPPLE);
100 glLineStipple(1, 0xAAAA);
104 for (i = 0; i < spline->tot_point; i++) {
105 MaskSplinePoint *point = &points_array[i];
106 BezTriple *bezt = &point->bezt;
108 if (point->parent.id) {
109 glVertex2f(bezt->vec[1][0],
112 glVertex2f(bezt->vec[1][0] - point->parent.offset[0],
113 bezt->vec[1][1] - point->parent.offset[1]);
119 glDisable(GL_LINE_STIPPLE);
123 /* return non-zero if spline is selected */
124 static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline,
125 const char UNUSED(draw_flag), const char draw_type)
127 const int is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
128 unsigned char rgb_spline[4];
129 MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
131 int i, hsize, tot_feather_point;
132 float (*feather_points)[2], (*fp)[2];
134 if (!spline->tot_point)
137 /* TODO, add this to sequence editor */
138 hsize = 4; /* UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); */
142 mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline);
145 feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
146 for (i = 0; i < spline->tot_point; i++) {
148 /* watch it! this is intentionally not the deform array, only check for sel */
149 MaskSplinePoint *point = &spline->points[i];
153 for (j = 0; j < point->tot_uw + 1; j++) {
157 sel = MASKPOINT_ISSEL_ANY(point);
160 sel = point->uw[j - 1].flag & SELECT;
164 if (point == masklay->act_point)
165 glColor3f(1.0f, 1.0f, 1.0f);
167 glColor3f(1.0f, 1.0f, 0.0f);
170 glColor3f(0.5f, 0.5f, 0.0f);
180 MEM_freeN(feather_points);
183 for (i = 0; i < spline->tot_point; i++) {
185 /* watch it! this is intentionally not the deform array, only check for sel */
186 MaskSplinePoint *point = &spline->points[i];
187 MaskSplinePoint *point_deform = &points_array[i];
188 BezTriple *bezt = &point_deform->bezt;
191 float *vert = bezt->vec[1];
192 int has_handle = BKE_mask_point_has_handle(point);
194 BKE_mask_point_handle(point_deform, handle);
196 /* draw handle segment */
199 /* this could be split into its own loop */
200 if (draw_type == MASK_DT_OUTLINE) {
201 const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
203 glColor4ubv(rgb_gray);
211 glColor3ubv(rgb_spline);
219 if (MASKPOINT_ISSEL_KNOT(point)) {
220 if (point == masklay->act_point)
221 glColor3f(1.0f, 1.0f, 1.0f);
223 glColor3f(1.0f, 1.0f, 0.0f);
226 glColor3f(0.5f, 0.5f, 0.0f);
232 /* draw handle points */
234 if (MASKPOINT_ISSEL_HANDLE(point)) {
235 if (point == masklay->act_point)
236 glColor3f(1.0f, 1.0f, 1.0f);
238 glColor3f(1.0f, 1.0f, 0.0f);
241 glColor3f(0.5f, 0.5f, 0.0f);
253 /* #define USE_XOR */
255 static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char rgb[4], const short is_active)
258 r_rgb[0] = (unsigned char)((((int)(rgb[0])) + 128) / 2);
259 r_rgb[1] = (unsigned char)((((int)(rgb[1])) + 128) / 2);
260 r_rgb[2] = (unsigned char)((((int)(rgb[2])) + 128) / 2);
264 *(unsigned int *)r_rgb = *(const unsigned int *)rgb;
268 static void mask_draw_curve_type(MaskSpline *spline, float (*points)[2], int tot_point,
269 const short is_feather, const short is_smooth, const short is_active,
270 const unsigned char rgb_spline[4], const char draw_type)
272 const int draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GL_LINE_LOOP : GL_LINE_STRIP;
273 const unsigned char rgb_black[4] = {0x00, 0x00, 0x00, 0xff};
274 // const unsigned char rgb_white[4] = {0xff, 0xff, 0xff, 0xff};
275 unsigned char rgb_tmp[4];
277 glEnableClientState(GL_VERTEX_ARRAY);
278 glVertexPointer(2, GL_FLOAT, 0, points);
282 case MASK_DT_OUTLINE:
285 mask_color_active_tint(rgb_tmp, rgb_black, is_active);
286 glColor4ubv(rgb_tmp);
288 glDrawArrays(draw_method, 0, tot_point);
291 mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
292 glColor4ubv(rgb_tmp);
293 glDrawArrays(draw_method, 0, tot_point);
299 glEnable(GL_LINE_STIPPLE);
302 glEnable(GL_COLOR_LOGIC_OP);
305 mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
306 glColor4ubv(rgb_tmp);
307 glLineStipple(3, 0xaaaa);
308 glEnableClientState(GL_VERTEX_ARRAY);
309 glVertexPointer(2, GL_FLOAT, 0, points);
310 glDrawArrays(draw_method, 0, tot_point);
313 glDisable(GL_COLOR_LOGIC_OP);
315 mask_color_active_tint(rgb_tmp, rgb_black, is_active);
316 glColor4ubv(rgb_tmp);
317 glLineStipple(3, 0x5555);
318 glDrawArrays(draw_method, 0, tot_point);
320 glDisable(GL_LINE_STIPPLE);
326 if (draw_type == MASK_DT_BLACK) { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0; }
327 else { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255; }
328 /* alpha values seem too low but gl draws many points that compensate for it */
329 if (is_feather) { rgb_tmp[3] = 64; }
330 else { rgb_tmp[3] = 128; }
333 rgb_tmp[0] = (unsigned char)(((short)rgb_tmp[0] + (short)rgb_spline[0]) / 2);
334 rgb_tmp[1] = (unsigned char)(((short)rgb_tmp[1] + (short)rgb_spline[1]) / 2);
335 rgb_tmp[2] = (unsigned char)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2);
338 if (is_smooth == FALSE && is_feather) {
340 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
343 mask_color_active_tint(rgb_tmp, rgb_tmp, is_active);
344 glColor4ubv(rgb_tmp);
346 glEnableClientState(GL_VERTEX_ARRAY);
347 glVertexPointer(2, GL_FLOAT, 0, points);
348 glDrawArrays(draw_method, 0, tot_point);
350 glDrawArrays(draw_method, 0, tot_point);
352 if (is_smooth == FALSE && is_feather) {
359 glDisableClientState(GL_VERTEX_ARRAY);
363 static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline,
364 const char draw_flag, const char draw_type,
365 const short is_active,
366 int width, int height)
368 const unsigned int resol = maxi(BKE_mask_spline_feather_resolution(spline, width, height),
369 BKE_mask_spline_resolution(spline, width, height));
371 unsigned char rgb_tmp[4];
373 const short is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
374 const short is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH);
375 const short is_fill = (spline->flag & MASK_SPLINE_NOFILL) == 0;
378 float (*diff_points)[2];
380 int tot_feather_point;
381 float (*feather_points)[2];
383 diff_points = BKE_mask_spline_differentiate_with_resolution_ex(spline, &tot_diff_point, resol);
389 glEnable(GL_LINE_SMOOTH);
391 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
394 feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, &tot_feather_point, resol, (is_fill != FALSE));
397 mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp);
398 mask_draw_curve_type(spline, feather_points, tot_feather_point,
399 TRUE, is_smooth, is_active,
404 float *fp = &diff_points[0][0];
405 float *fp_feather = &feather_points[0][0];
409 BLI_assert(tot_diff_point == tot_feather_point);
411 for (i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) {
412 sub_v2_v2v2(tvec, fp, fp_feather);
413 add_v2_v2v2(fp_feather, fp, tvec);
417 mask_draw_curve_type(spline, feather_points, tot_feather_point,
418 TRUE, is_smooth, is_active,
422 MEM_freeN(feather_points);
424 /* draw main curve */
425 mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp);
426 mask_draw_curve_type(spline, diff_points, tot_diff_point,
427 FALSE, is_smooth, is_active,
429 MEM_freeN(diff_points);
431 if (draw_flag & MASK_DRAWFLAG_SMOOTH) {
432 glDisable(GL_LINE_SMOOTH);
439 static void draw_masklays(Mask *mask, const char draw_flag, const char draw_type,
440 int width, int height)
445 for (masklay = mask->masklayers.first, i = 0; masklay; masklay = masklay->next, i++) {
447 const short is_active = (i == mask->masklay_act);
449 if (masklay->restrictflag & MASK_RESTRICT_VIEW) {
453 for (spline = masklay->splines.first; spline; spline = spline->next) {
455 /* draw curve itself first... */
456 draw_spline_curve(masklay, spline, draw_flag, draw_type, is_active, width, height);
458 // draw_spline_parents(masklay, spline);
460 if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) {
461 /* ...and then handles over the curve so they're nicely visible */
462 draw_spline_points(masklay, spline, draw_flag, draw_type);
465 /* show undeform for testing */
467 void *back = spline->points_deform;
469 spline->points_deform = NULL;
470 draw_spline_curve(masklay, spline, draw_flag, draw_type, is_active, width, height);
471 // draw_spline_parents(masklay, spline);
472 draw_spline_points(masklay, spline, draw_flag, draw_type);
473 spline->points_deform = back;
479 void ED_mask_draw(const bContext *C,
480 const char draw_flag, const char draw_type)
482 ScrArea *sa = CTX_wm_area(C);
484 Mask *mask = CTX_data_edit_mask(C);
490 ED_mask_get_size(sa, &width, &height);
492 draw_masklays(mask, draw_flag, draw_type, width, height);
495 /* sets up the opengl context.
496 * width, height are to match the values from ED_mask_get_size() */
497 void ED_mask_draw_region(Mask *mask, ARegion *ar,
498 const char draw_flag, const char draw_type,
499 const int width_i, const int height_i, /* convert directly into aspect corrected vars */
500 const float aspx, const float aspy,
501 const short do_scale_applied, const short do_post_draw,
502 float stabmat[4][4], /* optional - only used by clip */
503 const bContext *C /* optional - only used when do_post_draw is set */
506 struct View2D *v2d = &ar->v2d;
508 /* aspect always scales vertically in movie and image spaces */
509 const float width = width_i, height = (float)height_i * (aspy / aspx);
519 /* find window pixel coordinates of origin */
520 UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
523 /* w = BLI_RCT_SIZE_X(&v2d->tot); */
524 /* h = BLI_RCT_SIZE_Y(&v2d->tot);/*/
527 zoomx = (float)(BLI_RCT_SIZE_X(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_X(&ar->v2d.cur));
528 zoomy = (float)(BLI_RCT_SIZE_Y(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_Y(&ar->v2d.cur));
530 if (do_scale_applied) {
535 x += v2d->tot.xmin * zoomx;
536 y += v2d->tot.ymin * zoomy;
538 /* frame the image */
539 maxdim = maxf(width, height);
540 if (width == height) {
543 else if (width < height) {
544 xofs = ((height - width) / -2.0f) * zoomx;
547 else { /* (width > height) */
549 yofs = ((width - height) / -2.0f) * zoomy;
552 /* apply transformation so mask editing tools will assume drawing from the origin in normalized space */
554 glTranslatef(x + xofs, y + yofs, 0);
555 glScalef(maxdim * zoomx, maxdim * zoomy, 0);
558 glMultMatrixf(stabmat);
562 draw_masklays(mask, draw_flag, draw_type, width, height);
565 ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
571 void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra, const int efra)
573 const float framelen = ar->winx / (float)(efra - sfra + 1);
575 MaskLayer *masklay = BKE_mask_layer_active(mask);
578 glColor4ub(255, 175, 0, 255);
581 MaskLayerShape *masklay_shape;
583 for (masklay_shape = masklay->splines_shapes.first;
585 masklay_shape = masklay_shape->next)
587 int frame = masklay_shape->frame;
589 /* draw_keyframe(i, CFRA, sfra, framelen, 1); */
590 int height = (frame == cfra) ? 22 : 10;
591 int x = (frame - sfra) * framelen;
593 glVertex2i(x, height);