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
8
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 */
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 */
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
@ V3D_HIDE_OVERLAYS
@ RV3D_CAMOB
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.
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 Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves 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 Invert a color
#define C
Definition RandGen.cpp:29
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)
#define U
BPy_StructRNA * 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)
void * regiondata
struct bGPdata * gpd
struct MovieClip * clip
struct bGPdata * gpd
struct RenderData r
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)