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