Blender  V3.3
annotate_draw.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation. */
3 
8 #include <float.h>
9 #include <math.h>
10 #include <stddef.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include "MEM_guardedalloc.h"
16 
17 #include "BLI_sys_types.h"
18 
19 #include "BLI_listbase.h"
20 #include "BLI_math.h"
21 #include "BLI_utildefines.h"
22 
23 #include "BLF_api.h"
24 #include "BLT_translation.h"
25 
26 #include "DNA_gpencil_types.h"
27 #include "DNA_object_types.h"
28 #include "DNA_scene_types.h"
29 #include "DNA_screen_types.h"
30 #include "DNA_space_types.h"
31 #include "DNA_userdef_types.h"
32 #include "DNA_view3d_types.h"
33 
34 #include "BKE_context.h"
35 #include "BKE_global.h"
36 #include "BKE_gpencil.h"
37 
38 #include "WM_api.h"
39 
40 #include "GPU_immediate.h"
41 #include "GPU_matrix.h"
42 #include "GPU_state.h"
43 
44 #include "ED_gpencil.h"
45 #include "ED_screen.h"
46 #include "ED_space_api.h"
47 #include "ED_view3d.h"
48 
49 #include "UI_interface_icons.h"
50 #include "UI_resources.h"
51 
52 /* ************************************************** */
53 /* GREASE PENCIL DRAWING */
54 
55 /* ----- General Defines ------ */
56 /* flags for sflag */
57 typedef enum eDrawStrokeFlags {
61  GP_DRAWDATA_ONLY3D = (1 << 1),
63  GP_DRAWDATA_ONLYV2D = (1 << 2),
65  GP_DRAWDATA_ONLYI2D = (1 << 3),
69  GP_DRAWDATA_NO_XRAY = (1 << 5),
73 
74 /* ----- Tool Buffer Drawing ------ */
75 
77  const float *corner_point,
78  const float *arrow_coords,
79  const int arrow_style)
80 {
81  immBeginAtMost(GPU_PRIM_LINE_STRIP, arrow_style);
82 
83  switch (arrow_style) {
85  immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
86  immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
87  break;
89  immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
90  immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
91  immVertex2f(pos, arrow_coords[4], arrow_coords[5]);
92  immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
93  break;
95  immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
96  immVertex2f(pos, corner_point[0], corner_point[1]);
97  immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
98  break;
100  immVertex2f(pos, corner_point[0], corner_point[1]);
101  immVertex2f(pos, arrow_coords[0], arrow_coords[1]);
102  immVertex2f(pos, arrow_coords[4], arrow_coords[5]);
103  immVertex2f(pos, arrow_coords[6], arrow_coords[7]);
104  immVertex2f(pos, arrow_coords[2], arrow_coords[3]);
105  immVertex2f(pos, corner_point[0], corner_point[1]);
106  break;
107  default:
108  break;
109  }
110  immEnd();
111 }
112 
117  short thickness,
118  short dflag,
119  const float ink[4])
120 {
121  bGPdata_Runtime runtime = gps->runtime;
122  const tGPspoint *points = runtime.sbuffer;
123  int totpoints = runtime.sbuffer_used;
124  short sflag = runtime.sbuffer_sflag;
125 
126  int draw_points = 0;
127 
128  /* error checking */
129  if ((points == NULL) || (totpoints <= 0)) {
130  return;
131  }
132 
133  /* check if buffer can be drawn */
134  if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D)) {
135  return;
136  }
137 
138  if (sflag & GP_STROKE_ERASER) {
139  /* don't draw stroke at all! */
140  return;
141  }
142 
145 
146  const tGPspoint *pt = points;
147 
148  if (totpoints == 1) {
149  /* if drawing a single point, draw it larger */
150  GPU_point_size((float)(thickness + 2) * points->pressure);
152  immUniformColor3fvAlpha(ink, ink[3]);
154  immVertex2fv(pos, pt->m_xy);
155  }
156  else {
157  float oldpressure = points[0].pressure;
158 
159  /* draw stroke curve */
161 
162  float viewport[4];
163  GPU_viewport_size_get_f(viewport);
164  immUniform2fv("viewportSize", &viewport[2]);
165 
166  immUniform1f("lineWidth", max_ff(oldpressure * thickness, 1.0) * U.pixelsize);
167 
168  immUniformColor3fvAlpha(ink, ink[3]);
169 
171 
172  for (int i = 0; i < totpoints; i++, pt++) {
173  /* If there was a significant pressure change,
174  * stop the curve, change the thickness of the stroke,
175  * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP).
176  */
177  if (fabsf(pt->pressure - oldpressure) > 0.2f) {
178  /* need to have 2 points to avoid immEnd assert error */
179  if (draw_points < 2) {
180  immVertex2fv(pos, (pt - 1)->m_xy);
181  }
182 
183  immEnd();
184  draw_points = 0;
185 
186  immUniform1f("lineWidth", max_ff(pt->pressure * thickness, 1.0) * U.pixelsize);
187  immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1);
188 
189  /* need to roll-back one point to ensure that there are no gaps in the stroke */
190  if (i != 0) {
191  immVertex2fv(pos, (pt - 1)->m_xy);
192  draw_points++;
193  }
194 
195  oldpressure = pt->pressure; /* reset our threshold */
196  }
197 
198  /* now the point we want */
199  immVertex2fv(pos, pt->m_xy);
200  draw_points++;
201  }
202  /* need to have 2 points to avoid immEnd assert error */
203  if (draw_points < 2) {
204  immVertex2fv(pos, (pt - 1)->m_xy);
205  }
206  }
207 
208  immEnd();
209 
210  /* Draw arrow stroke. */
211  if (totpoints > 1) {
212  /* Draw ending arrow stroke. */
213  if ((sflag & GP_STROKE_USE_ARROW_END) &&
215  float end[2];
216  copy_v2_v2(end, points[1].m_xy);
218  }
219  /* Draw starting arrow stroke. */
220  if ((sflag & GP_STROKE_USE_ARROW_START) &&
222  float start[2];
223  copy_v2_v2(start, points[0].m_xy);
225  pos, start, runtime.arrow_start, runtime.arrow_start_style);
226  }
227  }
228 
230 }
231 
232 /* --------- 2D Stroke Drawing Helpers --------- */
233 /* change in parameter list */
235  const float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
236 {
237  if (sflag & GP_STROKE_2DSPACE) {
238  r_co[0] = pt[0];
239  r_co[1] = pt[1];
240  }
241  else if (sflag & GP_STROKE_2DIMAGE) {
242  const float x = (float)((pt[0] * winx) + offsx);
243  const float y = (float)((pt[1] * winy) + offsy);
244 
245  r_co[0] = x;
246  r_co[1] = y;
247  }
248  else {
249  const float x = (float)(pt[0] / 100 * winx) + offsx;
250  const float y = (float)(pt[1] / 100 * winy) + offsy;
251 
252  r_co[0] = x;
253  r_co[1] = y;
254  }
255 }
256 
257 /* ----- Existing Strokes Drawing (3D and Point) ------ */
258 
259 /* draw a given stroke - just a single dot (only one point) */
260 static void annotation_draw_stroke_point(const bGPDspoint *points,
261  short thickness,
262  short sflag,
263  int offsx,
264  int offsy,
265  int winx,
266  int winy,
267  const float ink[4])
268 {
269  const bGPDspoint *pt = points;
270 
271  /* get final position using parent matrix */
272  float fpt[3];
273  copy_v3_v3(fpt, &pt->x);
274 
277 
278  if (sflag & GP_STROKE_3DSPACE) {
280  }
281  else {
283 
284  /* get 2D coordinates of point */
285  float co[3] = {0.0f};
286  annotation_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
287  copy_v3_v3(fpt, co);
288  }
289 
290  /* set color */
291  immUniformColor3fvAlpha(ink, ink[3]);
292 
293  /* set point thickness (since there's only one of these) */
294  immUniform1f("size", (float)(thickness + 2) * pt->pressure);
295 
297  immVertex3fv(pos, fpt);
298  immEnd();
299 
301 }
302 
307  const bGPDspoint *points, int totpoints, short thickness, const float ink[4], bool cyclic)
308 {
309  float curpressure = points[0].pressure;
310  float cyclic_fpt[3];
311  int draw_points = 0;
312 
313  /* if cyclic needs one vertex more */
314  int cyclic_add = 0;
315  if (cyclic) {
316  cyclic_add++;
317  }
318 
321 
323 
324  float viewport[4];
325  GPU_viewport_size_get_f(viewport);
326  immUniform2fv("viewportSize", &viewport[2]);
327 
328  immUniform1f("lineWidth", max_ff(curpressure * thickness, 1.0) * U.pixelsize);
329 
330  immUniformColor3fvAlpha(ink, ink[3]);
331 
332  /* draw stroke curve */
333  immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add);
334  const bGPDspoint *pt = points;
335  for (int i = 0; i < totpoints; i++, pt++) {
336  /* If there was a significant pressure change, stop the curve,
337  * change the thickness of the stroke, and continue drawing again
338  * (since line-width cannot change in middle of GL_LINE_STRIP)
339  * NOTE: we want more visible levels of pressures when thickness is bigger.
340  */
341  if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
342  /* if the pressure changes before get at least 2 vertices,
343  * need to repeat last point to avoid assert in immEnd() */
344  if (draw_points < 2) {
345  const bGPDspoint *pt2 = pt - 1;
346  immVertex3fv(pos, &pt2->x);
347  }
348  immEnd();
349  draw_points = 0;
350 
351  curpressure = pt->pressure;
352  immUniform1f("lineWidth", max_ff(curpressure * thickness, 1.0) * U.pixelsize);
353  immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1 + cyclic_add);
354 
355  /* need to roll-back one point to ensure that there are no gaps in the stroke */
356  if (i != 0) {
357  const bGPDspoint *pt2 = pt - 1;
358  immVertex3fv(pos, &pt2->x);
359  draw_points++;
360  }
361  }
362 
363  /* now the point we want */
364  immVertex3fv(pos, &pt->x);
365  draw_points++;
366 
367  if (cyclic && i == 0) {
368  /* save first point to use in cyclic */
369  copy_v3_v3(cyclic_fpt, &pt->x);
370  }
371  }
372 
373  if (cyclic) {
374  /* draw line to first point to complete the cycle */
375  immVertex3fv(pos, cyclic_fpt);
376  draw_points++;
377  }
378 
379  /* if less of two points, need to repeat last point to avoid assert in immEnd() */
380  if (draw_points < 2) {
381  const bGPDspoint *pt2 = pt - 1;
382  immVertex3fv(pos, &pt2->x);
383  }
384 
385  immEnd();
387 }
388 
389 /* Draw a given stroke in 2d. */
390 static void annotation_draw_stroke_2d(const bGPDspoint *points,
391  int totpoints,
392  short thickness_s,
393  short sflag,
394  int offsx,
395  int offsy,
396  int winx,
397  int winy,
398  const float ink[4])
399 {
400  if (totpoints == 0) {
401  return;
402  }
403  float thickness = (float)thickness_s;
404 
407 
408  const bGPDspoint *pt;
409  const bGPDspoint *pt_prev;
410  int draw_points = 0;
411  float co[2];
412  float oldpressure = points[0].pressure;
413  if (totpoints == 1) {
414  /* if drawing a single point, draw it larger */
415  GPU_point_size((float)(thickness + 2) * points->pressure);
417  immUniformColor3fvAlpha(ink, ink[3]);
419 
420  annotation_calc_2d_stroke_fxy(&points->x, sflag, offsx, offsy, winx, winy, co);
421  immVertex2fv(pos, co);
422  }
423  else {
424  /* draw stroke curve */
426  immUniformColor3fvAlpha(ink, ink[3]);
427 
428  float viewport[4];
429  GPU_viewport_size_get_f(viewport);
430  immUniform2fv("viewportSize", &viewport[2]);
431 
432  immUniform1f("lineWidth", max_ff(oldpressure * thickness, 1.0) * U.pixelsize);
433 
435 
436  for (int i = 0; i < totpoints; i++) {
437  pt = &points[i];
438  /* If there was a significant pressure change,
439  * stop the curve, change the thickness of the stroke,
440  * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP).
441  */
442  if (fabsf(pt->pressure - oldpressure) > 0.2f) {
443  /* need to have 2 points to avoid immEnd assert error */
444  if (draw_points < 2) {
445  pt_prev = &points[i - 1];
446  annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
447  immVertex2fv(pos, co);
448  }
449 
450  immEnd();
451  draw_points = 0;
452 
453  immUniform1f("lineWidth", max_ff(pt->pressure * thickness, 1.0) * U.pixelsize);
454 
455  immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1);
456 
457  /* need to roll-back one point to ensure that there are no gaps in the stroke */
458  if (i != 0) {
459  pt_prev = &points[i - 1];
460  annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
461  immVertex2fv(pos, co);
462  draw_points++;
463  }
464 
465  oldpressure = pt->pressure; /* reset our threshold */
466  }
467 
468  /* now the point we want */
469  annotation_calc_2d_stroke_fxy(&pt->x, sflag, offsx, offsy, winx, winy, co);
470  immVertex2fv(pos, co);
471  draw_points++;
472  }
473  /* need to have 2 points to avoid immEnd assert error */
474  if (draw_points < 2) {
475  pt_prev = &points[0];
476  annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
477  immVertex2fv(pos, co);
478  }
479  }
480 
481  immEnd();
483 }
484 
485 /* ----- Strokes Drawing ------ */
486 
487 /* Helper for doing all the checks on whether a stroke can be drawn */
488 static bool annotation_can_draw_stroke(const bGPDstroke *gps, const int dflag)
489 {
490  /* skip stroke if it isn't in the right display space for this drawing context */
491  /* 1) 3D Strokes */
492  if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE)) {
493  return false;
494  }
495  if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE)) {
496  return false;
497  }
498 
499  /* 2) Screen Space 2D Strokes */
500  if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE)) {
501  return false;
502  }
503  if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE)) {
504  return false;
505  }
506 
507  /* 3) Image Space (2D) */
508  if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE)) {
509  return false;
510  }
511  if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE)) {
512  return false;
513  }
514 
515  /* skip stroke if it doesn't have any valid data */
516  if ((gps->points == NULL) || (gps->totpoints < 1)) {
517  return false;
518  }
519 
520  /* stroke can be drawn */
521  return true;
522 }
523 
524 /* draw a set of strokes */
525 static void annotation_draw_strokes(const bGPDframe *gpf,
526  int offsx,
527  int offsy,
528  int winx,
529  int winy,
530  int dflag,
531  short lthick,
532  const float color[4])
533 {
535 
536  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
537  /* check if stroke can be drawn */
538  if (annotation_can_draw_stroke(gps, dflag) == false) {
539  continue;
540  }
541 
542  /* check which stroke-drawer to use */
543  if (dflag & GP_DRAWDATA_ONLY3D) {
544  const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
545 
546  if (no_xray) {
548 
549  /* first arg is normally rv3d->dist, but this isn't
550  * available here and seems to work quite well without */
551  GPU_polygon_offset(1.0f, 1.0f);
552  }
553 
554  /* 3D Lines - OpenGL primitives-based */
555  if (gps->totpoints == 1) {
557  gps->points, lthick, gps->flag, offsx, offsy, winx, winy, color);
558  }
559  else {
561  gps->points, gps->totpoints, lthick, color, gps->flag & GP_STROKE_CYCLIC);
562  }
563 
564  if (no_xray) {
566 
567  GPU_polygon_offset(0.0f, 0.0f);
568  }
569  }
570  else {
571  /* 2D Strokes... */
572  if (gps->totpoints == 1) {
574  gps->points, lthick, gps->flag, offsx, offsy, winx, winy, color);
575  }
576  else {
578  gps->points, gps->totpoints, lthick, gps->flag, offsx, offsy, winx, winy, color);
579  }
580  }
581  }
582 
583  GPU_program_point_size(false);
584 }
585 
586 /* ----- General Drawing ------ */
587 /* draw onion-skinning for a layer */
589  bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag)
590 {
591  const float alpha = 1.0f;
592  float color[4];
593 
594  /* 1) Draw Previous Frames First */
596 
597  if (gpl->gstep > 0) {
598  bGPDframe *gf;
599  float fac;
600 
601  /* draw previous frames first */
602  for (gf = gpf->prev; gf; gf = gf->prev) {
603  /* check if frame is drawable */
604  if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
605  /* alpha decreases with distance from curframe index */
606  fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
607  color[3] = alpha * fac * 0.66f;
608  annotation_draw_strokes(gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
609  }
610  else {
611  break;
612  }
613  }
614  }
615  else if (gpl->gstep == 0) {
616  /* draw the strokes for the ghost frames (at half of the alpha set by user) */
617  if (gpf->prev) {
618  color[3] = (alpha / 7);
619  annotation_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
620  }
621  }
622  else {
623  /* don't draw - disabled */
624  }
625 
626  /* 2) Now draw next frames */
628 
629  if (gpl->gstep_next > 0) {
630  bGPDframe *gf;
631  float fac;
632 
633  /* now draw next frames */
634  for (gf = gpf->next; gf; gf = gf->next) {
635  /* check if frame is drawable */
636  if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) {
637  /* alpha decreases with distance from curframe index */
638  fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
639  color[3] = alpha * fac * 0.66f;
640  annotation_draw_strokes(gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
641  }
642  else {
643  break;
644  }
645  }
646  }
647  else if (gpl->gstep_next == 0) {
648  /* draw the strokes for the ghost frames (at half of the alpha set by user) */
649  if (gpf->next) {
650  color[3] = (alpha / 4);
651  annotation_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, gpl->thickness, color);
652  }
653  }
654  else {
655  /* don't draw - disabled */
656  }
657 }
658 
659 /* loop over gpencil data layers, drawing them */
661  bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
662 {
663  float ink[4];
664 
665  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
666  /* verify never thickness is less than 1 */
667  CLAMP_MIN(gpl->thickness, 1.0f);
668  short lthick = gpl->thickness;
669 
670  /* apply layer opacity */
671  copy_v3_v3(ink, gpl->color);
672  ink[3] = gpl->opacity;
673 
674  /* don't draw layer if hidden */
675  if (gpl->flag & GP_LAYER_HIDE) {
676  continue;
677  }
678 
679  /* get frame to draw */
681  if (gpf == NULL) {
682  continue;
683  }
684 
685  /* Add layer drawing settings to the set of "draw flags"
686  * NOTE: If the setting doesn't apply, it *must* be cleared,
687  * as dflag's carry over from the previous layer
688  */
689 
690  /* xray... */
692 
693  /* Draw 'onionskins' (frame left + right) */
694  if (gpl->onion_flag & GP_LAYER_ONIONSKIN) {
695  annotation_draw_onionskins(gpl, gpf, offsx, offsy, winx, winy, dflag);
696  }
697 
698  /* draw the strokes already in active frame */
699  annotation_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, lthick, ink);
700 
701  /* Check if may need to draw the active stroke cache, only if this layer is the active layer
702  * that is being edited. (Stroke buffer is currently stored in gp-data)
703  */
704  if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
705  (gpf->flag & GP_FRAME_PAINT)) {
706  /* Buffer stroke needs to be drawn with a different linestyle
707  * to help differentiate them from normal strokes.
708  *
709  * It should also be noted that sbuffer contains temporary point types
710  * i.e. tGPspoints NOT bGPDspoints
711  */
712  annotation_draw_stroke_buffer(gpd, lthick, dflag, ink);
713  }
714  }
715 }
716 
717 /* draw grease-pencil datablock */
719  bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
720 {
721  /* turn on smooth lines (i.e. anti-aliasing) */
722  GPU_line_smooth(true);
723 
724  /* turn on alpha-blending */
726 
727  /* Do not write to depth (avoid self-occlusion). */
728  bool prev_depth_mask = GPU_depth_mask_get();
729  GPU_depth_mask(false);
730 
731  /* draw! */
732  annotation_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag);
733 
734  /* turn off alpha blending, then smooth lines */
735  GPU_blend(GPU_BLEND_NONE); /* alpha blending */
736  GPU_line_smooth(false); /* smooth lines */
737 
738  GPU_depth_mask(prev_depth_mask);
739 }
740 
741 /* if we have strokes for scenes (3d view)/clips (movie clip editor)
742  * and objects/tracks, multiple data blocks have to be drawn */
744  bGPdata *gpd,
745  int offsx,
746  int offsy,
747  int winx,
748  int winy,
749  int cfra,
750  int dflag,
751  const eSpace_Type space_type)
752 {
753  bGPdata *gpd_source = NULL;
754 
755  if (scene) {
756  if (space_type == SPACE_VIEW3D) {
757  gpd_source = (scene->gpd ? scene->gpd : NULL);
758  }
759  else if (space_type == SPACE_CLIP && scene->clip) {
760  /* currently drawing only gpencil data from either clip or track,
761  * but not both - XXX fix logic behind */
762  gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL);
763  }
764 
765  if (gpd_source) {
766  annotation_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag);
767  }
768  }
769 
770  /* scene/clip data has already been drawn, only object/track data is drawn here
771  * if gpd_source == gpd, we don't have any object/track data and we can skip */
772  if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) {
773  annotation_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag);
774  }
775 }
776 
777 /* ----- Annotation Sketches Drawing API ------ */
778 
780 {
783  ARegion *region = CTX_wm_region(C);
785 
786  int offsx, offsy, sizex, sizey;
787  int dflag = GP_DRAWDATA_NOSTATUS;
788 
790  if (gpd == NULL) {
791  return;
792  }
793 
794  /* calculate rect */
795  switch (area->spacetype) {
796  case SPACE_IMAGE: /* image */
797  case SPACE_CLIP: /* clip */
798  {
799  /* just draw using standard scaling (settings here are currently ignored anyways) */
800  /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way,
801  * so disabled. */
802  offsx = 0;
803  offsy = 0;
804  sizex = region->winx;
805  sizey = region->winy;
806 
807  wmOrtho2(
808  region->v2d.cur.xmin, region->v2d.cur.xmax, region->v2d.cur.ymin, region->v2d.cur.ymax);
809 
811  break;
812  }
813  case SPACE_SEQ: /* sequence */
814  {
815  /* just draw using standard scaling (settings here are currently ignored anyways) */
816  offsx = 0;
817  offsy = 0;
818  sizex = region->winx;
819  sizey = region->winy;
820 
821  /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
822  * and everything moved to standard View2d
823  */
824  dflag |= GP_DRAWDATA_ONLYV2D;
825  break;
826  }
827  default: /* for spacetype not yet handled */
828  offsx = 0;
829  offsy = 0;
830  sizex = region->winx;
831  sizey = region->winy;
832 
833  dflag |= GP_DRAWDATA_ONLYI2D;
834  break;
835  }
836 
837  if (ED_screen_animation_playing(wm)) {
838  /* Don't show onion-skins during animation playback/scrub (i.e. it obscures the poses)
839  * OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes). */
840  dflag |= GP_DRAWDATA_NO_ONIONS;
841  }
842 
843  /* draw it! */
845  scene, gpd, offsx, offsy, sizex, sizey, scene->r.cfra, dflag, area->spacetype);
846 }
847 
848 void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
849 {
852  ARegion *region = CTX_wm_region(C);
854  int dflag = 0;
855 
856  /* check that we have grease-pencil stuff to draw */
857  if (area == NULL) {
858  return;
859  }
861  if (gpd == NULL) {
862  return;
863  }
864 
865  /* special hack for Image Editor */
866  /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way,
867  * so disabled. */
868  if (ELEM(area->spacetype, SPACE_IMAGE, SPACE_CLIP)) {
869  dflag |= GP_DRAWDATA_IEDITHACK;
870  }
871 
872  /* draw it! */
873  if (onlyv2d) {
875  }
876  if (ED_screen_animation_playing(wm)) {
877  dflag |= GP_DRAWDATA_NO_ONIONS;
878  }
879 
881  scene, gpd, 0, 0, region->winx, region->winy, scene->r.cfra, dflag, area->spacetype);
882 }
883 
885  Scene *scene, struct Depsgraph *depsgraph, View3D *v3d, ARegion *region, bool only3d)
886 {
887  int dflag = 0;
888  RegionView3D *rv3d = region->regiondata;
889  int offsx, offsy, winx, winy;
890 
891  /* check that we have grease-pencil stuff to draw */
892  /* XXX: Hardcoded reference here may get out of sync if we change how we fetch annotation data
893  */
894  bGPdata *gpd = scene->gpd;
895  if (gpd == NULL) {
896  return;
897  }
898 
899  /* When rendering to the off-screen buffer we don't want to
900  * deal with the camera border, otherwise map the coords to the camera border. */
901  if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_FLAG_RENDER_VIEWPORT)) {
902  rctf rectf;
903  ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &rectf, true); /* no shift */
904 
905  offsx = round_fl_to_int(rectf.xmin);
906  offsy = round_fl_to_int(rectf.ymin);
907  winx = round_fl_to_int(rectf.xmax - rectf.xmin);
908  winy = round_fl_to_int(rectf.ymax - rectf.ymin);
909  }
910  else {
911  offsx = 0;
912  offsy = 0;
913  winx = region->winx;
914  winy = region->winy;
915  }
916 
917  /* set flags */
918  if (only3d) {
919  /* 3D strokes/3D space:
920  * - only 3D space points
921  * - don't status text either (as it's the wrong space)
922  */
924  }
925 
926  if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
927  /* don't draw status text when "only render" flag is set */
928  dflag |= GP_DRAWDATA_NOSTATUS;
929  }
930 
931  /* draw it! */
933  scene, gpd, offsx, offsy, winx, winy, scene->r.cfra, dflag, v3d->spacetype);
934 }
935 
937  Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
938 {
940 
941  annotation_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype);
942 }
943 
944 /* ************************************************** */
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
@ G_FLAG_RENDER_VIEWPORT
Definition: BKE_global.h:148
struct bGPDframe * BKE_gpencil_layer_frame_get(struct bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
Definition: gpencil.c:1232
@ GP_GETFRAME_USE_PREV
Definition: BKE_gpencil.h:338
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
MINLINE int round_fl_to_int(float a)
MINLINE float max_ff(float a, float b)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
unsigned int uint
Definition: BLI_sys_types.h:67
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define CLAMP_MIN(a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ 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.
eSpace_Type
@ 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, 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:721
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:19
@ GPU_PRIM_LINE_STRIP
Definition: GPU_primitive.h:22
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
Definition: GPU_shader.h:253
@ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA
Definition: GPU_shader.h:310
@ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA
Definition: GPU_shader.h:338
void GPU_program_point_size(bool enable)
Definition: gpu_state.cc:172
@ GPU_BLEND_NONE
Definition: GPU_state.h:60
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:62
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:39
void GPU_line_smooth(bool enable)
Definition: gpu_state.cc:75
void GPU_depth_mask(bool depth)
Definition: gpu_state.cc:107
void GPU_point_size(float size)
Definition: gpu_state.cc:164
bool GPU_depth_mask_get(void)
Definition: gpu_state.cc:273
@ GPU_DEPTH_LESS_EQUAL
Definition: GPU_state.h:86
@ GPU_DEPTH_NONE
Definition: GPU_state.h:83
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:65
void GPU_viewport_size_get_f(float coords[4])
Definition: gpu_state.cc:259
@ 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.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
#define C
Definition: RandGen.cpp:25
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:57
@ GP_DRAWDATA_ONLYV2D
Definition: annotate_draw.c:63
@ GP_DRAWDATA_ONLY3D
Definition: annotate_draw.c:61
@ GP_DRAWDATA_NO_ONIONS
Definition: annotate_draw.c:71
@ GP_DRAWDATA_IEDITHACK
Definition: annotate_draw.c:67
@ GP_DRAWDATA_NO_XRAY
Definition: annotate_draw.c:69
@ GP_DRAWDATA_ONLYI2D
Definition: annotate_draw.c:65
@ GP_DRAWDATA_NOSTATUS
Definition: annotate_draw.c:59
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_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:76
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_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag, const eSpace_Type space_type)
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
int ED_gpencil_session_active(void)
Definition: gpencil_undo.c:44
bGPdata * ED_annotation_data_get_active(const bContext *C)
uint pos
format
Definition: logImageCore.h:38
#define G(x, y, z)
#define fabsf(x)
Definition: metal/compat.h:219
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
struct RenderData r
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:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
float pressure
Definition: ED_gpencil.h:83
float m_xy[2]
Definition: ED_gpencil.h:81
void wmOrtho2(float x1, float x2, float y1, float y2)
Definition: wm_subwindow.c:84