Blender  V3.3
gpencil_fill.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2017 Blender Foundation. */
3 
8 #include <stdio.h>
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "BLI_blenlib.h"
13 #include "BLI_ghash.h"
14 #include "BLI_math.h"
15 #include "BLI_stack.h"
16 #include "BLI_utildefines.h"
17 
18 #include "BLT_translation.h"
19 
20 #include "DNA_brush_types.h"
21 #include "DNA_gpencil_types.h"
22 #include "DNA_image_types.h"
23 #include "DNA_material_types.h"
24 #include "DNA_meshdata_types.h"
25 #include "DNA_object_types.h"
27 
28 #include "BKE_brush.h"
29 #include "BKE_context.h"
30 #include "BKE_deform.h"
31 #include "BKE_gpencil.h"
32 #include "BKE_gpencil_geom.h"
33 #include "BKE_image.h"
34 #include "BKE_lib_id.h"
35 #include "BKE_main.h"
36 #include "BKE_material.h"
37 #include "BKE_paint.h"
38 #include "BKE_report.h"
39 #include "BKE_screen.h"
40 
41 #include "ED_gpencil.h"
42 #include "ED_keyframing.h"
43 #include "ED_screen.h"
44 #include "ED_space_api.h"
45 #include "ED_view3d.h"
46 
47 #include "RNA_access.h"
48 #include "RNA_define.h"
49 
50 #include "IMB_imbuf.h"
51 #include "IMB_imbuf_types.h"
52 
53 #include "GPU_framebuffer.h"
54 #include "GPU_immediate.h"
55 #include "GPU_matrix.h"
56 #include "GPU_state.h"
57 
58 #include "UI_interface.h"
59 
60 #include "WM_api.h"
61 #include "WM_types.h"
62 
63 #include "DEG_depsgraph.h"
64 #include "DEG_depsgraph_query.h"
65 
66 #include "gpencil_intern.h"
67 
68 #define LEAK_HORZ 0
69 #define LEAK_VERT 1
70 #define MIN_WINDOW_SIZE 128
71 
72 /* Set to 1 to debug filling internal image. By default, the value must be 0. */
73 #define FILL_DEBUG 0
74 
75 /* Duplicated: etempFlags */
76 enum {
77  GP_DRAWFILLS_NOSTATUS = (1 << 0), /* don't draw status info */
78  GP_DRAWFILLS_ONLY3D = (1 << 1), /* only draw 3d-strokes */
79 };
80 
81 /* Temporary fill operation data `op->customdata`. */
82 typedef struct tGPDfill {
84  struct Main *bmain;
87  struct wmWindow *win;
89  struct Scene *scene;
91  struct Object *ob;
93  struct ScrArea *area;
95  struct RegionView3D *rv3d;
97  struct View3D *v3d;
99  struct ARegion *region;
101  struct bGPdata *gpd;
103  struct Material *mat;
105  struct Brush *brush;
107  struct bGPDlayer *gpl;
109  struct bGPDframe *gpf;
117  short flag;
119  short oldkey;
121  bool on_back;
123  bool is_render;
125  bool done;
127  int mouse[2];
129  int sizex;
131  int sizey;
134 
136  short fill_leak;
143  /* scaling factor */
144  float fill_factor;
145 
146  /* Frame to use. */
148 
152  void *sbuffer;
154  float *depth_arr;
155 
162 
163  /* Temporary size x. */
164  int bwinx;
165  /* Temporary size y. */
166  int bwiny;
168 
169  /* Space Conversion Data */
171 
173  float zoom;
174 
177 
179 
180 bool skip_layer_check(short fill_layer_mode, int gpl_active_index, int gpl_index);
181 static void gpencil_draw_boundary_lines(const struct bContext *UNUSED(C), struct tGPDfill *tgpf);
182 
183 /* Delete any temporary stroke. */
184 static void gpencil_delete_temp_stroke_extension(tGPDfill *tgpf, const bool all_frames)
185 {
186  LISTBASE_FOREACH (bGPDlayer *, gpl, &tgpf->gpd->layers) {
187  if (gpl->flag & GP_LAYER_HIDE) {
188  continue;
189  }
190 
191  bGPDframe *init_gpf = (all_frames) ? gpl->frames.first :
193  gpl, tgpf->active_cfra, GP_GETFRAME_USE_PREV);
194  if (init_gpf == NULL) {
195  continue;
196  }
197  for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
198  LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
199  /* free stroke */
200  if ((gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG)) {
201  BLI_remlink(&gpf->strokes, gps);
203  }
204  }
205  if (!all_frames) {
206  break;
207  }
208  }
209  }
210 }
211 
213  bGPDspoint *b,
214  float length,
215  float r_point[3])
216 {
217  float ab[3];
218  sub_v3_v3v3(ab, &b->x, &a->x);
219  normalize_v3(ab);
220  mul_v3_fl(ab, length);
221  add_v3_v3v3(r_point, &b->x, ab);
222 }
223 
224 /* Loop all layers create stroke extensions. */
226 {
227  Object *ob = tgpf->ob;
228  bGPdata *gpd = tgpf->gpd;
229  Brush *brush = tgpf->brush;
230  BrushGpencilSettings *brush_settings = brush->gpencil_settings;
231 
232  bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
233  BLI_assert(gpl_active != NULL);
234 
235  const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active);
236  BLI_assert(gpl_active_index >= 0);
237 
238  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
239  if (gpl->flag & GP_LAYER_HIDE) {
240  continue;
241  }
242 
243  /* Decide if the strokes of layers are included or not depending on the layer mode. */
244  const int gpl_index = BLI_findindex(&gpd->layers, gpl);
245  bool skip = skip_layer_check(brush_settings->fill_layer_mode, gpl_active_index, gpl_index);
246  if (skip) {
247  continue;
248  }
249 
251  if (gpf == NULL) {
252  continue;
253  }
254 
255  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
256  /* Check if stroke can be drawn. */
257  if ((gps->points == NULL) || (gps->totpoints < 2)) {
258  continue;
259  }
260  if (gps->flag & (GP_STROKE_NOFILL | GP_STROKE_TAG)) {
261  continue;
262  }
263  /* Check if the color is visible. */
264  MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
265  if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE)) {
266  continue;
267  }
268 
269  /* Extend start. */
270  bGPDspoint *pt0 = &gps->points[1];
271  bGPDspoint *pt1 = &gps->points[0];
272  bGPDstroke *gps_new = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness);
273  gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG;
274  BLI_addtail(&gpf->strokes, gps_new);
275 
276  bGPDspoint *pt = &gps_new->points[0];
277  copy_v3_v3(&pt->x, &pt1->x);
278  pt->strength = 1.0f;
279  pt->pressure = 1.0f;
280 
281  pt = &gps_new->points[1];
282  pt->strength = 1.0f;
283  pt->pressure = 1.0f;
284  extrapolate_points_by_length(pt0, pt1, tgpf->fill_extend_fac * 0.1f, &pt->x);
285 
286  /* Extend end. */
287  pt0 = &gps->points[gps->totpoints - 2];
288  pt1 = &gps->points[gps->totpoints - 1];
289  gps_new = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness);
290  gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG;
291  BLI_addtail(&gpf->strokes, gps_new);
292 
293  pt = &gps_new->points[0];
294  copy_v3_v3(&pt->x, &pt1->x);
295  pt->strength = 1.0f;
296  pt->pressure = 1.0f;
297 
298  pt = &gps_new->points[1];
299  pt->strength = 1.0f;
300  pt->pressure = 1.0f;
301  extrapolate_points_by_length(pt0, pt1, tgpf->fill_extend_fac * 0.1f, &pt->x);
302  }
303  }
304 }
305 
306 static void gpencil_update_extend(tGPDfill *tgpf)
307 {
309 
310  if (tgpf->fill_extend_fac > 0.0f) {
312  }
314 }
315 
317 {
318  if (tgpf->is_render) {
319  return true;
320  }
321 
322  const bool show_help = (tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) != 0;
323  const bool show_extend = (tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) != 0;
324  const bool is_extend = (gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG);
325 
326  if ((!show_help) && (show_extend)) {
327  if (!is_extend) {
328  return false;
329  }
330  }
331 
332  if ((show_help) && (!show_extend)) {
333  if (is_extend) {
334  return false;
335  }
336  }
337 
338  return true;
339 }
340 
341 /* draw a given stroke using same thickness and color for all points */
343  bGPDstroke *gps,
344  const float diff_mat[4][4],
345  const bool cyclic,
346  const float ink[4],
347  const int flag,
348  const float thershold,
349  const float thickness)
350 {
351  bGPDspoint *points = gps->points;
352 
353  Material *ma = tgpf->mat;
354  MaterialGPencilStyle *gp_style = ma->gp_style;
355 
356  int totpoints = gps->totpoints;
357  float fpt[3];
358  float col[4];
359  const float extend_col[4] = {0.0f, 1.0f, 1.0f, 1.0f};
360  const bool is_extend = (gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG);
361 
362  if (!gpencil_stroke_is_drawable(tgpf, gps)) {
363  return;
364  }
365 
366  if ((is_extend) && (!tgpf->is_render)) {
367  copy_v4_v4(col, extend_col);
368  }
369  else {
370  copy_v4_v4(col, ink);
371  }
372  /* if cyclic needs more vertex */
373  int cyclic_add = (cyclic) ? 1 : 0;
374 
378 
380 
381  /* draw stroke curve */
382  GPU_line_width((!is_extend) ? thickness : thickness * 2.0f);
383  immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add);
384  const bGPDspoint *pt = points;
385 
386  for (int i = 0; i < totpoints; i++, pt++) {
387 
388  if (flag & GP_BRUSH_FILL_HIDE) {
389  float alpha = gp_style->stroke_rgba[3] * pt->strength;
390  CLAMP(alpha, 0.0f, 1.0f);
391  col[3] = alpha <= thershold ? 0.0f : 1.0f;
392  }
393  else {
394  col[3] = 1.0f;
395  }
396  /* set point */
397  immAttr4fv(color, col);
398  mul_v3_m4v3(fpt, diff_mat, &pt->x);
399  immVertex3fv(pos, fpt);
400  }
401 
402  if (cyclic && totpoints > 2) {
403  /* draw line to first point to complete the cycle */
404  immAttr4fv(color, col);
405  mul_v3_m4v3(fpt, diff_mat, &points->x);
406  immVertex3fv(pos, fpt);
407  }
408 
409  immEnd();
411 }
412 
413 static void draw_mouse_position(tGPDfill *tgpf)
414 {
415  if (tgpf->gps_mouse == NULL) {
416  return;
417  }
418  uchar mouse_color[4] = {0, 0, 255, 255};
419 
420  bGPDspoint *pt = &tgpf->gps_mouse->points[0];
421  float point_size = (tgpf->zoom == 1.0f) ? 4.0f * tgpf->fill_factor :
422  (0.5f * tgpf->zoom) + tgpf->fill_factor;
426 
427  /* Draw mouse click position in Blue. */
429  GPU_point_size(point_size);
431  immAttr4ubv(col, mouse_color);
432  immVertex3fv(pos, &pt->x);
433  immEnd();
435 }
436 
437 /* Helper: Check if must skip the layer */
438 bool skip_layer_check(short fill_layer_mode, int gpl_active_index, int gpl_index)
439 {
440  bool skip = false;
441 
442  switch (fill_layer_mode) {
443  case GP_FILL_GPLMODE_ACTIVE: {
444  if (gpl_index != gpl_active_index) {
445  skip = true;
446  }
447  break;
448  }
449  case GP_FILL_GPLMODE_ABOVE: {
450  if (gpl_index != gpl_active_index + 1) {
451  skip = true;
452  }
453  break;
454  }
455  case GP_FILL_GPLMODE_BELOW: {
456  if (gpl_index != gpl_active_index - 1) {
457  skip = true;
458  }
459  break;
460  }
462  if (gpl_index <= gpl_active_index) {
463  skip = true;
464  }
465  break;
466  }
468  if (gpl_index >= gpl_active_index) {
469  skip = true;
470  }
471  break;
472  }
474  default:
475  break;
476  }
477 
478  return skip;
479 }
480 
481 /* Loop all layers to draw strokes. */
482 static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4])
483 {
484  Object *ob = tgpf->ob;
485  bGPdata *gpd = tgpf->gpd;
486  Brush *brush = tgpf->brush;
487  BrushGpencilSettings *brush_settings = brush->gpencil_settings;
488  ToolSettings *ts = tgpf->scene->toolsettings;
489 
490  tGPDdraw tgpw;
491  tgpw.rv3d = tgpf->rv3d;
492  tgpw.depsgraph = tgpf->depsgraph;
493  tgpw.ob = ob;
494  tgpw.gpd = gpd;
495  tgpw.offsx = 0;
496  tgpw.offsy = 0;
497  tgpw.winx = tgpf->sizex;
498  tgpw.winy = tgpf->sizey;
499  tgpw.dflag = 0;
500  tgpw.disable_fill = 1;
502 
504 
505  bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
506  BLI_assert(gpl_active != NULL);
507 
508  const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active);
509  BLI_assert(gpl_active_index >= 0);
510 
511  /* Draw blue point where click with mouse. */
512  draw_mouse_position(tgpf);
513 
514  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
515  /* do not draw layer if hidden */
516  if (gpl->flag & GP_LAYER_HIDE) {
517  continue;
518  }
519 
520  /* calculate parent position */
522 
523  /* Decide if the strokes of layers are included or not depending on the layer mode.
524  * Cannot skip the layer because it can use boundary strokes and must be used. */
525  const int gpl_index = BLI_findindex(&gpd->layers, gpl);
526  bool skip = skip_layer_check(brush_settings->fill_layer_mode, gpl_active_index, gpl_index);
527 
528  /* if active layer and no keyframe, create a new one */
529  if (gpl == tgpf->gpl) {
530  if ((gpl->actframe == NULL) || (gpl->actframe->framenum != tgpf->active_cfra)) {
531  short add_frame_mode;
532  if (IS_AUTOKEY_ON(tgpf->scene)) {
534  add_frame_mode = GP_GETFRAME_ADD_COPY;
535  }
536  else {
537  add_frame_mode = GP_GETFRAME_ADD_NEW;
538  }
539  }
540  else {
541  add_frame_mode = GP_GETFRAME_USE_PREV;
542  }
543 
544  BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, add_frame_mode);
545  }
546  }
547 
548  /* get frame to draw */
550  if (gpf == NULL) {
551  continue;
552  }
553 
554  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
555  /* check if stroke can be drawn */
556  if ((gps->points == NULL) || (gps->totpoints < 2)) {
557  continue;
558  }
559  /* check if the color is visible */
560  MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
561  if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE)) {
562  continue;
563  }
564 
565  /* If the layer must be skipped, but the stroke is not boundary, skip stroke. */
566  if ((skip) && ((gps->flag & GP_STROKE_NOFILL) == 0)) {
567  continue;
568  }
569 
570  tgpw.gps = gps;
571  tgpw.gpl = gpl;
572  tgpw.gpf = gpf;
573  tgpw.t_gpf = gpf;
574 
575  tgpw.is_fill_stroke = (tgpf->fill_draw_mode == GP_FILL_DMODE_CONTROL) ? false : true;
576  /* Reduce thickness to avoid gaps. */
577  tgpw.lthick = gpl->line_change;
578  tgpw.opacity = 1.0;
579  copy_v4_v4(tgpw.tintcolor, ink);
580  tgpw.onion = true;
581  tgpw.custonion = true;
582 
583  /* Normal strokes. */
585  if (gpencil_stroke_is_drawable(tgpf, gps) && ((gps->flag & GP_STROKE_TAG) == 0)) {
586  ED_gpencil_draw_fill(&tgpw);
587  }
588  }
589 
590  /* 3D Lines with basic shapes and invisible lines */
593  gps,
594  tgpw.diff_mat,
595  gps->flag & GP_STROKE_CYCLIC,
596  ink,
597  tgpf->flag,
598  tgpf->fill_threshold,
599  1.0f);
600  }
601  }
602  }
603 
605 }
606 
607 /* Draw strokes in off-screen buffer. */
609 {
610  bool is_ortho = false;
611  float winmat[4][4];
612 
613  if (!tgpf->gpd) {
614  return false;
615  }
616 
617  /* set temporary new size */
618  tgpf->bwinx = tgpf->region->winx;
619  tgpf->bwiny = tgpf->region->winy;
620  tgpf->brect = tgpf->region->winrct;
621 
622  /* resize region */
623  tgpf->region->winrct.xmin = 0;
624  tgpf->region->winrct.ymin = 0;
625  tgpf->region->winrct.xmax = max_ii((int)tgpf->region->winx * tgpf->fill_factor, MIN_WINDOW_SIZE);
626  tgpf->region->winrct.ymax = max_ii((int)tgpf->region->winy * tgpf->fill_factor, MIN_WINDOW_SIZE);
627  tgpf->region->winx = (short)abs(tgpf->region->winrct.xmax - tgpf->region->winrct.xmin);
628  tgpf->region->winy = (short)abs(tgpf->region->winrct.ymax - tgpf->region->winrct.ymin);
629 
630  /* save new size */
631  tgpf->sizex = (int)tgpf->region->winx;
632  tgpf->sizey = (int)tgpf->region->winy;
633 
634  char err_out[256] = "unknown";
635  GPUOffScreen *offscreen = GPU_offscreen_create(
636  tgpf->sizex, tgpf->sizey, true, GPU_RGBA8, err_out);
637  if (offscreen == NULL) {
638  printf("GPencil - Fill - Unable to create fill buffer\n");
639  return false;
640  }
641 
642  GPU_offscreen_bind(offscreen, true);
643  uint flag = IB_rectfloat;
644  ImBuf *ibuf = IMB_allocImBuf(tgpf->sizex, tgpf->sizey, 32, flag);
645 
646  rctf viewplane;
647  float clip_start, clip_end;
648 
649  is_ortho = ED_view3d_viewplane_get(tgpf->depsgraph,
650  tgpf->v3d,
651  tgpf->rv3d,
652  tgpf->sizex,
653  tgpf->sizey,
654  &viewplane,
655  &clip_start,
656  &clip_end,
657  NULL);
658 
659  /* Rescale `viewplane` to fit all strokes. */
660  float width = viewplane.xmax - viewplane.xmin;
661  float height = viewplane.ymax - viewplane.ymin;
662 
663  float width_new = width * tgpf->zoom;
664  float height_new = height * tgpf->zoom;
665  float scale_x = (width_new - width) / 2.0f;
666  float scale_y = (height_new - height) / 2.0f;
667 
668  viewplane.xmin -= scale_x;
669  viewplane.xmax += scale_x;
670  viewplane.ymin -= scale_y;
671  viewplane.ymax += scale_y;
672 
673  if (is_ortho) {
674  orthographic_m4(winmat,
675  viewplane.xmin,
676  viewplane.xmax,
677  viewplane.ymin,
678  viewplane.ymax,
679  -clip_end,
680  clip_end);
681  }
682  else {
683  perspective_m4(winmat,
684  viewplane.xmin,
685  viewplane.xmax,
686  viewplane.ymin,
687  viewplane.ymax,
688  clip_start,
689  clip_end);
690  }
691 
694  GPU_matrix_push();
696 
697  GPU_depth_mask(true);
698  GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
699  GPU_clear_depth(1.0f);
700 
702  tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->region, NULL, winmat, NULL, true);
703  /* set for opengl */
705  GPU_matrix_set(tgpf->rv3d->viewmat);
706 
707  /* draw strokes */
708  const float ink[4] = {1.0f, 0.0f, 0.0f, 1.0f};
709  gpencil_draw_datablock(tgpf, ink);
710 
711  GPU_depth_mask(false);
712 
714  GPU_matrix_pop();
715 
716  /* create a image to see result of template */
717  if (ibuf->rect_float) {
719  }
720  else if (ibuf->rect) {
721  GPU_offscreen_read_pixels(offscreen, GPU_DATA_UBYTE, ibuf->rect);
722  }
723  if (ibuf->rect_float && ibuf->rect) {
724  IMB_rect_from_float(ibuf);
725  }
726 
727  tgpf->ima = BKE_image_add_from_imbuf(tgpf->bmain, ibuf, "GP_fill");
728  tgpf->ima->id.tag |= LIB_TAG_DOIT;
729 
730  BKE_image_release_ibuf(tgpf->ima, ibuf, NULL);
731 
732  /* Switch back to window-system-provided frame-buffer. */
733  GPU_offscreen_unbind(offscreen, true);
734  GPU_offscreen_free(offscreen);
735 
736  return true;
737 }
738 
739 /* Return pixel data (RGBA) at index. */
740 static void get_pixel(const ImBuf *ibuf, const int idx, float r_col[4])
741 {
742  BLI_assert(ibuf->rect_float != NULL);
743  memcpy(r_col, &ibuf->rect_float[idx * 4], sizeof(float[4]));
744 }
745 
746 /* Set pixel data (RGBA) at index. */
747 static void set_pixel(ImBuf *ibuf, int idx, const float col[4])
748 {
749  BLI_assert(ibuf->rect_float != NULL);
750  float *rrectf = &ibuf->rect_float[idx * 4];
751  copy_v4_v4(rrectf, col);
752 }
753 
754 /* Helper: Check if one image row is empty. */
755 static bool is_row_filled(const ImBuf *ibuf, const int row_index)
756 {
757  float *row = &ibuf->rect_float[ibuf->x * 4 * row_index];
758  return (row[0] == 0.0f && memcmp(row, row + 1, ((ibuf->x * 4) - 1) * sizeof(float)) != 0);
759 }
760 
775 static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index, int type)
776 {
777  float rgba[4];
778  int pt;
779  bool t_a = false;
780  bool t_b = false;
781  const int extreme = limit - 1;
782 
783  /* Horizontal leak (check vertical pixels)
784  * X
785  * X
786  * xB7
787  * X
788  * X
789  */
790  if (type == LEAK_HORZ) {
791  /* pixels on top */
792  pt = index + (ibuf->x * extreme);
793  if (pt <= maxpixel) {
794  get_pixel(ibuf, pt, rgba);
795  if (rgba[0] == 1.0f) {
796  t_a = true;
797  }
798  }
799  else {
800  /* Edge of image. */
801  t_a = true;
802  }
803  /* pixels on bottom */
804  pt = index - (ibuf->x * extreme);
805  if (pt >= 0) {
806  get_pixel(ibuf, pt, rgba);
807  if (rgba[0] == 1.0f) {
808  t_b = true;
809  }
810  }
811  else {
812  /* Edge of image. */
813  t_b = true;
814  }
815  }
816 
817  /* Vertical leak (check horizontal pixels)
818  *
819  * XXXxB7XX
820  */
821  if (type == LEAK_VERT) {
822  /* get pixel range of the row */
823  int row = index / ibuf->x;
824  int lowpix = row * ibuf->x;
825  int higpix = lowpix + ibuf->x - 1;
826 
827  /* pixels to right */
828  pt = index - extreme;
829  if (pt >= lowpix) {
830  get_pixel(ibuf, pt, rgba);
831  if (rgba[0] == 1.0f) {
832  t_a = true;
833  }
834  }
835  else {
836  t_a = true; /* Edge of image. */
837  }
838  /* pixels to left */
839  pt = index + extreme;
840  if (pt <= higpix) {
841  get_pixel(ibuf, pt, rgba);
842  if (rgba[0] == 1.0f) {
843  t_b = true;
844  }
845  }
846  else {
847  t_b = true; /* edge of image */
848  }
849  }
850  return (bool)(t_a && t_b);
851 }
852 
861 {
862  ImBuf *ibuf;
863  float rgba[4];
864  void *lock;
865  const float fill_col[4] = {0.0f, 1.0f, 0.0f, 1.0f};
866  ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
867  const int maxpixel = (ibuf->x * ibuf->y) - 1;
868  bool border_contact = false;
869 
870  BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
871 
872  /* Calculate index of the seed point using the position of the mouse looking
873  * for a blue pixel. */
874  int index = -1;
875  for (int i = 0; i < maxpixel; i++) {
876  get_pixel(ibuf, i, rgba);
877  if (rgba[2] == 1.0f) {
878  index = i;
879  break;
880  }
881  }
882 
883  if ((index >= 0) && (index <= maxpixel)) {
884  if (!FILL_DEBUG) {
885  BLI_stack_push(stack, &index);
886  }
887  }
888 
904  while (!BLI_stack_is_empty(stack)) {
905  int v;
906 
907  BLI_stack_pop(stack, &v);
908 
909  get_pixel(ibuf, v, rgba);
910 
911  /* Determine if the flood contacts with external borders. */
912  if (rgba[3] == 0.5f) {
913  border_contact = true;
914  }
915 
916  /* check if no border(red) or already filled color(green) */
917  if ((rgba[0] != 1.0f) && (rgba[1] != 1.0f)) {
918  /* fill current pixel with green */
919  set_pixel(ibuf, v, fill_col);
920 
921  /* add contact pixels */
922  /* pixel left */
923  if (v - 1 >= 0) {
924  index = v - 1;
925  if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_HORZ)) {
926  BLI_stack_push(stack, &index);
927  }
928  }
929  /* pixel right */
930  if (v + 1 <= maxpixel) {
931  index = v + 1;
932  if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_HORZ)) {
933  BLI_stack_push(stack, &index);
934  }
935  }
936  /* pixel top */
937  if (v + ibuf->x <= maxpixel) {
938  index = v + ibuf->x;
939  if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_VERT)) {
940  BLI_stack_push(stack, &index);
941  }
942  }
943  /* pixel bottom */
944  if (v - ibuf->x >= 0) {
945  index = v - ibuf->x;
946  if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_VERT)) {
947  BLI_stack_push(stack, &index);
948  }
949  }
950  }
951  }
952 
953  /* release ibuf */
954  BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
955 
956  tgpf->ima->id.tag |= LIB_TAG_DOIT;
957  /* free temp stack data */
958  BLI_stack_free(stack);
959 
960  return border_contact;
961 }
962 
963 /* Set a border to create image limits. */
964 static void gpencil_set_borders(tGPDfill *tgpf, const bool transparent)
965 {
966  ImBuf *ibuf;
967  void *lock;
968  const float fill_col[2][4] = {{1.0f, 0.0f, 0.0f, 0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}};
969  ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
970  int idx;
971  int pixel = 0;
972  const int coloridx = transparent ? 0 : 1;
973 
974  /* horizontal lines */
975  for (idx = 0; idx < ibuf->x; idx++) {
976  /* bottom line */
977  set_pixel(ibuf, idx, fill_col[coloridx]);
978  /* top line */
979  pixel = idx + (ibuf->x * (ibuf->y - 1));
980  set_pixel(ibuf, pixel, fill_col[coloridx]);
981  }
982  /* vertical lines */
983  for (idx = 0; idx < ibuf->y; idx++) {
984  /* left line */
985  set_pixel(ibuf, ibuf->x * idx, fill_col[coloridx]);
986  /* right line */
987  pixel = ibuf->x * idx + (ibuf->x - 1);
988  set_pixel(ibuf, pixel, fill_col[coloridx]);
989  }
990 
991  /* release ibuf */
992  BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
993 
994  tgpf->ima->id.tag |= LIB_TAG_DOIT;
995 }
996 
997 /* Invert image to paint inverse area. */
998 static void gpencil_invert_image(tGPDfill *tgpf)
999 {
1000  ImBuf *ibuf;
1001  void *lock;
1002  const float fill_col[3][4] = {
1003  {1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 0.0f}};
1004  ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
1005 
1006  const int maxpixel = (ibuf->x * ibuf->y) - 1;
1007 
1008  for (int v = maxpixel; v != 0; v--) {
1009  float color[4];
1010  get_pixel(ibuf, v, color);
1011  /* Green->Red. */
1012  if (color[1] == 1.0f) {
1013  set_pixel(ibuf, v, fill_col[0]);
1014  }
1015  /* Red->Green */
1016  else if (color[0] == 1.0f) {
1017  set_pixel(ibuf, v, fill_col[1]);
1018  }
1019  else {
1020  /* Set to Transparent. */
1021  set_pixel(ibuf, v, fill_col[2]);
1022  }
1023  }
1024 
1025  /* release ibuf */
1026  BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
1027 
1028  tgpf->ima->id.tag |= LIB_TAG_DOIT;
1029 }
1030 
1031 /* Mark and clear processed areas. */
1033 {
1034  ImBuf *ibuf;
1035  void *lock;
1036  const float blue_col[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1037  const float clear_col[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1038  tGPspoint *point2D;
1039 
1040  if (tgpf->sbuffer_used == 0) {
1041  return;
1042  }
1043 
1044  ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
1045  point2D = (tGPspoint *)tgpf->sbuffer;
1046 
1047  /* First set in blue the perimeter. */
1048  for (int i = 0; i < tgpf->sbuffer_used && point2D; i++, point2D++) {
1049  int image_idx = ibuf->x * (int)point2D->m_xy[1] + (int)point2D->m_xy[0];
1050  set_pixel(ibuf, image_idx, blue_col);
1051  }
1052 
1053  /* Second, clean by lines any pixel between blue pixels. */
1054  float rgba[4];
1055 
1056  for (int idy = 0; idy < ibuf->y; idy++) {
1057  int init = -1;
1058  int end = -1;
1059  for (int idx = 0; idx < ibuf->x; idx++) {
1060  int image_idx = ibuf->x * idy + idx;
1061  get_pixel(ibuf, image_idx, rgba);
1062  /* Blue. */
1063  if (rgba[2] == 1.0f) {
1064  if (init < 0) {
1065  init = image_idx;
1066  }
1067  else {
1068  end = image_idx;
1069  }
1070  }
1071  /* Red. */
1072  else if (rgba[0] == 1.0f) {
1073  if (init > -1) {
1074  for (int i = init; i <= max_ii(init, end); i++) {
1075  set_pixel(ibuf, i, clear_col);
1076  }
1077  init = -1;
1078  end = -1;
1079  }
1080  }
1081  }
1082  /* Check last segment. */
1083  if (init > -1) {
1084  for (int i = init; i <= max_ii(init, end); i++) {
1085  set_pixel(ibuf, i, clear_col);
1086  }
1087  set_pixel(ibuf, init, clear_col);
1088  }
1089  }
1090 
1091  /* release ibuf */
1092  BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
1093 
1094  tgpf->ima->id.tag |= LIB_TAG_DOIT;
1095 }
1096 
1111 static bool dilate_shape(ImBuf *ibuf)
1112 {
1113 #define IS_GREEN (color[1] == 1.0f)
1114 #define IS_NOT_GREEN (color[1] != 1.0f)
1115 
1116  bool done = false;
1117 
1118  BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
1119  const float green[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1120  const int max_size = (ibuf->x * ibuf->y) - 1;
1121  /* detect pixels and expand into red areas */
1122  for (int row = 0; row < ibuf->y; row++) {
1123  if (!is_row_filled(ibuf, row)) {
1124  continue;
1125  }
1126  int maxpixel = (ibuf->x * (row + 1)) - 1;
1127  int minpixel = ibuf->x * row;
1128 
1129  for (int v = maxpixel; v != minpixel; v--) {
1130  float color[4];
1131  int index;
1132  get_pixel(ibuf, v, color);
1133  if (IS_GREEN) {
1134  int tp = 0;
1135  int bm = 0;
1136  int lt = 0;
1137  int rt = 0;
1138 
1139  /* pixel left */
1140  if (v - 1 >= 0) {
1141  index = v - 1;
1142  get_pixel(ibuf, index, color);
1143  if (IS_NOT_GREEN) {
1144  BLI_stack_push(stack, &index);
1145  lt = index;
1146  }
1147  }
1148  /* pixel right */
1149  if (v + 1 <= maxpixel) {
1150  index = v + 1;
1151  get_pixel(ibuf, index, color);
1152  if (IS_NOT_GREEN) {
1153  BLI_stack_push(stack, &index);
1154  rt = index;
1155  }
1156  }
1157  /* pixel top */
1158  if (v + ibuf->x <= max_size) {
1159  index = v + ibuf->x;
1160  get_pixel(ibuf, index, color);
1161  if (IS_NOT_GREEN) {
1162  BLI_stack_push(stack, &index);
1163  tp = index;
1164  }
1165  }
1166  /* pixel bottom */
1167  if (v - ibuf->x >= 0) {
1168  index = v - ibuf->x;
1169  get_pixel(ibuf, index, color);
1170  if (IS_NOT_GREEN) {
1171  BLI_stack_push(stack, &index);
1172  bm = index;
1173  }
1174  }
1175  /* pixel top-left */
1176  if (tp && lt) {
1177  index = tp - 1;
1178  get_pixel(ibuf, index, color);
1179  if (IS_NOT_GREEN) {
1180  BLI_stack_push(stack, &index);
1181  }
1182  }
1183  /* pixel top-right */
1184  if (tp && rt) {
1185  index = tp + 1;
1186  get_pixel(ibuf, index, color);
1187  if (IS_NOT_GREEN) {
1188  BLI_stack_push(stack, &index);
1189  }
1190  }
1191  /* pixel bottom-left */
1192  if (bm && lt) {
1193  index = bm - 1;
1194  get_pixel(ibuf, index, color);
1195  if (IS_NOT_GREEN) {
1196  BLI_stack_push(stack, &index);
1197  }
1198  }
1199  /* pixel bottom-right */
1200  if (bm && rt) {
1201  index = bm + 1;
1202  get_pixel(ibuf, index, color);
1203  if (IS_NOT_GREEN) {
1204  BLI_stack_push(stack, &index);
1205  }
1206  }
1207  }
1208  }
1209  }
1210  /* set dilated pixels */
1211  while (!BLI_stack_is_empty(stack)) {
1212  int v;
1213  BLI_stack_pop(stack, &v);
1214  set_pixel(ibuf, v, green);
1215  done = true;
1216  }
1217  BLI_stack_free(stack);
1218 
1219  return done;
1220 
1221 #undef IS_GREEN
1222 #undef IS_NOT_GREEN
1223 }
1224 
1231 static bool contract_shape(ImBuf *ibuf)
1232 {
1233 #define IS_GREEN (color[1] == 1.0f)
1234 #define IS_NOT_GREEN (color[1] != 1.0f)
1235 
1236  bool done = false;
1237 
1238  BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
1239  const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1240  const int max_size = (ibuf->x * ibuf->y) - 1;
1241 
1242  /* Detect if pixel is near of no green pixels and mark green pixel to be cleared. */
1243  for (int row = 0; row < ibuf->y; row++) {
1244  if (!is_row_filled(ibuf, row)) {
1245  continue;
1246  }
1247  int maxpixel = (ibuf->x * (row + 1)) - 1;
1248  int minpixel = ibuf->x * row;
1249 
1250  for (int v = maxpixel; v != minpixel; v--) {
1251  float color[4];
1252  get_pixel(ibuf, v, color);
1253  if (IS_GREEN) {
1254  /* pixel left */
1255  if (v - 1 >= 0) {
1256  get_pixel(ibuf, v - 1, color);
1257  if (IS_NOT_GREEN) {
1258  BLI_stack_push(stack, &v);
1259  continue;
1260  }
1261  }
1262  /* pixel right */
1263  if (v + 1 <= maxpixel) {
1264  get_pixel(ibuf, v + 1, color);
1265  if (IS_NOT_GREEN) {
1266  BLI_stack_push(stack, &v);
1267  continue;
1268  }
1269  }
1270  /* pixel top */
1271  if (v + ibuf->x <= max_size) {
1272  get_pixel(ibuf, v + ibuf->x, color);
1273  if (IS_NOT_GREEN) {
1274  BLI_stack_push(stack, &v);
1275  continue;
1276  }
1277  }
1278  /* pixel bottom */
1279  if (v - ibuf->x >= 0) {
1280  get_pixel(ibuf, v - ibuf->x, color);
1281  if (IS_NOT_GREEN) {
1282  BLI_stack_push(stack, &v);
1283  continue;
1284  }
1285  }
1286  }
1287  }
1288  }
1289  /* Clear pixels. */
1290  while (!BLI_stack_is_empty(stack)) {
1291  int v;
1292  BLI_stack_pop(stack, &v);
1293  set_pixel(ibuf, v, clear);
1294  done = true;
1295  }
1296  BLI_stack_free(stack);
1297 
1298  return done;
1299 
1300 #undef IS_GREEN
1301 #undef IS_NOT_GREEN
1302 }
1303 
1304 /* Get the outline points of a shape using Moore Neighborhood algorithm
1305  *
1306  * This is a Blender customized version of the general algorithm described
1307  * in https://en.wikipedia.org/wiki/Moore_neighborhood
1308  */
1309 static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate)
1310 {
1311  ImBuf *ibuf;
1312  Brush *brush = tgpf->brush;
1313  float rgba[4];
1314  void *lock;
1315  int v[2];
1316  int boundary_co[2];
1317  int start_co[2];
1318  int first_co[2] = {-1, -1};
1319  int backtracked_co[2];
1320  int current_check_co[2];
1321  int prev_check_co[2];
1322  int backtracked_offset[1][2] = {{0, 0}};
1323  bool first_pixel = false;
1324  bool start_found = false;
1325  const int NEIGHBOR_COUNT = 8;
1326 
1327  const int offset[8][2] = {
1328  {-1, -1},
1329  {0, -1},
1330  {1, -1},
1331  {1, 0},
1332  {1, 1},
1333  {0, 1},
1334  {-1, 1},
1335  {-1, 0},
1336  };
1337 
1338  tgpf->stack = BLI_stack_new(sizeof(int[2]), __func__);
1339 
1340  ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
1341  int imagesize = ibuf->x * ibuf->y;
1342 
1343  /* Dilate or contract. */
1344  if (dilate) {
1345  for (int i = 0; i < abs(brush->gpencil_settings->dilate_pixels); i++) {
1346  if (brush->gpencil_settings->dilate_pixels > 0) {
1347  dilate_shape(ibuf);
1348  }
1349  else {
1350  contract_shape(ibuf);
1351  }
1352  }
1353  }
1354 
1355  for (int idx = imagesize - 1; idx != 0; idx--) {
1356  get_pixel(ibuf, idx, rgba);
1357  if (rgba[1] == 1.0f) {
1358  boundary_co[0] = idx % ibuf->x;
1359  boundary_co[1] = idx / ibuf->x;
1360  copy_v2_v2_int(start_co, boundary_co);
1361  backtracked_co[0] = (idx - 1) % ibuf->x;
1362  backtracked_co[1] = (idx - 1) / ibuf->x;
1363  backtracked_offset[0][0] = backtracked_co[0] - boundary_co[0];
1364  backtracked_offset[0][1] = backtracked_co[1] - boundary_co[1];
1365  copy_v2_v2_int(prev_check_co, start_co);
1366 
1367  BLI_stack_push(tgpf->stack, &boundary_co);
1368  start_found = true;
1369  break;
1370  }
1371  }
1372 
1373  while (start_found) {
1374  int cur_back_offset = -1;
1375  for (int i = 0; i < NEIGHBOR_COUNT; i++) {
1376  if (backtracked_offset[0][0] == offset[i][0] && backtracked_offset[0][1] == offset[i][1]) {
1377  /* Finding the back-tracked pixel offset index */
1378  cur_back_offset = i;
1379  break;
1380  }
1381  }
1382 
1383  int loop = 0;
1384  while (loop < (NEIGHBOR_COUNT - 1) && cur_back_offset != -1) {
1385  int offset_idx = (cur_back_offset + 1) % NEIGHBOR_COUNT;
1386  current_check_co[0] = boundary_co[0] + offset[offset_idx][0];
1387  current_check_co[1] = boundary_co[1] + offset[offset_idx][1];
1388 
1389  int image_idx = ibuf->x * current_check_co[1] + current_check_co[0];
1390  /* Check if the index is inside the image. If the index is outside is
1391  * because the algorithm is unable to find the outline of the figure. This is
1392  * possible for negative filling when click inside a figure instead of
1393  * clicking outside.
1394  * If the index is out of range, finish the filling. */
1395  if (image_idx > imagesize - 1) {
1396  start_found = false;
1397  break;
1398  }
1399  get_pixel(ibuf, image_idx, rgba);
1400 
1401  /* find next boundary pixel */
1402  if (rgba[1] == 1.0f) {
1403  copy_v2_v2_int(boundary_co, current_check_co);
1404  copy_v2_v2_int(backtracked_co, prev_check_co);
1405  backtracked_offset[0][0] = backtracked_co[0] - boundary_co[0];
1406  backtracked_offset[0][1] = backtracked_co[1] - boundary_co[1];
1407 
1408  BLI_stack_push(tgpf->stack, &boundary_co);
1409 
1410  break;
1411  }
1412  copy_v2_v2_int(prev_check_co, current_check_co);
1413  cur_back_offset++;
1414  loop++;
1415  }
1416  /* Current pixel is equal to starting or first pixel. */
1417  if ((boundary_co[0] == start_co[0] && boundary_co[1] == start_co[1]) ||
1418  (boundary_co[0] == first_co[0] && boundary_co[1] == first_co[1])) {
1419  BLI_stack_pop(tgpf->stack, &v);
1420  break;
1421  }
1422 
1423  if (!first_pixel) {
1424  first_pixel = true;
1425  copy_v2_v2_int(first_co, boundary_co);
1426  }
1427  }
1428 
1429  /* release ibuf */
1430  BKE_image_release_ibuf(tgpf->ima, ibuf, lock);
1431 }
1432 
1433 /* Get z-depth array to reproject on surface. */
1435 {
1436  tGPspoint *ptc;
1437  ToolSettings *ts = tgpf->scene->toolsettings;
1438  int totpoints = tgpf->sbuffer_used;
1439  int i = 0;
1440 
1441  if (totpoints == 0) {
1442  return;
1443  }
1444 
1445  /* for surface sketching, need to set the right OpenGL context stuff so that
1446  * the conversions will project the values correctly...
1447  */
1449  /* need to restore the original projection settings before packing up */
1452  tgpf->depsgraph, tgpf->region, tgpf->v3d, NULL, V3D_DEPTH_NO_GPENCIL, &tgpf->depths);
1453 
1454  /* Since strokes are so fine, when using their depth we need a margin
1455  * otherwise they might get missed. */
1456  int depth_margin = 0;
1457 
1458  /* get an array of depths, far depths are blended */
1459  int mval_prev[2] = {0};
1460  int interp_depth = 0;
1461  int found_depth = 0;
1462 
1463  const ViewDepths *depths = tgpf->depths;
1464  tgpf->depth_arr = MEM_mallocN(sizeof(float) * totpoints, "depth_points");
1465 
1466  for (i = 0, ptc = tgpf->sbuffer; i < totpoints; i++, ptc++) {
1467 
1468  int mval_i[2];
1469  round_v2i_v2fl(mval_i, ptc->m_xy);
1470 
1471  if ((ED_view3d_depth_read_cached(depths, mval_i, depth_margin, tgpf->depth_arr + i) == 0) &&
1473  depths, mval_i, mval_prev, depth_margin + 1, tgpf->depth_arr + i) == 0))) {
1474  interp_depth = true;
1475  }
1476  else {
1477  found_depth = true;
1478  }
1479 
1480  copy_v2_v2_int(mval_prev, mval_i);
1481  }
1482 
1483  if (found_depth == false) {
1484  /* Sigh! not much we can do here. Ignore depth in this case. */
1485  for (i = totpoints - 1; i >= 0; i--) {
1486  tgpf->depth_arr[i] = 0.9999f;
1487  }
1488  }
1489  else {
1490  if (interp_depth) {
1491  interp_sparse_array(tgpf->depth_arr, totpoints, DEPTH_INVALID);
1492  }
1493  }
1494  }
1495 }
1496 
1497 /* create array of points using stack as source */
1499 {
1500  tGPspoint *point2D;
1501  int totpoints = BLI_stack_count(tgpf->stack);
1502  if (totpoints == 0) {
1503  return 0;
1504  }
1505 
1506  tgpf->sbuffer_used = (short)totpoints;
1507  tgpf->sbuffer = MEM_callocN(sizeof(tGPspoint) * totpoints, __func__);
1508 
1509  point2D = tgpf->sbuffer;
1510  while (!BLI_stack_is_empty(tgpf->stack)) {
1511  int v[2];
1512  BLI_stack_pop(tgpf->stack, &v);
1513  copy_v2fl_v2i(point2D->m_xy, v);
1514  /* shift points to center of pixel */
1515  add_v2_fl(point2D->m_xy, 0.5f);
1516  point2D->pressure = 1.0f;
1517  point2D->strength = 1.0f;
1518  point2D->time = 0.0f;
1519  point2D++;
1520  }
1521 
1522  return totpoints;
1523 }
1524 
1525 /* create a grease pencil stroke using points in buffer */
1527 {
1528  ToolSettings *ts = tgpf->scene->toolsettings;
1529  const char align_flag = ts->gpencil_v3d_align;
1530  const bool is_depth = (bool)(align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE));
1531  const bool is_lock_axis_view = (bool)(ts->gp_sculpt.lock_axis == 0);
1532  const bool is_camera = is_lock_axis_view && (tgpf->rv3d->persp == RV3D_CAMOB) && (!is_depth);
1533 
1534  Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
1535  if (brush == NULL) {
1536  return;
1537  }
1538 
1539  bGPDspoint *pt;
1540  MDeformVert *dvert = NULL;
1541  tGPspoint *point2D;
1542 
1543  if (tgpf->sbuffer_used == 0) {
1544  return;
1545  }
1546 
1547  /* Set as done. */
1548  tgpf->done = true;
1549 
1550  /* Get frame or create a new one. */
1551  tgpf->gpf = BKE_gpencil_layer_frame_get(tgpf->gpl,
1552  tgpf->active_cfra,
1555 
1556  /* Set frame as selected. */
1557  tgpf->gpf->flag |= GP_FRAME_SELECT;
1558 
1559  /* create new stroke */
1560  bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke");
1561  gps->thickness = brush->size;
1562  gps->fill_opacity_fac = 1.0f;
1563  gps->hardeness = brush->gpencil_settings->hardeness;
1565  gps->inittime = 0.0f;
1566 
1567  /* Apply the vertex color to fill. */
1568  ED_gpencil_fill_vertex_color_set(ts, brush, gps);
1569 
1570  /* the polygon must be closed, so enabled cyclic */
1571  gps->flag |= GP_STROKE_CYCLIC;
1572  gps->flag |= GP_STROKE_3DSPACE;
1573 
1575  if (gps->mat_nr < 0) {
1576  if (tgpf->ob->actcol - 1 < 0) {
1577  gps->mat_nr = 0;
1578  }
1579  else {
1580  gps->mat_nr = tgpf->ob->actcol - 1;
1581  }
1582  }
1583 
1584  /* allocate memory for storage points */
1585  gps->totpoints = tgpf->sbuffer_used;
1586  gps->points = MEM_callocN(sizeof(bGPDspoint) * tgpf->sbuffer_used, "gp_stroke_points");
1587 
1588  /* add stroke to frame */
1589  if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) || (tgpf->on_back == true)) {
1590  BLI_addhead(&tgpf->gpf->strokes, gps);
1591  }
1592  else {
1593  BLI_addtail(&tgpf->gpf->strokes, gps);
1594  }
1595 
1596  /* add points */
1597  pt = gps->points;
1598  point2D = (tGPspoint *)tgpf->sbuffer;
1599 
1600  const int def_nr = tgpf->gpd->vertex_group_active_index - 1;
1601  const bool have_weight = (bool)BLI_findlink(&tgpf->gpd->vertex_group_names, def_nr);
1602 
1603  if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
1605  dvert = gps->dvert;
1606  }
1607 
1608  for (int i = 0; i < tgpf->sbuffer_used && point2D; i++, point2D++, pt++) {
1609  /* convert screen-coordinates to 3D coordinates */
1611  tgpf->region,
1612  tgpf->ob,
1613  point2D,
1614  tgpf->depth_arr ? tgpf->depth_arr + i : NULL,
1615  &pt->x);
1616 
1617  pt->pressure = 1.0f;
1618  pt->strength = 1.0f;
1619  pt->time = 0.0f;
1620 
1621  /* Apply the vertex color to point. */
1622  ED_gpencil_point_vertex_color_set(ts, brush, pt, NULL);
1623 
1624  if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
1625  MDeformWeight *dw = BKE_defvert_ensure_index(dvert, def_nr);
1626  if (dw) {
1627  dw->weight = ts->vgroup_weight;
1628  }
1629 
1630  dvert++;
1631  }
1632  else {
1633  if (dvert != NULL) {
1634  dvert->totweight = 0;
1635  dvert->dw = NULL;
1636  dvert++;
1637  }
1638  }
1639  }
1640 
1641  /* Smooth stroke. No copy of the stroke since there only a minor improvement here. */
1642  for (int i = 0; i < gps->totpoints; i++) {
1643  BKE_gpencil_stroke_smooth_point(gps, i, 1.0f, 2, false, true, gps);
1644  }
1645 
1646  /* if axis locked, reproject to plane locked */
1647  if ((tgpf->lock_axis > GP_LOCKAXIS_VIEW) &&
1648  ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) == 0)) {
1649  float origin[3];
1650  ED_gpencil_drawing_reference_get(tgpf->scene, tgpf->ob, ts->gpencil_v3d_align, origin);
1652  tgpf->scene, tgpf->ob, tgpf->rv3d, tgpf->gpl, gps, origin, tgpf->lock_axis - 1);
1653  }
1654 
1655  /* if parented change position relative to parent object */
1656  for (int a = 0; a < tgpf->sbuffer_used; a++) {
1657  pt = &gps->points[a];
1658  gpencil_apply_parent_point(tgpf->depsgraph, tgpf->ob, tgpf->gpl, pt);
1659  }
1660 
1661  /* If camera view or view projection, reproject flat to view to avoid perspective effect. */
1662  if ((!is_depth) && (((align_flag & GP_PROJECT_VIEWSPACE) && is_lock_axis_view) || (is_camera))) {
1663  ED_gpencil_project_stroke_to_view(tgpf->C, tgpf->gpl, gps);
1664  }
1665 
1666  /* simplify stroke */
1667  for (int b = 0; b < tgpf->fill_simplylvl; b++) {
1669  }
1670 
1671  /* Calc geometry data. */
1673 }
1674 
1675 /* ----------------------- */
1676 /* Drawing */
1677 /* Helper: Draw status message while the user is running the operator */
1679 {
1680  const char *status_str = TIP_("Fill: ESC/RMB cancel, LMB Fill, Shift Draw on Back");
1681  ED_workspace_status_text(C, status_str);
1682 }
1683 
1684 /* draw boundary lines to see fill limits */
1686 {
1687  if (!tgpf->gpd) {
1688  return;
1689  }
1690  const float ink[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1691  gpencil_draw_datablock(tgpf, ink);
1692 }
1693 
1694 /* Drawing callback for modal operator in 3d mode */
1695 static void gpencil_fill_draw_3d(const bContext *C, ARegion *UNUSED(region), void *arg)
1696 {
1697  tGPDfill *tgpf = (tGPDfill *)arg;
1698  /* Draw only in the region that originated operator. This is required for multi-window. */
1699  ARegion *region = CTX_wm_region(C);
1700  if (region != tgpf->region) {
1701  return;
1702  }
1704 }
1705 
1706 /* check if context is suitable for filling */
1708 {
1709  Object *obact = CTX_data_active_object(C);
1710 
1711  if (ED_operator_regionactive(C)) {
1712  ScrArea *area = CTX_wm_area(C);
1713  if (area->spacetype == SPACE_VIEW3D) {
1714  if ((obact == NULL) || (obact->type != OB_GPENCIL) ||
1715  (obact->mode != OB_MODE_PAINT_GPENCIL)) {
1716  return false;
1717  }
1718 
1719  return true;
1720  }
1721  CTX_wm_operator_poll_msg_set(C, "Active region not valid for filling operator");
1722  return false;
1723  }
1724 
1725  CTX_wm_operator_poll_msg_set(C, "Active region not set");
1726  return false;
1727 }
1728 
1729 /* Allocate memory and initialize values */
1731 {
1732  tGPDfill *tgpf = MEM_callocN(sizeof(tGPDfill), "GPencil Fill Data");
1733 
1734  /* define initial values */
1737  Main *bmain = CTX_data_main(C);
1739 
1740  /* set current scene and window info */
1741  tgpf->C = C;
1742  tgpf->bmain = CTX_data_main(C);
1743  tgpf->scene = scene;
1744  tgpf->ob = CTX_data_active_object(C);
1745  tgpf->area = CTX_wm_area(C);
1746  tgpf->region = CTX_wm_region(C);
1747  tgpf->rv3d = tgpf->region->regiondata;
1748  tgpf->v3d = tgpf->area->spacedata.first;
1750  tgpf->win = CTX_wm_window(C);
1751  tgpf->active_cfra = scene->r.cfra;
1752  tgpf->reports = op->reports;
1753 
1754  /* Setup space conversions. */
1756  tgpf->zoom = 1.0f;
1757 
1758  /* set GP datablock */
1759  tgpf->gpd = gpd;
1760  tgpf->gpl = BKE_gpencil_layer_active_get(gpd);
1761  if (tgpf->gpl == NULL) {
1762  tgpf->gpl = BKE_gpencil_layer_addnew(tgpf->gpd, DATA_("GP_Layer"), true, false);
1763  }
1764 
1765  tgpf->lock_axis = ts->gp_sculpt.lock_axis;
1766 
1767  tgpf->oldkey = -1;
1768  tgpf->is_render = false;
1769  tgpf->sbuffer_used = 0;
1770  tgpf->sbuffer = NULL;
1771  tgpf->depth_arr = NULL;
1772 
1773  /* save filling parameters */
1774  Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
1775  tgpf->brush = brush;
1776  tgpf->flag = brush->gpencil_settings->flag;
1783  tgpf->fill_leak = (int)ceil((float)brush->gpencil_settings->fill_leak * tgpf->fill_factor);
1784 
1785  int totcol = tgpf->ob->totcol;
1786 
1787  /* get color info */
1789  bmain, tgpf->ob, brush);
1790 
1791  tgpf->mat = ma;
1792 
1793  /* Untag strokes to be sure nothing is pending due any canceled process. */
1794  LISTBASE_FOREACH (bGPDlayer *, gpl, &tgpf->gpd->layers) {
1795  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1796  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
1797  gps->flag &= ~GP_STROKE_TAG;
1798  }
1799  }
1800  }
1801 
1802  /* check whether the material was newly added */
1803  if (totcol != tgpf->ob->totcol) {
1805  }
1806 
1807  /* init undo */
1808  gpencil_undo_init(tgpf->gpd);
1809 
1810  /* return context data for running operator */
1811  return tgpf;
1812 }
1813 
1814 /* end operator */
1816 {
1818 
1819  /* clear undo stack */
1821 
1822  /* restore cursor to indicate end of fill */
1824 
1825  tGPDfill *tgpf = op->customdata;
1826 
1827  /* don't assume that operator data exists at all */
1828  if (tgpf) {
1829  /* clear status message area */
1831 
1832  MEM_SAFE_FREE(tgpf->sbuffer);
1833  MEM_SAFE_FREE(tgpf->depth_arr);
1834 
1835  /* Remove any temp stroke. */
1837 
1838  /* remove drawing handler */
1839  if (tgpf->draw_handle_3d) {
1841  }
1842 
1843  /* Remove depth buffer in cache. */
1844  if (tgpf->depths) {
1846  }
1847 
1848  /* finally, free memory used by temp data */
1849  MEM_freeN(tgpf);
1850  }
1851 
1852  /* clear pointer */
1853  op->customdata = NULL;
1854 
1855  /* drawing batch cache is dirty now */
1856  if ((ob) && (ob->type == OB_GPENCIL) && (ob->data)) {
1857  bGPdata *gpd2 = ob->data;
1859  gpd2->flag |= GP_DATA_CACHE_IS_DIRTY;
1860  }
1861 
1863 }
1864 
1866 {
1867  /* this is just a wrapper around exit() */
1868  gpencil_fill_exit(C, op);
1869 }
1870 
1871 /* Init: Allocate memory and set init values */
1873 {
1874  tGPDfill *tgpf;
1875  /* cannot paint in locked layer */
1878  if ((gpl) && (gpl->flag & GP_LAYER_LOCKED)) {
1879  return 0;
1880  }
1881 
1882  /* check context */
1883  tgpf = op->customdata = gpencil_session_init_fill(C, op);
1884  if (tgpf == NULL) {
1885  /* something wasn't set correctly in context */
1886  gpencil_fill_exit(C, op);
1887  return 0;
1888  }
1889 
1890  /* everything is now setup ok */
1891  return 1;
1892 }
1893 
1894 /* start of interactive part of operator */
1895 static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1896 {
1899  Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
1900  tGPDfill *tgpf = NULL;
1901 
1902  /* Fill tool needs a material (cannot use default material) */
1903  bool valid = true;
1904  if ((brush) && (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
1905  if (brush->gpencil_settings->material == NULL) {
1906  valid = false;
1907  }
1908  }
1909  else {
1910  if (BKE_object_material_get(ob, ob->actcol) == NULL) {
1911  valid = false;
1912  }
1913  }
1914  if (!valid) {
1915  BKE_report(op->reports, RPT_ERROR, "Fill tool needs active material");
1916  return OPERATOR_CANCELLED;
1917  }
1918 
1919  /* try to initialize context data needed */
1920  if (!gpencil_fill_init(C, op)) {
1921  gpencil_fill_exit(C, op);
1922  if (op->customdata) {
1923  MEM_freeN(op->customdata);
1924  }
1925  return OPERATOR_CANCELLED;
1926  }
1927 
1928  tgpf = op->customdata;
1929 
1930  /* Enable custom drawing handlers to show help lines */
1931  const bool do_extend = (tgpf->fill_extend_fac > 0.0f);
1932  const bool help_lines = ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) ||
1933  ((tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) && (do_extend)));
1934 
1935  if (help_lines) {
1938  }
1939 
1941 
1943 
1946 
1947  /* Add a modal handler for this operator. */
1949 
1950  return OPERATOR_RUNNING_MODAL;
1951 }
1952 
1953 /* Helper: Calc the maximum bounding box size of strokes to get the zoom level of the viewport.
1954  * For each stroke, the 2D projected bounding box is calculated and using this data, the total
1955  * object bounding box (all strokes) is calculated. */
1957 {
1958  Brush *brush = tgpf->brush;
1960  tgpf->zoom = 1.0f;
1961  return;
1962  }
1963 
1964  Object *ob = tgpf->ob;
1965  bGPdata *gpd = tgpf->gpd;
1966  BrushGpencilSettings *brush_settings = tgpf->brush->gpencil_settings;
1967  bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
1968  BLI_assert(gpl_active != NULL);
1969 
1970  const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active);
1971  BLI_assert(gpl_active_index >= 0);
1972 
1973  /* Init maximum boundbox size. */
1974  rctf rect_max;
1975  const float winx_half = tgpf->region->winx / 2.0f;
1976  const float winy_half = tgpf->region->winy / 2.0f;
1977  BLI_rctf_init(&rect_max,
1978  0.0f - winx_half,
1979  tgpf->region->winx + winx_half,
1980  0.0f - winy_half,
1981  tgpf->region->winy + winy_half);
1982 
1983  float objectbox_min[2], objectbox_max[2];
1984  INIT_MINMAX2(objectbox_min, objectbox_max);
1985  rctf rect_bound;
1986  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1987  if (gpl->flag & GP_LAYER_HIDE) {
1988  continue;
1989  }
1990  float diff_mat[4][4];
1991  /* calculate parent matrix */
1992  BKE_gpencil_layer_transform_matrix_get(tgpf->depsgraph, ob, gpl, diff_mat);
1993 
1994  /* Decide if the strokes of layers are included or not depending on the layer mode.
1995  * Cannot skip the layer because it can use boundary strokes and must be used. */
1996  const int gpl_index = BLI_findindex(&gpd->layers, gpl);
1997  bool skip = skip_layer_check(brush_settings->fill_layer_mode, gpl_active_index, gpl_index);
1998 
1999  /* Get frame to check. */
2001  if (gpf == NULL) {
2002  continue;
2003  }
2004 
2005  /* Read all strokes. */
2006  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2007  /* check if stroke can be drawn */
2008  if ((gps->points == NULL) || (gps->totpoints < 2)) {
2009  continue;
2010  }
2011  /* check if the color is visible */
2012  MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
2013  if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE)) {
2014  continue;
2015  }
2016 
2017  /* If the layer must be skipped, but the stroke is not boundary, skip stroke. */
2018  if ((skip) && ((gps->flag & GP_STROKE_NOFILL) == 0)) {
2019  continue;
2020  }
2021 
2022  float boundbox_min[2];
2023  float boundbox_max[2];
2024  ED_gpencil_projected_2d_bound_box(&tgpf->gsc, gps, diff_mat, boundbox_min, boundbox_max);
2025  minmax_v2v2_v2(objectbox_min, objectbox_max, boundbox_min);
2026  minmax_v2v2_v2(objectbox_min, objectbox_max, boundbox_max);
2027  }
2028  }
2029  /* Clamp max bound box. */
2030  BLI_rctf_init(
2031  &rect_bound, objectbox_min[0], objectbox_max[0], objectbox_min[1], objectbox_max[1]);
2032  float r_xy[2];
2033  BLI_rctf_clamp(&rect_bound, &rect_max, r_xy);
2034 
2035  /* Calculate total width used. */
2036  float width = tgpf->region->winx;
2037  if (rect_bound.xmin < 0.0f) {
2038  width -= rect_bound.xmin;
2039  }
2040  if (rect_bound.xmax > tgpf->region->winx) {
2041  width += rect_bound.xmax - tgpf->region->winx;
2042  }
2043  /* Calculate total height used. */
2044  float height = tgpf->region->winy;
2045  if (rect_bound.ymin < 0.0f) {
2046  height -= rect_bound.ymin;
2047  }
2048  if (rect_bound.ymax > tgpf->region->winy) {
2049  height += rect_bound.ymax - tgpf->region->winy;
2050  }
2051 
2052  width = ceilf(width);
2053  height = ceilf(height);
2054 
2055  float zoomx = (width > tgpf->region->winx) ? width / (float)tgpf->region->winx : 1.0f;
2056  float zoomy = (height > tgpf->region->winy) ? height / (float)tgpf->region->winy : 1.0f;
2057  if ((zoomx != 1.0f) || (zoomy != 1.0f)) {
2058  tgpf->zoom = min_ff(max_ff(zoomx, zoomy) * 1.5f, 5.0f);
2059  }
2060 }
2061 
2063 {
2064  ImBuf *ibuf;
2065  void *lock;
2066  const float blue_col[4] = {0.0f, 0.0f, 1.0f, 1.0f};
2067  ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
2068  const int maxpixel = (ibuf->x * ibuf->y) - 1;
2069  float rgba[4];
2070  for (int i = 0; i < maxpixel; i++) {
2071  get_pixel(ibuf, i, rgba);
2072  if (rgba[3] == 0.0f) {
2073  set_pixel(ibuf, i, blue_col);
2074  BKE_image_release_ibuf(tgpf->ima, ibuf, NULL);
2075  return true;
2076  }
2077  }
2078 
2079  BKE_image_release_ibuf(tgpf->ima, ibuf, NULL);
2080  return false;
2081 }
2082 
2083 static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted)
2084 {
2085  wmWindow *win = CTX_wm_window(tgpf->C);
2086 
2087  /* render screen to temp image */
2088  int totpoints = 1;
2089  if (gpencil_render_offscreen(tgpf)) {
2090 
2091  /* Set red borders to create a external limit. */
2092  gpencil_set_borders(tgpf, true);
2093 
2094  /* apply boundary fill */
2095  const bool border_contact = gpencil_boundaryfill_area(tgpf);
2096 
2097  /* Fill only if it never comes in contact with an edge. It is better not to fill than
2098  * to fill the entire area, as this is confusing for the artist. */
2099  if ((!border_contact) || (is_inverted)) {
2100  /* Invert direction if press Ctrl. */
2101  if (is_inverted) {
2102  gpencil_invert_image(tgpf);
2103  while (gpencil_find_and_mark_empty_areas(tgpf)) {
2105  }
2106  }
2107 
2108  /* Clean borders to avoid infinite loops. */
2109  gpencil_set_borders(tgpf, false);
2110  WM_cursor_time(win, 50);
2111  int totpoints_prv = 0;
2112  int loop_limit = 0;
2113  while (totpoints > 0) {
2114  /* Analyze outline. */
2115  gpencil_get_outline_points(tgpf, (totpoints == 1) ? true : false);
2116 
2117  /* Create array of points from stack. */
2118  totpoints = gpencil_points_from_stack(tgpf);
2119  if (totpoints > 0) {
2120  /* Create z-depth array for reproject. */
2122 
2123  /* Create stroke and reproject. */
2125  }
2126  if (is_inverted) {
2128  }
2129  else {
2130  /* Exit of the loop. */
2131  totpoints = 0;
2132  }
2133 
2134  /* free temp stack data */
2135  if (tgpf->stack) {
2136  BLI_stack_free(tgpf->stack);
2137  }
2138  WM_cursor_time(win, 100);
2139 
2140  /* Free memory. */
2141  MEM_SAFE_FREE(tgpf->sbuffer);
2142  MEM_SAFE_FREE(tgpf->depth_arr);
2143 
2144  /* Limit very small areas. */
2145  if (totpoints < 3) {
2146  break;
2147  }
2148  /* Limit infinite loops is some corner cases. */
2149  if (totpoints_prv == totpoints) {
2150  loop_limit++;
2151  if (loop_limit > 3) {
2152  break;
2153  }
2154  }
2155  totpoints_prv = totpoints;
2156  }
2157  }
2158  else {
2159  BKE_report(tgpf->reports, RPT_INFO, "Unable to fill unclosed areas");
2160  }
2161 
2162  /* Delete temp image. */
2163  if ((tgpf->ima) && (!FILL_DEBUG)) {
2164  BKE_id_free(tgpf->bmain, tgpf->ima);
2165  }
2166 
2167  return true;
2168  }
2169 
2170  return false;
2171 }
2172 
2173 /* events handling during interactive part of operator */
2174 static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
2175 {
2176  tGPDfill *tgpf = op->customdata;
2177  Brush *brush = tgpf->brush;
2178  BrushGpencilSettings *brush_settings = brush->gpencil_settings;
2179  tgpf->on_back = RNA_boolean_get(op->ptr, "on_back");
2180 
2181  const bool is_brush_inv = brush_settings->fill_direction == BRUSH_DIR_IN;
2182  const bool is_inverted = (is_brush_inv && (event->modifier & KM_CTRL) == 0) ||
2183  (!is_brush_inv && (event->modifier & KM_CTRL) != 0);
2184  const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(tgpf->gpd);
2185  const bool do_extend = (tgpf->fill_extend_fac > 0.0f);
2186  const bool help_lines = ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) ||
2187  ((tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) && (do_extend)));
2188  int estate = OPERATOR_RUNNING_MODAL;
2189 
2190  switch (event->type) {
2191  case EVT_ESCKEY:
2192  case RIGHTMOUSE:
2193  estate = OPERATOR_CANCELLED;
2194  break;
2195  case LEFTMOUSE:
2196  if (!IS_AUTOKEY_ON(tgpf->scene) && (!is_multiedit) && (tgpf->gpl->actframe == NULL)) {
2197  BKE_report(op->reports, RPT_INFO, "No available frame for creating stroke");
2198  estate = OPERATOR_CANCELLED;
2199  break;
2200  }
2201 
2202  /* first time the event is not enabled to show help lines. */
2203  if ((tgpf->oldkey != -1) || (!help_lines)) {
2205  if (region) {
2206  bool in_bounds = false;
2207  /* Perform bounds check */
2208  in_bounds = BLI_rcti_isect_pt_v(&region->winrct, event->xy);
2209 
2210  if ((in_bounds) && (region->regiontype == RGN_TYPE_WINDOW)) {
2211  tgpf->mouse[0] = event->mval[0];
2212  tgpf->mouse[1] = event->mval[1];
2213  tgpf->is_render = true;
2214  /* Define Zoom level. */
2215  gpencil_zoom_level_set(tgpf);
2216 
2217  /* Create Temp stroke. */
2218  tgpf->gps_mouse = BKE_gpencil_stroke_new(0, 1, 10.0f);
2219  tGPspoint point2D;
2220  bGPDspoint *pt = &tgpf->gps_mouse->points[0];
2221  copy_v2fl_v2i(point2D.m_xy, tgpf->mouse);
2223  tgpf->scene, tgpf->region, tgpf->ob, &point2D, NULL, &pt->x);
2224 
2225  /* Hash of selected frames. */
2226  GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64);
2227 
2228  /* If not multi-frame and there is no frame in scene->r.cfra for the active layer,
2229  * create a new frame. */
2230  if (!is_multiedit) {
2232  tgpf->gpl,
2233  tgpf->active_cfra,
2235  tgpf->gpf->flag |= GP_FRAME_SELECT;
2236 
2238  frame_list, POINTER_FROM_INT(tgpf->active_cfra), tgpf->gpl->actframe);
2239  }
2240  else {
2241  BKE_gpencil_frame_selected_hash(tgpf->gpd, frame_list);
2242  }
2243 
2244  /* Loop all frames. */
2245  wmWindow *win = CTX_wm_window(C);
2246 
2247  GHashIterator gh_iter;
2248  int total = BLI_ghash_len(frame_list);
2249  int i = 1;
2250  GHASH_ITER (gh_iter, frame_list) {
2251  /* Set active frame as current for filling. */
2253  int step = ((float)i / (float)total) * 100.0f;
2254  WM_cursor_time(win, step);
2255 
2256  if (do_extend) {
2257  gpencil_update_extend(tgpf);
2258  }
2259 
2260  /* Repeat loop until get something. */
2261  tgpf->done = false;
2262  int loop_limit = 0;
2263  while ((!tgpf->done) && (loop_limit < 2)) {
2264  WM_cursor_time(win, loop_limit + 1);
2265  /* Render screen to temp image and do fill. */
2266  gpencil_do_frame_fill(tgpf, is_inverted);
2267 
2268  /* restore size */
2269  tgpf->region->winx = (short)tgpf->bwinx;
2270  tgpf->region->winy = (short)tgpf->bwiny;
2271  tgpf->region->winrct = tgpf->brect;
2272  if (!tgpf->done) {
2273  /* If the zoom was not set before, avoid a loop. */
2274  if (tgpf->zoom == 1.0f) {
2275  loop_limit++;
2276  }
2277  else {
2278  tgpf->zoom = 1.0f;
2279  tgpf->fill_factor = max_ff(
2282  }
2283  }
2284  loop_limit++;
2285  }
2286 
2287  if (do_extend) {
2289  }
2290 
2291  i++;
2292  }
2294  /* Free hash table. */
2295  BLI_ghash_free(frame_list, NULL, NULL);
2296 
2297  /* Free temp stroke. */
2299 
2300  /* push undo data */
2301  gpencil_undo_push(tgpf->gpd);
2302 
2303  /* Save extend value for next operation. */
2304  brush_settings->fill_extend_fac = tgpf->fill_extend_fac;
2305 
2306  estate = OPERATOR_FINISHED;
2307  }
2308  else {
2309  estate = OPERATOR_CANCELLED;
2310  }
2311  }
2312  else {
2313  estate = OPERATOR_CANCELLED;
2314  }
2315  }
2316  else if (do_extend) {
2317  gpencil_update_extend(tgpf);
2318  }
2319  tgpf->oldkey = event->type;
2320  break;
2321  case EVT_PAGEUPKEY:
2322  case WHEELUPMOUSE:
2323  if (tgpf->oldkey == 1) {
2324  tgpf->fill_extend_fac -= (event->modifier & KM_SHIFT) ? 0.01f : 0.1f;
2325  CLAMP_MIN(tgpf->fill_extend_fac, 0.0f);
2326  gpencil_update_extend(tgpf);
2327  }
2328  break;
2329  case EVT_PAGEDOWNKEY:
2330  case WHEELDOWNMOUSE:
2331  if (tgpf->oldkey == 1) {
2332  tgpf->fill_extend_fac += (event->modifier & KM_SHIFT) ? 0.01f : 0.1f;
2333  CLAMP_MAX(tgpf->fill_extend_fac, 100.0f);
2334  gpencil_update_extend(tgpf);
2335  }
2336  break;
2337  default:
2338  break;
2339  }
2340  /* process last operations before exiting */
2341  switch (estate) {
2342  case OPERATOR_FINISHED:
2343  gpencil_fill_exit(C, op);
2345  break;
2346 
2347  case OPERATOR_CANCELLED:
2348  gpencil_fill_exit(C, op);
2349  break;
2350 
2351  default:
2352  break;
2353  }
2354 
2355  /* return status code */
2356  return estate;
2357 }
2358 
2360 {
2361  PropertyRNA *prop;
2362 
2363  /* identifiers */
2364  ot->name = "Grease Pencil Fill";
2365  ot->idname = "GPENCIL_OT_fill";
2366  ot->description = "Fill with color the shape formed by strokes";
2367 
2368  /* api callbacks */
2373 
2374  /* flags */
2376 
2377  prop = RNA_def_boolean(ot->srna, "on_back", false, "Draw on Back", "Send new stroke to back");
2379 }
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 bGPdata * CTX_data_gpencil_data(const bContext *C)
Definition: context.c:1445
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
void CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg)
Definition: context.c:1042
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct ToolSettings * CTX_data_tool_settings(const bContext *C)
Definition: context.c:1282
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
support for deformation groups and hooks.
struct MDeformWeight * BKE_defvert_ensure_index(struct MDeformVert *dv, int defgroup)
Definition: deform.c:748
struct bGPDlayer * BKE_gpencil_layer_active_get(struct bGPdata *gpd)
Definition: gpencil.c:1558
struct bGPDlayer * BKE_gpencil_layer_addnew(struct bGPdata *gpd, const char *name, bool setactive, bool add_to_header)
Definition: gpencil.c:621
void BKE_gpencil_dvert_ensure(struct bGPDstroke *gps)
Definition: gpencil.c:1891
struct Material * BKE_gpencil_object_material_ensure_from_active_input_brush(struct Main *bmain, struct Object *ob, struct Brush *brush)
Definition: gpencil.c:1780
struct bGPDstroke * BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
Definition: gpencil.c:756
void BKE_gpencil_free_stroke(struct bGPDstroke *gps)
Definition: gpencil.c:391
struct bGPDframe * BKE_gpencil_layer_frame_get(struct bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
Definition: gpencil.c:1232
int BKE_gpencil_object_material_get_index_from_brush(struct Object *ob, struct Brush *brush)
Definition: gpencil.c:1759
void BKE_gpencil_layer_transform_matrix_get(const struct Depsgraph *depsgraph, struct Object *obact, struct bGPDlayer *gpl, float diff_mat[4][4])
void BKE_gpencil_frame_selected_hash(struct bGPdata *gpd, struct GHash *r_list)
Definition: gpencil.c:2869
@ GP_GETFRAME_ADD_NEW
Definition: BKE_gpencil.h:341
@ GP_GETFRAME_ADD_COPY
Definition: BKE_gpencil.h:343
@ GP_GETFRAME_USE_PREV
Definition: BKE_gpencil.h:338
void BKE_gpencil_stroke_geometry_update(struct bGPdata *gpd, struct bGPDstroke *gps)
void BKE_gpencil_stroke_simplify_fixed(struct bGPdata *gpd, struct bGPDstroke *gps)
bool BKE_gpencil_stroke_smooth_point(struct bGPDstroke *gps, int point_index, float influence, int iterations, bool smooth_caps, bool keep_shape, struct bGPDstroke *r_gps)
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
struct Image * BKE_image_add_from_imbuf(struct Main *bmain, struct ImBuf *ibuf, const char *name)
void BKE_id_free(struct Main *bmain, void *idv)
General operations, lookup, etc. for materials.
struct MaterialGPencilStyle * BKE_gpencil_material_settings(struct Object *ob, short act)
Definition: material.c:805
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
struct Brush * BKE_paint_brush(struct Paint *paint)
Definition: paint.c:607
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
struct ARegion * BKE_area_find_region_xy(struct ScrArea *area, int regiontype, const int xy[2]) ATTR_NONNULL(3)
Definition: screen.c:898
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:298
GHash * BLI_ghash_int_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
#define GHASH_ITER(gh_iter_, ghash_)
Definition: BLI_ghash.h:321
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:705
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:710
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
void orthographic_m4(float mat[4][4], float left, float right, float bottom, float top, float nearClip, float farClip)
Definition: math_geom.c:4517
void perspective_m4(float mat[4][4], float left, float right, float bottom, float top, float nearClip, float farClip)
Definition: math_geom.c:4542
int interp_sparse_array(float *array, int list_size, float skipval)
Definition: math_geom.c:3917
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
MINLINE void round_v2i_v2fl(int r[2], const float a[2])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v2fl_v2i(float r[2], const int a[2])
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v2_v2_int(int r[2], const int a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
Definition: math_vector.c:890
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void add_v2_fl(float r[2], float f)
bool BLI_rcti_isect_pt_v(const struct rcti *rect, const int xy[2])
bool BLI_rctf_clamp(struct rctf *rect, const struct rctf *rect_bounds, float r_xy[2])
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition: rct.c:407
void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL()
Definition: stack.c:135
size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:225
void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL()
Definition: stack.c:129
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:247
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
Definition: stack.c:94
#define BLI_stack_new(esize, descr)
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define INIT_MINMAX2(min, max)
#define CLAMP_MAX(a, c)
#define POINTER_FROM_INT(i)
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define ELEM(...)
#define CLAMP_MIN(a, b)
#define TIP_(msgid)
#define DATA_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
@ GP_FILL_DMODE_STROKE
@ GP_FILL_DMODE_CONTROL
@ GP_FILL_DMODE_BOTH
@ GP_BRUSH_FILL_SHOW_HELPLINES
@ GP_BRUSH_FILL_HIDE
@ GP_BRUSH_MATERIAL_PINNED
@ GP_BRUSH_FILL_SHOW_EXTENDLINES
@ GP_BRUSH_FILL_FIT_DISABLE
@ BRUSH_DIR_IN
@ GP_FILL_GPLMODE_ABOVE
@ GP_FILL_GPLMODE_ALL_ABOVE
@ GP_FILL_GPLMODE_VISIBLE
@ GP_FILL_GPLMODE_ALL_BELOW
@ GP_FILL_GPLMODE_BELOW
@ GP_FILL_GPLMODE_ACTIVE
#define GPENCIL_MIN_FILL_FAC
@ GP_STROKE_NOFILL
@ GP_STROKE_TAG
@ GP_STROKE_CYCLIC
@ GP_STROKE_3DSPACE
#define GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)
@ GP_LAYER_LOCKED
@ GP_LAYER_HIDE
#define GPENCIL_MAX_FILL_FAC
@ GP_FRAME_SELECT
@ GP_DATA_CACHE_IS_DIRTY
@ GP_MATERIAL_HIDE
@ OB_MODE_PAINT_GPENCIL
Object is a sort of wrapper for general info.
@ OB_GPENCIL
@ GP_LOCKAXIS_VIEW
@ GP_PROJECT_VIEWSPACE
@ GP_PROJECT_DEPTH_VIEW
@ GP_PROJECT_DEPTH_STROKE
@ GP_TOOL_FLAG_RETAIN_LAST
@ GP_TOOL_FLAG_PAINT_ONBACK
@ GP_TOOL_FLAG_CREATE_WEIGHTS
@ RGN_TYPE_WINDOW
#define RGN_TYPE_ANY
@ SPACE_VIEW3D
#define RV3D_CAMOB
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
#define IS_AUTOKEY_ON(scene)
bool ED_operator_regionactive(struct bContext *C)
Definition: screen_ops.c:91
void ED_workspace_status_text(struct bContext *C, const char *str)
Definition: area.c:816
#define REGION_DRAW_POST_VIEW
Definition: ED_space_api.h:62
void * ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *customdata, int type)
Definition: spacetypes.c:226
bool ED_region_draw_cb_exit(struct ARegionType *art, void *handle)
Definition: spacetypes.c:241
bool ED_view3d_depth_read_cached(const ViewDepths *vd, const int mval[2], int margin, float *r_depth)
bool ED_view3d_viewplane_get(struct Depsgraph *depsgraph, const struct View3D *v3d, const struct RegionView3D *rv3d, int winxi, int winyi, struct rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize)
bool ED_view3d_depth_read_cached_seg(const ViewDepths *vd, const int mval_sta[2], const int mval_end[2], int margin, float *depth)
void ED_view3d_update_viewmat(struct Depsgraph *depsgraph, const struct Scene *scene, struct View3D *v3d, struct ARegion *region, const float viewmat[4][4], const float winmat[4][4], const struct rcti *rect, bool offscreen)
void ED_view3d_depths_free(ViewDepths *depths)
Definition: view3d_draw.c:2366
@ V3D_DEPTH_NO_GPENCIL
Definition: ED_view3d.h:182
void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *region)
void ED_view3d_depth_override(struct Depsgraph *depsgraph, struct ARegion *region, struct View3D *v3d, struct Object *obact, eV3DDepthOverrideMode mode, struct ViewDepths **r_depths)
Definition: view3d_draw.c:2294
void immAttr4fv(uint attr_id, const float data[4])
void immAttr4ubv(uint attr_id, const unsigned char data[4])
void immUnbindProgram(void)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immBeginAtMost(GPUPrimType, uint max_vertex_len)
GPUVertFormat * immVertexFormat(void)
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_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 type
_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 GLsizei width
_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 green
void GPU_matrix_pop(void)
Definition: gpu_matrix.cc:126
void GPU_matrix_identity_projection_set(void)
Definition: gpu_matrix.cc:154
void GPU_matrix_pop_projection(void)
Definition: gpu_matrix.cc:140
#define GPU_matrix_set(x)
Definition: GPU_matrix.h:225
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:119
#define GPU_matrix_projection_set(x)
Definition: GPU_matrix.h:226
void GPU_matrix_identity_set(void)
Definition: gpu_matrix.cc:168
void GPU_matrix_push_projection(void)
Definition: gpu_matrix.cc:133
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:19
@ GPU_PRIM_LINE_STRIP
Definition: GPU_primitive.h:22
@ GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR
Definition: GPU_shader.h:329
@ GPU_SHADER_3D_FLAT_COLOR
Definition: GPU_shader.h:238
@ 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_width(float width)
Definition: gpu_state.cc:158
void GPU_depth_mask(bool depth)
Definition: gpu_state.cc:107
void GPU_point_size(float size)
Definition: gpu_state.cc:164
@ GPU_DATA_UBYTE
Definition: GPU_texture.h:174
@ GPU_DATA_FLOAT
Definition: GPU_texture.h:171
@ GPU_RGBA8
Definition: GPU_texture.h:87
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ GPU_COMP_U8
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:500
void IMB_rect_from_float(struct ImBuf *ibuf)
Definition: divers.c:696
Contains defines and structs used throughout the imbuf module.
@ IB_rectfloat
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
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
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
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
#define C
Definition: RandGen.cpp:25
@ OPTYPE_BLOCKING
Definition: WM_types.h:150
@ OPTYPE_UNDO
Definition: WM_types.h:148
#define ND_SPACE_PROPERTIES
Definition: WM_types.h:472
#define NA_EDITED
Definition: WM_types.h:523
#define NC_GPENCIL
Definition: WM_types.h:349
@ KM_CTRL
Definition: WM_types.h:239
@ KM_SHIFT
Definition: WM_types.h:238
#define NC_SPACE
Definition: WM_types.h:342
#define DEPTH_INVALID
volatile int lock
ATTR_WARN_UNUSED_RESULT BMesh * bm
ATTR_WARN_UNUSED_RESULT const BMVert * v
Scene scene
void ED_gpencil_draw_fill(tGPDdraw *tgpw)
Definition: drawgpencil.c:410
static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
static void gpencil_zoom_level_set(tGPDfill *tgpf)
static bool is_row_filled(const ImBuf *ibuf, const int row_index)
Definition: gpencil_fill.c:755
static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index, int type)
Definition: gpencil_fill.c:775
static void gpencil_fill_status_indicators(bContext *C)
void GPENCIL_OT_fill(wmOperatorType *ot)
static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted)
static bool gpencil_stroke_is_drawable(tGPDfill *tgpf, bGPDstroke *gps)
Definition: gpencil_fill.c:316
static bool gpencil_find_and_mark_empty_areas(tGPDfill *tgpf)
static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4])
Definition: gpencil_fill.c:482
static int gpencil_fill_init(bContext *C, wmOperator *op)
static void gpencil_draw_boundary_lines(const struct bContext *UNUSED(C), struct tGPDfill *tgpf)
static bool gpencil_boundaryfill_area(tGPDfill *tgpf)
Definition: gpencil_fill.c:860
#define LEAK_VERT
Definition: gpencil_fill.c:69
#define FILL_DEBUG
Definition: gpencil_fill.c:73
static void gpencil_draw_basic_stroke(tGPDfill *tgpf, bGPDstroke *gps, const float diff_mat[4][4], const bool cyclic, const float ink[4], const int flag, const float thershold, const float thickness)
Definition: gpencil_fill.c:342
bool skip_layer_check(short fill_layer_mode, int gpl_active_index, int gpl_index)
Definition: gpencil_fill.c:438
static void get_pixel(const ImBuf *ibuf, const int idx, float r_col[4])
Definition: gpencil_fill.c:740
static void gpencil_fill_exit(bContext *C, wmOperator *op)
static void gpencil_invert_image(tGPDfill *tgpf)
Definition: gpencil_fill.c:998
static void set_pixel(ImBuf *ibuf, int idx, const float col[4])
Definition: gpencil_fill.c:747
struct tGPDfill tGPDfill
static void gpencil_update_extend(tGPDfill *tgpf)
Definition: gpencil_fill.c:306
static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
static bool gpencil_fill_poll(bContext *C)
static void gpencil_fill_draw_3d(const bContext *C, ARegion *UNUSED(region), void *arg)
static void gpencil_fill_cancel(bContext *C, wmOperator *op)
static void gpencil_erase_processed_area(tGPDfill *tgpf)
#define IS_NOT_GREEN
static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate)
#define LEAK_HORZ
Definition: gpencil_fill.c:68
static tGPDfill * gpencil_session_init_fill(bContext *C, wmOperator *op)
#define MIN_WINDOW_SIZE
Definition: gpencil_fill.c:70
static bool contract_shape(ImBuf *ibuf)
@ GP_DRAWFILLS_ONLY3D
Definition: gpencil_fill.c:78
@ GP_DRAWFILLS_NOSTATUS
Definition: gpencil_fill.c:77
static void draw_mouse_position(tGPDfill *tgpf)
Definition: gpencil_fill.c:413
static int gpencil_points_from_stack(tGPDfill *tgpf)
static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
static bool dilate_shape(ImBuf *ibuf)
static bool gpencil_render_offscreen(tGPDfill *tgpf)
Definition: gpencil_fill.c:608
static void gpencil_get_depth_array(tGPDfill *tgpf)
static void gpencil_create_extensions(tGPDfill *tgpf)
Definition: gpencil_fill.c:225
static void gpencil_delete_temp_stroke_extension(tGPDfill *tgpf, const bool all_frames)
Definition: gpencil_fill.c:184
#define IS_GREEN
static void gpencil_set_borders(tGPDfill *tgpf, const bool transparent)
Definition: gpencil_fill.c:964
static void extrapolate_points_by_length(bGPDspoint *a, bGPDspoint *b, float length, float r_point[3])
Definition: gpencil_fill.c:212
void gpencil_undo_init(struct bGPdata *gpd)
Definition: gpencil_undo.c:97
void gpencil_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc)
void gpencil_apply_parent_point(struct Depsgraph *depsgraph, struct Object *obact, bGPDlayer *gpl, bGPDspoint *pt)
void gpencil_undo_push(struct bGPdata *gpd)
Definition: gpencil_undo.c:113
void gpencil_undo_finish(void)
Definition: gpencil_undo.c:164
void gpencil_stroke_convertcoords_tpoint(struct Scene *scene, struct ARegion *region, struct Object *ob, const struct tGPspoint *point2D, float *depth, float r_out[3])
void ED_gpencil_projected_2d_bound_box(const GP_SpaceConversion *gsc, const bGPDstroke *gps, const float diff_mat[4][4], float r_min[2], float r_max[2])
void ED_gpencil_project_stroke_to_plane(const Scene *scene, const Object *ob, const RegionView3D *rv3d, bGPDlayer *gpl, bGPDstroke *gps, const float origin[3], const int axis)
void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *gps)
void ED_gpencil_fill_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDstroke *gps)
void ED_gpencil_point_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDspoint *pt, tGPspoint *tpt)
void ED_gpencil_drawing_reference_get(const Scene *scene, const Object *ob, char align_flag, float r_vec[3])
uint pos
uint col
void GPU_offscreen_free(GPUOffScreen *ofs)
void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
GPUOffScreen * GPU_offscreen_create(int width, int height, bool depth, eGPUTextureFormat format, char err_out[256])
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, eGPUDataFormat format, void *pixels)
void GPU_clear_color(float red, float green, float blue, float alpha)
void GPU_clear_depth(float depth)
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
format
Definition: logImageCore.h:38
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
ccl_device_inline float3 ceil(const float3 &a)
Definition: math_float3.h:363
#define ceilf(x)
Definition: metal/compat.h:225
static void clear(Message *msg)
Definition: msgfmt.c:278
static unsigned a[3]
Definition: RandGen.cpp:78
static void area(int d1, int d2, int e1, int e2, float weights[2])
T length(const vec_base< T, Size > &a)
T abs(const T &a)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken rgba("rgba", pxr::TfToken::Immortal)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
void * regiondata
short regiontype
struct ARegionType * type
struct Material * material
struct BrushGpencilSettings * gpencil_settings
int tag
Definition: DNA_ID.h:387
unsigned int * rect
float * rect_float
void * first
Definition: DNA_listBase.h:31
struct MDeformWeight * dw
Definition: BKE_main.h:121
struct MaterialGPencilStyle * gp_style
void * data
float viewmat[4][4]
float winmat[4][4]
struct ToolSettings * toolsettings
struct RenderData r
ListBase spacedata
GpPaint * gp_paint
struct GP_Sculpt_Settings gp_sculpt
float * depths
Definition: ED_view3d.h:80
struct bGPDframe * next
ListBase strokes
bGPDframe * actframe
bGPDspoint * points
float fill_opacity_fac
float aspect_ratio[2]
struct MDeformVert * dvert
ListBase vertex_group_names
ListBase layers
int vertex_group_active_index
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
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
short lthick
float diff_mat[4][4]
int disable_fill
struct bGPdata * gpd
bool custonion
struct bGPDstroke * gps
float opacity
struct Object * ob
bool is_fill_stroke
struct Depsgraph * depsgraph
float tintcolor[4]
struct bGPDlayer * gpl
struct bGPDframe * gpf
struct bGPDframe * t_gpf
struct RegionView3D * rv3d
struct Main * bmain
Definition: gpencil_fill.c:84
struct ReportList * reports
Definition: gpencil_fill.c:113
Image * ima
Definition: gpencil_fill.c:157
short oldkey
Definition: gpencil_fill.c:119
float fill_factor
Definition: gpencil_fill.c:144
struct wmWindow * win
Definition: gpencil_fill.c:87
struct Material * mat
Definition: gpencil_fill.c:103
float * depth_arr
Definition: gpencil_fill.c:154
struct Scene * scene
Definition: gpencil_fill.c:89
float fill_threshold
Definition: gpencil_fill.c:138
bContext * C
Definition: gpencil_fill.c:83
short fill_leak
Definition: gpencil_fill.c:136
struct ScrArea * area
Definition: gpencil_fill.c:93
int fill_draw_mode
Definition: gpencil_fill.c:142
short sbuffer_used
Definition: gpencil_fill.c:150
struct bGPDlayer * gpl
Definition: gpencil_fill.c:107
void * draw_handle_3d
Definition: gpencil_fill.c:161
float fill_extend_fac
Definition: gpencil_fill.c:176
short flag
Definition: gpencil_fill.c:117
int active_cfra
Definition: gpencil_fill.c:147
float zoom
Definition: gpencil_fill.c:173
struct bGPdata * gpd
Definition: gpencil_fill.c:101
struct Depsgraph * depsgraph
Definition: gpencil_fill.c:85
struct RegionView3D * rv3d
Definition: gpencil_fill.c:95
int lock_axis
Definition: gpencil_fill.c:133
rcti brect
Definition: gpencil_fill.c:167
struct bGPDstroke * gps_mouse
Definition: gpencil_fill.c:111
BLI_Stack * stack
Definition: gpencil_fill.c:159
bool is_render
Definition: gpencil_fill.c:123
struct Object * ob
Definition: gpencil_fill.c:91
int fill_simplylvl
Definition: gpencil_fill.c:140
GP_SpaceConversion gsc
Definition: gpencil_fill.c:170
struct ViewDepths * depths
Definition: gpencil_fill.c:115
struct bGPDframe * gpf
Definition: gpencil_fill.c:109
int mouse[2]
Definition: gpencil_fill.c:127
void * sbuffer
Definition: gpencil_fill.c:152
struct ARegion * region
Definition: gpencil_fill.c:99
struct View3D * v3d
Definition: gpencil_fill.c:97
bool on_back
Definition: gpencil_fill.c:121
struct Brush * brush
Definition: gpencil_fill.c:105
float pressure
Definition: ED_gpencil.h:83
float m_xy[2]
Definition: ED_gpencil.h:81
float time
Definition: ED_gpencil.h:87
float strength
Definition: ED_gpencil.h:85
int xy[2]
Definition: WM_types.h:682
short type
Definition: WM_types.h:678
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
struct ReportList * reports
struct PointerRNA * ptr
void WM_cursor_modal_set(wmWindow *win, int val)
Definition: wm_cursors.c:191
void WM_cursor_modal_restore(wmWindow *win)
Definition: wm_cursors.c:200
void WM_cursor_time(wmWindow *win, int nr)
Definition: wm_cursors.c:317
@ WM_CURSOR_PAINT_BRUSH
Definition: wm_cursors.h:33
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ RIGHTMOUSE
@ WHEELUPMOUSE
@ EVT_PAGEUPKEY
@ EVT_PAGEDOWNKEY
@ WHEELDOWNMOUSE
@ LEFTMOUSE
@ EVT_ESCKEY
wmOperatorType * ot
Definition: wm_files.c:3479