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