Blender  V2.93
annotate_draw.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008, Blender Foundation
17  * This is a new part of Blender
18  */
19 
24 #include <float.h>
25 #include <math.h>
26 #include <stddef.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "MEM_guardedalloc.h"
32 
33 #include "BLI_sys_types.h"
34 
35 #include "BLI_listbase.h"
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38 
39 #include "BLF_api.h"
40 #include "BLT_translation.h"
41 
42 #include "DNA_gpencil_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_space_types.h"
47 #include "DNA_userdef_types.h"
48 #include "DNA_view3d_types.h"
49 
50 #include "BKE_context.h"
51 #include "BKE_global.h"
52 #include "BKE_gpencil.h"
53 
54 #include "WM_api.h"
55 
56 #include "GPU_immediate.h"
57 #include "GPU_matrix.h"
58 #include "GPU_state.h"
59 
60 #include "ED_gpencil.h"
61 #include "ED_screen.h"
62 #include "ED_space_api.h"
63 #include "ED_view3d.h"
64 
65 #include "UI_interface_icons.h"
66 #include "UI_resources.h"
67 
68 /* ************************************************** */
69 /* GREASE PENCIL DRAWING */
70 
71 /* ----- General Defines ------ */
72 /* flags for sflag */
73 typedef enum eDrawStrokeFlags {
77  GP_DRAWDATA_ONLY3D = (1 << 1),
79  GP_DRAWDATA_ONLYV2D = (1 << 2),
81  GP_DRAWDATA_ONLYI2D = (1 << 3),
85  GP_DRAWDATA_NO_XRAY = (1 << 5),
89 
90 /* ----- Tool Buffer Drawing ------ */
91 
93  const float *corner_point,
94  const float *arrow_coords,
95  const int arrow_style)
96 {
97  immBeginAtMost(GPU_PRIM_LINE_STRIP, arrow_style);
98 
99  switch (arrow_style) {
101  immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
102  immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
103  break;
105  immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
106  immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
107  immVertex2f(pos, arrow_coords[4], arrow_coords[5]);
108  immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
109  break;
111  immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
112  immVertex2f(pos, corner_point[0], corner_point[1]);
113  immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
114  break;
116  immVertex2f(pos, corner_point[0], corner_point[1]);
117  immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
118  immVertex2f(pos, arrow_coords[4], arrow_coords[5]);
119  immVertex2f(pos, arrow_coords[6], arrow_coords[7]);
120  immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
121  immVertex2f(pos, corner_point[0], corner_point[1]);
122  break;
123  default:
124  break;
125  }
126  immEnd();
127 }
128 
129 /* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */
131  short thickness,
132  short dflag,
133  const float ink[4])
134 {
135  bGPdata_Runtime runtime = gps->runtime;
136  const tGPspoint *points = runtime.sbuffer;
137  int totpoints = runtime.sbuffer_used;
138  short sflag = runtime.sbuffer_sflag;
139 
140  int draw_points = 0;
141 
142  /* error checking */
143  if ((points == NULL) || (totpoints <= 0)) {
144  return;
145  }
146 
147  /* check if buffer can be drawn */
148  if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D)) {
149  return;
150  }
151 
152  if (sflag & GP_STROKE_ERASER) {
153  /* don't draw stroke at all! */
154  return;
155  }
156 
159 
160  const tGPspoint *pt = points;
161 
162  if (totpoints == 1) {
163  /* if drawing a single point, draw it larger */
164  GPU_point_size((float)(thickness + 2) * points->pressure);
166  immUniformColor3fvAlpha(ink, ink[3]);
168  immVertex2fv(pos, &pt->x);
169  }
170  else {
171  float oldpressure = points[0].pressure;
172 
173  /* draw stroke curve */
175 
176  float viewport[4];
177  GPU_viewport_size_get_f(viewport);
178  immUniform2fv("viewportSize", &viewport[2]);
179 
180  immUniform1f("lineWidth", max_ff(oldpressure * thickness, 1.0) * U.pixelsize);
181 
182  immUniformColor3fvAlpha(ink, ink[3]);
183 
185 
186  for (int i = 0; i < totpoints; i++, pt++) {
187  /* If there was a significant pressure change,
188  * stop the curve, change the thickness of the stroke,
189  * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP).
190  */
191  if (fabsf(pt->pressure - oldpressure) > 0.2f) {
192  /* need to have 2 points to avoid immEnd assert error */
193  if (draw_points < 2) {
194  immVertex2fv(pos, &(pt - 1)->x);
195  }
196 
197  immEnd();
198  draw_points = 0;
199 
200  immUniform1f("lineWidth", max_ff(pt->pressure * thickness, 1.0) * U.pixelsize);
201  immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1);
202 
203  /* need to roll-back one point to ensure that there are no gaps in the stroke */
204  if (i != 0) {
205  immVertex2fv(pos, &(pt - 1)->x);
206  draw_points++;
207  }
208 
209  oldpressure = pt->pressure; /* reset our threshold */
210  }
211 
212  /* now the point we want */
213  immVertex2fv(pos, &pt->x);
214  draw_points++;
215  }
216  /* need to have 2 points to avoid immEnd assert error */
217  if (draw_points < 2) {
218  immVertex2fv(pos, &(pt - 1)->x);
219  }
220  }
221 
222  immEnd();
223 
224  /* Draw arrow stroke. */
225  if (totpoints > 1) {
226  /* Draw ending arrow stroke. */
227  if ((sflag & GP_STROKE_USE_ARROW_END) &&
229  float end[2];
230  copy_v2_fl2(end, points[1].x, points[1].y);
232  }
233  /* Draw starting arrow stroke. */
234  if ((sflag & GP_STROKE_USE_ARROW_START) &&
236  float start[2];
237  copy_v2_fl2(start, points[0].x, points[0].y);
239  pos, start, runtime.arrow_start, runtime.arrow_start_style);
240  }
241  }
242 
244 }
245 
246 /* --------- 2D Stroke Drawing Helpers --------- */
247 /* change in parameter list */
249  const float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
250 {
251  if (sflag & GP_STROKE_2DSPACE) {
252  r_co[0] = pt[0];
253  r_co[1] = pt[1];
254  }
255  else if (sflag & GP_STROKE_2DIMAGE) {
256  const float x = (float)((pt[0] * winx) + offsx);
257  const float y = (float)((pt[1] * winy) + offsy);
258 
259  r_co[0] = x;
260  r_co[1] = y;
261  }
262  else {
263  const float x = (float)(pt[0] / 100 * winx) + offsx;
264  const float y = (float)(pt[1] / 100 * winy) + offsy;
265 
266  r_co[0] = x;
267  r_co[1] = y;
268  }
269 }
270 
271 /* ----- Existing Strokes Drawing (3D and Point) ------ */
272 
273 /* draw a given stroke - just a single dot (only one point) */
274 static void annotation_draw_stroke_point(const bGPDspoint *points,
275  short thickness,
276  short sflag,
277  int offsx,
278  int offsy,
279  int winx,
280  int winy,
281  const float ink[4])
282 {
283  const bGPDspoint *pt = points;
284 
285  /* get final position using parent matrix */
286  float fpt[3];
287  copy_v3_v3(fpt, &pt->x);
288 
291 
292  if (sflag & GP_STROKE_3DSPACE) {
294  }
295  else {
297 
298  /* get 2D coordinates of point */
299  float co[3] = {0.0f};
300  annotation_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
301  copy_v3_v3(fpt, co);
302  }
303 
304  /* set color */
305  immUniformColor3fvAlpha(ink, ink[3]);
306 
307  /* set point thickness (since there's only one of these) */
308  immUniform1f("size", (float)(thickness + 2) * pt->pressure);
309 
311  immVertex3fv(pos, fpt);
312  immEnd();
313 
315 }
316 
317 /* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
319  const bGPDspoint *points, int totpoints, short thickness, const float ink[4], bool cyclic)
320 {
321  float curpressure = points[0].pressure;
322  float cyclic_fpt[3];
323  int draw_points = 0;
324 
325  /* if cyclic needs one vertex more */
326  int cyclic_add = 0;
327  if (cyclic) {
328  cyclic_add++;
329  }
330 
333 
335 
336  float viewport[4];
337  GPU_viewport_size_get_f(viewport);
338  immUniform2fv("viewportSize", &viewport[2]);
339 
340  immUniform1f("lineWidth", max_ff(curpressure * thickness, 1.0) * U.pixelsize);
341 
342  immUniformColor3fvAlpha(ink, ink[3]);
343 
344  /* draw stroke curve */
345  immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add);
346  const bGPDspoint *pt = points;
347  for (int i = 0; i < totpoints; i++, pt++) {
348  /* If there was a significant pressure change, stop the curve,
349  * change the thickness of the stroke, and continue drawing again
350  * (since line-width cannot change in middle of GL_LINE_STRIP)
351  * Note: we want more visible levels of pressures when thickness is bigger.
352  */
353  if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
354  /* if the pressure changes before get at least 2 vertices,
355  * need to repeat last point to avoid assert in immEnd() */
356  if (draw_points < 2) {
357  const bGPDspoint *pt2 = pt - 1;
358  immVertex3fv(pos, &pt2->x);
359  }
360  immEnd();
361  draw_points = 0;
362 
363  curpressure = pt->pressure;
364  immUniform1f("lineWidth", max_ff(curpressure * thickness, 1.0) * U.pixelsize);
365  immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1 + cyclic_add);
366 
367  /* need to roll-back one point to ensure that there are no gaps in the stroke */
368  if (i != 0) {
369  const bGPDspoint *pt2 = pt - 1;
370  immVertex3fv(pos, &pt2->x);
371  draw_points++;
372  }
373  }
374 
375  /* now the point we want */
376  immVertex3fv(pos, &pt->x);
377  draw_points++;
378 
379  if (cyclic && i == 0) {
380  /* save first point to use in cyclic */
381  copy_v3_v3(cyclic_fpt, &pt->x);
382  }
383  }
384 
385  if (cyclic) {
386  /* draw line to first point to complete the cycle */
387  immVertex3fv(pos, cyclic_fpt);
388  draw_points++;
389  }
390 
391  /* if less of two points, need to repeat last point to avoid assert in immEnd() */
392  if (draw_points < 2) {
393  const bGPDspoint *pt2 = pt - 1;
394  immVertex3fv(pos, &pt2->x);
395  }
396 
397  immEnd();
399 }
400 
401 /* Draw a given stroke in 2d. */
402 static void annotation_draw_stroke_2d(const bGPDspoint *points,
403  int totpoints,
404  short thickness_s,
405  short sflag,
406  int offsx,
407  int offsy,
408  int winx,
409  int winy,
410  const float ink[4])
411 {
412  if (totpoints == 0) {
413  return;
414  }
415  float thickness = (float)thickness_s;
416 
419 
420  const bGPDspoint *pt;
421  const bGPDspoint *pt_prev;
422  int draw_points = 0;
423  float co[2];
424  float oldpressure = points[0].pressure;
425  if (totpoints == 1) {
426  /* if drawing a single point, draw it larger */
427  GPU_point_size((float)(thickness + 2) * points->pressure);
429  immUniformColor3fvAlpha(ink, ink[3]);
431 
432  annotation_calc_2d_stroke_fxy(&points->x, sflag, offsx, offsy, winx, winy, co);
433  immVertex2fv(pos, co);
434  }
435  else {
436  /* draw stroke curve */
438  immUniformColor3fvAlpha(ink, ink[3]);
439 
440  float viewport[4];
441  GPU_viewport_size_get_f(viewport);
442  immUniform2fv("viewportSize", &viewport[2]);
443 
444  immUniform1f("lineWidth", max_ff(oldpressure * thickness, 1.0) * U.pixelsize);
445 
447 
448  for (int i = 0; i < totpoints; i++) {
449  pt = &points[i];
450  /* If there was a significant pressure change,
451  * stop the curve, change the thickness of the stroke,
452  * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP).
453  */
454  if (fabsf(pt->pressure - oldpressure) > 0.2f) {
455  /* need to have 2 points to avoid immEnd assert error */
456  if (draw_points < 2) {
457  pt_prev = &points[i - 1];
458  annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
459  immVertex2fv(pos, co);
460  }
461 
462  immEnd();
463  draw_points = 0;
464 
465  immUniform1f("lineWidth", max_ff(pt->pressure * thickness, 1.0) * U.pixelsize);
466 
467  immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1);
468 
469  /* need to roll-back one point to ensure that there are no gaps in the stroke */
470  if (i != 0) {
471  pt_prev = &points[i - 1];
472  annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
473  immVertex2fv(pos, co);
474  draw_points++;
475  }
476 
477  oldpressure = pt->pressure; /* reset our threshold */
478  }
479 
480  /* now the point we want */
481  annotation_calc_2d_stroke_fxy(&pt->x, sflag, offsx, offsy, winx, winy, co);
482  immVertex2fv(pos, co);
483  draw_points++;
484  }
485  /* need to have 2 points to avoid immEnd assert error */
486  if (draw_points < 2) {
487  pt_prev = &points[0];
488  annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
489  immVertex2fv(pos, co);
490  }
491  }
492 
493  immEnd();
495 }
496 
497 /* ----- Strokes Drawing ------ */
498 
499 /* Helper for doing all the checks on whether a stroke can be drawn */
500 static bool annotation_can_draw_stroke(const bGPDstroke *gps, const int dflag)
501 {
502  /* skip stroke if it isn't in the right display space for this drawing context */
503  /* 1) 3D Strokes */
504  if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE)) {
505  return false;
506  }
507  if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE)) {
508  return false;
509  }
510 
511  /* 2) Screen Space 2D Strokes */
512  if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE)) {
513  return false;
514  }
515  if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE)) {
516  return false;
517  }
518 
519  /* 3) Image Space (2D) */
520  if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE)) {
521  return false;
522  }
523  if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE)) {
524  return false;
525  }
526 
527  /* skip stroke if it doesn't have any valid data */
528  if ((gps->points == NULL) || (gps->totpoints < 1)) {
529  return false;
530  }
531 
532  /* stroke can be drawn */
533  return true;
534 }
535 
536 /* draw a set of strokes */
537 static void annotation_draw_strokes(const bGPDframe *gpf,
538  int offsx,
539  int offsy,
540  int winx,
541  int winy,
542  int dflag,
543  short lthick,
544  const float color[4])
545 {
547 
548  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
549  /* check if stroke can be drawn */
550  if (annotation_can_draw_stroke(gps, dflag) == false) {
551  continue;
552  }
553 
554  /* check which stroke-drawer to use */
555  if (dflag & GP_DRAWDATA_ONLY3D) {
556  const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
557 
558  if (no_xray) {
560 
561  /* first arg is normally rv3d->dist, but this isn't
562  * available here and seems to work quite well without */
563  GPU_polygon_offset(1.0f, 1.0f);
564  }
565 
566  /* 3D Lines - OpenGL primitives-based */
567  if (gps->totpoints == 1) {
569  gps->points, lthick, gps->flag, offsx, offsy, winx, winy, color);
570  }
571  else {
573  gps->points, gps->totpoints, lthick, color, gps->flag & GP_STROKE_CYCLIC);
574  }
575 
576  if (no_xray) {
578 
579  GPU_polygon_offset(0.0f, 0.0f);
580  }
581  }
582  else {
583  /* 2D Strokes... */
584  if (gps->totpoints == 1) {
586  gps->points, lthick, gps->flag, offsx, offsy, winx, winy, color);
587  }
588  else {
590  gps->points, gps->totpoints, lthick, gps->flag, offsx, offsy, winx, winy, color);
591  }
592  }
593  }
594 
595  GPU_program_point_size(false);
596 }
597 
598 /* ----- General Drawing ------ */
599 /* draw onion-skinning for a layer */
601  bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag)
602 {
603  const float alpha = 1.0f;
604  float color[4];
605 
606  /* 1) Draw Previous Frames First */
607  copy_v3_v3(color, gpl->gcolor_prev);
608 
609  if (gpl->gstep > 0) {
610  bGPDframe *gf;
611  float fac;
612 
613  /* draw previous frames first */
614  for (gf = gpf->prev; gf; gf = gf->prev) {
615  /* check if frame is drawable */
616  if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
617  /* alpha decreases with distance from curframe index */
618  fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
619  color[3] = alpha * fac * 0.66f;
620  annotation_draw_strokes(gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
621  }
622  else {
623  break;
624  }
625  }
626  }
627  else if (gpl->gstep == 0) {
628  /* draw the strokes for the ghost frames (at half of the alpha set by user) */
629  if (gpf->prev) {
630  color[3] = (alpha / 7);
631  annotation_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
632  }
633  }
634  else {
635  /* don't draw - disabled */
636  }
637 
638  /* 2) Now draw next frames */
639  copy_v3_v3(color, gpl->gcolor_next);
640 
641  if (gpl->gstep_next > 0) {
642  bGPDframe *gf;
643  float fac;
644 
645  /* now draw next frames */
646  for (gf = gpf->next; gf; gf = gf->next) {
647  /* check if frame is drawable */
648  if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) {
649  /* alpha decreases with distance from curframe index */
650  fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
651  color[3] = alpha * fac * 0.66f;
652  annotation_draw_strokes(gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
653  }
654  else {
655  break;
656  }
657  }
658  }
659  else if (gpl->gstep_next == 0) {
660  /* draw the strokes for the ghost frames (at half of the alpha set by user) */
661  if (gpf->next) {
662  color[3] = (alpha / 4);
663  annotation_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
664  }
665  }
666  else {
667  /* don't draw - disabled */
668  }
669 }
670 
671 /* loop over gpencil data layers, drawing them */
673  bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
674 {
675  float ink[4];
676 
677  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
678  /* verify never thickness is less than 1 */
679  CLAMP_MIN(gpl->thickness, 1.0f);
680  short lthick = gpl->thickness;
681 
682  /* apply layer opacity */
683  copy_v3_v3(ink, gpl->color);
684  ink[3] = gpl->opacity;
685 
686  /* don't draw layer if hidden */
687  if (gpl->flag & GP_LAYER_HIDE) {
688  continue;
689  }
690 
691  /* get frame to draw */
693  if (gpf == NULL) {
694  continue;
695  }
696 
697  /* Add layer drawing settings to the set of "draw flags"
698  * NOTE: If the setting doesn't apply, it *must* be cleared,
699  * as dflag's carry over from the previous layer
700  */
701 
702  /* xray... */
704 
705  /* Draw 'onionskins' (frame left + right) */
706  if (gpl->onion_flag & GP_LAYER_ONIONSKIN) {
707  annotation_draw_onionskins(gpl, gpf, offsx, offsy, winx, winy, dflag);
708  }
709 
710  /* draw the strokes already in active frame */
711  annotation_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, lthick, ink);
712 
713  /* Check if may need to draw the active stroke cache, only if this layer is the active layer
714  * that is being edited. (Stroke buffer is currently stored in gp-data)
715  */
716  if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
717  (gpf->flag & GP_FRAME_PAINT)) {
718  /* Buffer stroke needs to be drawn with a different linestyle
719  * to help differentiate them from normal strokes.
720  *
721  * It should also be noted that sbuffer contains temporary point types
722  * i.e. tGPspoints NOT bGPDspoints
723  */
724  annotation_draw_stroke_buffer(gpd, lthick, dflag, ink);
725  }
726  }
727 }
728 
729 /* draw grease-pencil datablock */
731  bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
732 {
733  /* turn on smooth lines (i.e. anti-aliasing) */
734  GPU_line_smooth(true);
735 
736  /* turn on alpha-blending */
738 
739  /* Do not write to depth (avoid self-occlusion). */
740  bool prev_depth_mask = GPU_depth_mask_get();
741  GPU_depth_mask(false);
742 
743  /* draw! */
744  annotation_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag);
745 
746  /* turn off alpha blending, then smooth lines */
747  GPU_blend(GPU_BLEND_NONE); /* alpha blending */
748  GPU_line_smooth(false); /* smooth lines */
749 
750  GPU_depth_mask(prev_depth_mask);
751 }
752 
753 /* if we have strokes for scenes (3d view)/clips (movie clip editor)
754  * and objects/tracks, multiple data blocks have to be drawn */
756  bGPdata *gpd,
757  int offsx,
758  int offsy,
759  int winx,
760  int winy,
761  int cfra,
762  int dflag,
763  const char spacetype)
764 {
765  bGPdata *gpd_source = NULL;
766 
767  if (scene) {
768  if (spacetype == SPACE_VIEW3D) {
769  gpd_source = (scene->gpd ? scene->gpd : NULL);
770  }
771  else if (spacetype == SPACE_CLIP && scene->clip) {
772  /* currently drawing only gpencil data from either clip or track,
773  * but not both - XXX fix logic behind */
774  gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL);
775  }
776 
777  if (gpd_source) {
778  annotation_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag);
779  }
780  }
781 
782  /* scene/clip data has already been drawn, only object/track data is drawn here
783  * if gpd_source == gpd, we don't have any object/track data and we can skip */
784  if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) {
785  annotation_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag);
786  }
787 }
788 
789 /* ----- Annotation Sketches Drawing API ------ */
790 
791 /* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */
793 {
796  ARegion *region = CTX_wm_region(C);
798 
799  int offsx, offsy, sizex, sizey;
800  int dflag = GP_DRAWDATA_NOSTATUS;
801 
803  if (gpd == NULL) {
804  return;
805  }
806 
807  /* calculate rect */
808  switch (area->spacetype) {
809  case SPACE_IMAGE: /* image */
810  case SPACE_CLIP: /* clip */
811  {
812  /* just draw using standard scaling (settings here are currently ignored anyways) */
813  /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way,
814  * so disabled. */
815  offsx = 0;
816  offsy = 0;
817  sizex = region->winx;
818  sizey = region->winy;
819 
820  wmOrtho2(
821  region->v2d.cur.xmin, region->v2d.cur.xmax, region->v2d.cur.ymin, region->v2d.cur.ymax);
822 
824  break;
825  }
826  case SPACE_SEQ: /* sequence */
827  {
828  /* just draw using standard scaling (settings here are currently ignored anyways) */
829  offsx = 0;
830  offsy = 0;
831  sizex = region->winx;
832  sizey = region->winy;
833 
834  /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
835  * and everything moved to standard View2d
836  */
837  dflag |= GP_DRAWDATA_ONLYV2D;
838  break;
839  }
840  default: /* for spacetype not yet handled */
841  offsx = 0;
842  offsy = 0;
843  sizex = region->winx;
844  sizey = region->winy;
845 
846  dflag |= GP_DRAWDATA_ONLYI2D;
847  break;
848  }
849 
850  if (ED_screen_animation_playing(wm)) {
851  /* Don't show onion-skins during animation playback/scrub (i.e. it obscures the poses)
852  * OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes). */
853  dflag |= GP_DRAWDATA_NO_ONIONS;
854  }
855 
856  /* draw it! */
857  annotation_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, area->spacetype);
858 }
859 
867 void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
868 {
871  ARegion *region = CTX_wm_region(C);
873  int dflag = 0;
874 
875  /* check that we have grease-pencil stuff to draw */
876  if (area == NULL) {
877  return;
878  }
880  if (gpd == NULL) {
881  return;
882  }
883 
884  /* special hack for Image Editor */
885  /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way,
886  * so disabled. */
887  if (ELEM(area->spacetype, SPACE_IMAGE, SPACE_CLIP)) {
888  dflag |= GP_DRAWDATA_IEDITHACK;
889  }
890 
891  /* draw it! */
892  if (onlyv2d) {
894  }
895  if (ED_screen_animation_playing(wm)) {
896  dflag |= GP_DRAWDATA_NO_ONIONS;
897  }
898 
900  scene, gpd, 0, 0, region->winx, region->winy, CFRA, dflag, area->spacetype);
901 }
902 
903 /* draw annotations sketches to specified 3d-view assuming that matrices are already set
904  * correctly Note: this gets called twice - first time with only3d=true to draw 3d-strokes,
905  * second time with only3d=false for screen-aligned strokes */
907  Scene *scene, struct Depsgraph *depsgraph, View3D *v3d, ARegion *region, bool only3d)
908 {
909  int dflag = 0;
910  RegionView3D *rv3d = region->regiondata;
911  int offsx, offsy, winx, winy;
912 
913  /* check that we have grease-pencil stuff to draw */
914  /* XXX: Hardcoded reference here may get out of sync if we change how we fetch annotation data
915  */
916  bGPdata *gpd = scene->gpd;
917  if (gpd == NULL) {
918  return;
919  }
920 
921  /* when rendering to the offscreen buffer we don't want to
922  * deal with the camera border, otherwise map the coords to the camera border. */
923  if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_FLAG_RENDER_VIEWPORT)) {
924  rctf rectf;
925  ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &rectf, true); /* no shift */
926 
927  offsx = round_fl_to_int(rectf.xmin);
928  offsy = round_fl_to_int(rectf.ymin);
929  winx = round_fl_to_int(rectf.xmax - rectf.xmin);
930  winy = round_fl_to_int(rectf.ymax - rectf.ymin);
931  }
932  else {
933  offsx = 0;
934  offsy = 0;
935  winx = region->winx;
936  winy = region->winy;
937  }
938 
939  /* set flags */
940  if (only3d) {
941  /* 3D strokes/3D space:
942  * - only 3D space points
943  * - don't status text either (as it's the wrong space)
944  */
946  }
947 
948  if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
949  /* don't draw status text when "only render" flag is set */
950  dflag |= GP_DRAWDATA_NOSTATUS;
951  }
952 
953  /* draw it! */
954  annotation_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
955 }
956 
958  Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
959 {
961 
962  annotation_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype);
963 }
964 
965 /* ************************************************** */
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
@ G_FLAG_RENDER_VIEWPORT
Definition: BKE_global.h:110
struct bGPDframe * BKE_gpencil_layer_frame_get(struct bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
Definition: gpencil.c:1307
@ GP_GETFRAME_USE_PREV
Definition: BKE_gpencil.h:187
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
MINLINE int round_fl_to_int(float a)
MINLINE float max_ff(float a, float b)
MINLINE void copy_v2_fl2(float v[2], float x, float y)
MINLINE void copy_v3_v3(float r[3], const float a[3])
unsigned int uint
Definition: BLI_sys_types.h:83
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define CLAMP_MIN(a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
@ GP_STROKE_ARROWSTYLE_NONE
@ GP_STROKE_ARROWSTYLE_SEGMENT
@ GP_STROKE_ARROWSTYLE_CLOSED
@ GP_STROKE_ARROWSTYLE_OPEN
@ GP_STROKE_ARROWSTYLE_SQUARE
@ GP_STROKE_USE_ARROW_END
@ GP_STROKE_2DIMAGE
@ GP_STROKE_ERASER
@ GP_STROKE_CYCLIC
@ GP_STROKE_2DSPACE
@ GP_STROKE_3DSPACE
@ GP_STROKE_USE_ARROW_START
@ GP_LAYER_NO_XRAY
@ GP_LAYER_ACTIVE
@ GP_LAYER_HIDE
@ GP_LAYER_ONIONSKIN
@ GP_FRAME_PAINT
Object is a sort of wrapper for general info.
#define CFRA
@ SPACE_CLIP
@ SPACE_SEQ
@ SPACE_IMAGE
@ SPACE_VIEW3D
#define RV3D_CAMOB
#define V3D_HIDE_OVERLAYS
bScreen * ED_screen_animation_playing(const struct wmWindowManager *wm)
void ED_view3d_calc_camera_border(const struct Scene *scene, struct Depsgraph *depsgraph, const struct ARegion *region, const struct View3D *v3d, const struct RegionView3D *rv3d, struct rctf *r_viewborder, const bool no_shift)
void immUniform2fv(const char *name, const float data[2])
void immUnbindProgram(void)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immVertex2fv(uint attr_id, const float data[2])
void immBeginAtMost(GPUPrimType, uint max_vertex_len)
void immUniform1f(const char *name, float x)
GPUVertFormat * immVertexFormat(void)
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immUniformColor3fvAlpha(const float rgb[3], float a)
void immEnd(void)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
void GPU_polygon_offset(float viewdist, float dist)
Definition: gpu_matrix.cc:758
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:35
@ GPU_PRIM_LINE_STRIP
Definition: GPU_primitive.h:38
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
Definition: GPU_shader.h:223
@ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA
Definition: GPU_shader.h:278
@ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA
Definition: GPU_shader.h:334
void GPU_program_point_size(bool enable)
Definition: gpu_state.cc:191
@ GPU_BLEND_NONE
Definition: GPU_state.h:55
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:57
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:55
void GPU_line_smooth(bool enable)
Definition: gpu_state.cc:85
void GPU_depth_mask(bool depth)
Definition: gpu_state.cc:117
void GPU_point_size(float size)
Definition: gpu_state.cc:179
bool GPU_depth_mask_get(void)
Definition: gpu_state.cc:293
@ GPU_DEPTH_LESS_EQUAL
Definition: GPU_state.h:81
@ GPU_DEPTH_NONE
Definition: GPU_state.h:78
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:75
void GPU_viewport_size_get_f(float coords[4])
Definition: gpu_state.cc:279
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:39
static void annotation_draw_strokes(const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag, short lthick, const float color[4])
eDrawStrokeFlags
Definition: annotate_draw.c:73
@ GP_DRAWDATA_ONLYV2D
Definition: annotate_draw.c:79
@ GP_DRAWDATA_ONLY3D
Definition: annotate_draw.c:77
@ GP_DRAWDATA_NO_ONIONS
Definition: annotate_draw.c:87
@ GP_DRAWDATA_IEDITHACK
Definition: annotate_draw.c:83
@ GP_DRAWDATA_NO_XRAY
Definition: annotate_draw.c:85
@ GP_DRAWDATA_ONLYI2D
Definition: annotate_draw.c:81
@ GP_DRAWDATA_NOSTATUS
Definition: annotate_draw.c:75
void ED_annotation_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
static void annotation_draw_stroke_3d(const bGPDspoint *points, int totpoints, short thickness, const float ink[4], bool cyclic)
static void annotation_draw_data_layers(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
static void annotation_draw_stroke_2d(const bGPDspoint *points, int totpoints, short thickness_s, short sflag, int offsx, int offsy, int winx, int winy, const float ink[4])
void ED_annotation_draw_2dimage(const bContext *C)
static void annotation_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag, const char spacetype)
static void annotation_draw_stroke_buffer(bGPdata *gps, short thickness, short dflag, const float ink[4])
static void annotation_draw_stroke_arrow_buffer(uint pos, const float *corner_point, const float *arrow_coords, const int arrow_style)
Definition: annotate_draw.c:92
static void annotation_draw_onionskins(bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag)
void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
static void annotation_calc_2d_stroke_fxy(const float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
static void annotation_draw_stroke_point(const bGPDspoint *points, short thickness, short sflag, int offsx, int offsy, int winx, int winy, const float ink[4])
void ED_annotation_draw_view3d(Scene *scene, struct Depsgraph *depsgraph, View3D *v3d, ARegion *region, bool only3d)
static void annotation_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
static bool annotation_can_draw_stroke(const bGPDstroke *gps, const int dflag)
unsigned int U
Definition: btGjkEpa3.h:78
Scene scene
const Depsgraph * depsgraph
static CCL_NAMESPACE_BEGIN const double alpha
int ED_gpencil_session_active(void)
Definition: gpencil_undo.c:60
bGPdata * ED_annotation_data_get_active(const bContext *C)
uint pos
#define fabsf(x)
format
Definition: logImageCore.h:47
static void area(int d1, int d2, int e1, int e2, float weights[2])
static void draw_points(ArmatureDrawContext *ctx, const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm, const int boneflag, const short constflag, const int select_id)
void * regiondata
struct bGPdata * gpd
struct MovieClip * clip
struct bGPdata * gpd
char spacetype
struct bGPDframe * next
ListBase strokes
struct bGPDframe * prev
float gcolor_next[3]
float gcolor_prev[3]
bGPDspoint * points
ListBase layers
bGPdata_Runtime runtime
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
float x
Definition: ED_gpencil.h:97
float pressure
Definition: ED_gpencil.h:99
#define G(x, y, z)
void wmOrtho2(float x1, float x2, float y1, float y2)
Definition: wm_subwindow.c:100