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