Blender  V2.93
gpencil_primitive.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  * Operators for creating new Grease Pencil primitives (boxes, circles, ...)
19  */
20 
25 #include <math.h>
26 #include <stddef.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "MEM_guardedalloc.h"
32 
33 #include "BLI_blenlib.h"
34 #include "BLI_math.h"
35 #include "BLI_rand.h"
36 #include "BLI_utildefines.h"
37 
38 #include "BLT_translation.h"
39 
40 #include "PIL_time.h"
41 
42 #include "DNA_brush_types.h"
43 #include "DNA_gpencil_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_screen_types.h"
48 #include "DNA_space_types.h"
49 #include "DNA_view3d_types.h"
50 
51 #include "BKE_brush.h"
52 #include "BKE_colortools.h"
53 #include "BKE_context.h"
54 #include "BKE_deform.h"
55 #include "BKE_global.h"
56 #include "BKE_gpencil.h"
57 #include "BKE_gpencil_geom.h"
58 #include "BKE_main.h"
59 #include "BKE_material.h"
60 #include "BKE_paint.h"
61 #include "BKE_report.h"
62 
63 #include "UI_interface.h"
64 #include "UI_resources.h"
65 
66 #include "WM_api.h"
67 #include "WM_types.h"
68 
69 #include "RNA_access.h"
70 #include "RNA_define.h"
71 #include "RNA_enum_types.h"
72 
73 #include "ED_gpencil.h"
74 #include "ED_keyframing.h"
75 #include "ED_object.h"
76 #include "ED_screen.h"
77 #include "ED_space_api.h"
78 #include "ED_view3d.h"
79 
80 #include "DEG_depsgraph.h"
81 #include "DEG_depsgraph_query.h"
82 
83 #include "gpencil_intern.h"
84 
85 #define MIN_EDGES 2
86 #define MAX_EDGES 128
87 #define MAX_CP 128
88 
89 #define IDLE 0
90 #define IN_PROGRESS 1
91 #define IN_CURVE_EDIT 2
92 #define IN_MOVE 3
93 #define IN_BRUSH_SIZE 4
94 #define IN_BRUSH_STRENGTH 5
95 #define IN_POLYLINE 6
96 
97 #define SELECT_NONE 0
98 #define SELECT_START 1
99 #define SELECT_CP1 2
100 #define SELECT_CP2 3
101 #define SELECT_END 4
102 
103 #define BIG_SIZE_CTL 15
104 #define MID_SIZE_CTL 10
105 #define SMALL_SIZE_CTL 8
106 
107 #define MOVE_NONE 0
108 #define MOVE_ENDS 1
109 #define MOVE_CP 2
110 
111 /* ************************************************ */
112 /* Core/Shared Utilities */
114  {GP_STROKE_BOX, "BOX", 0, "Box", ""},
115  {GP_STROKE_LINE, "LINE", 0, "Line", ""},
116  {GP_STROKE_POLYLINE, "POLYLINE", 0, "Polyline", ""},
117  {GP_STROKE_CIRCLE, "CIRCLE", 0, "Circle", ""},
118  {GP_STROKE_ARC, "ARC", 0, "Arc", ""},
119  {GP_STROKE_CURVE, "CURVE", 0, "Curve", ""},
120  {0, NULL, 0, NULL, NULL},
121 };
122 /* clear the session buffers (call this before AND after a paint operation) */
124 {
125  bGPdata *gpd = p->gpd;
126 
127  /* clear memory of buffer (or allocate it if starting a new session) */
129  gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, true);
130 
131  /* reset flags */
132  gpd->runtime.sbuffer_sflag = 0;
134 
135  /* Set vertex colors for buffer. */
137  p->ob,
138  p->scene->toolsettings,
139  p->brush,
140  p->material,
141  p->random_settings.hsv,
142  1.0f);
143 
146  }
147 }
148 
150 {
151  bGPdata *gpd = p->gpd;
152  Brush *brush = p->brush;
153 
154  /* use brush material */
156 
158  gpd->runtime.sbuffer_brush = brush;
159 }
160 
161 /* Helper to square a primitive */
162 static void gpencil_primitive_to_square(tGPDprimitive *tgpi, const float x, const float y)
163 {
164  float w = fabsf(x);
165  float h = fabsf(y);
166  if ((x > 0 && y > 0) || (x < 0 && y < 0)) {
167  if (w > h) {
168  tgpi->end[1] = tgpi->origin[1] + x;
169  }
170  else {
171  tgpi->end[0] = tgpi->origin[0] + y;
172  }
173  }
174  else {
175  if (w > h) {
176  tgpi->end[1] = tgpi->origin[1] - x;
177  }
178  else {
179  tgpi->end[0] = tgpi->origin[0] - y;
180  }
181  }
182 }
183 
184 /* Helper to constrain a primitive */
185 static void gpencil_primitive_constrain(tGPDprimitive *tgpi, bool line_mode)
186 {
187  float x = tgpi->end[0] - tgpi->origin[0];
188  float y = tgpi->end[1] - tgpi->origin[1];
189 
190  if (line_mode) {
191  float angle = fabsf(atan2f(y, x));
192  if (angle < 0.4f || angle > (M_PI - 0.4f)) {
193  tgpi->end[1] = tgpi->origin[1];
194  }
195  else if (angle > (M_PI_2 - 0.4f) && angle < (M_PI_2 + 0.4f)) {
196  tgpi->end[0] = tgpi->origin[0];
197  }
198  else {
200  }
201  }
202  else {
204  }
205 }
206 
207 /* Helper to rotate point around origin */
208 static void gpencil_rotate_v2_v2v2fl(float v[2],
209  const float p[2],
210  const float origin[2],
211  const float angle)
212 {
213  float pt[2];
214  float r[2];
215  sub_v2_v2v2(pt, p, origin);
216  rotate_v2_v2fl(r, pt, angle);
217  add_v2_v2v2(v, r, origin);
218 }
219 
220 /* Helper to rotate line around line center. */
222  float va[2], float vb[2], const float a[2], const float b[2], const float angle)
223 {
224  float midpoint[2];
225  mid_v2_v2v2(midpoint, a, b);
226  gpencil_rotate_v2_v2v2fl(va, a, midpoint, angle);
227  gpencil_rotate_v2_v2v2fl(vb, b, midpoint, angle);
228 }
229 
230 /* Helper to update cps */
232 {
233  if (!tgpi->curve) {
234  mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
235  copy_v2_v2(tgpi->cp1, tgpi->midpoint);
236  copy_v2_v2(tgpi->cp2, tgpi->cp1);
237  }
238  else if (tgpi->type == GP_STROKE_CURVE) {
239  mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
240  interp_v2_v2v2(tgpi->cp1, tgpi->midpoint, tgpi->start, 0.33f);
241  interp_v2_v2v2(tgpi->cp2, tgpi->midpoint, tgpi->end, 0.33f);
242  }
243  else if (tgpi->type == GP_STROKE_ARC) {
244  if (tgpi->flip) {
245  gpencil_primitive_rotate_line(tgpi->cp1, tgpi->cp2, tgpi->start, tgpi->end, M_PI_2);
246  }
247  else {
248  gpencil_primitive_rotate_line(tgpi->cp1, tgpi->cp2, tgpi->end, tgpi->start, M_PI_2);
249  }
250  }
251 }
252 
253 /* Poll callback for primitive operators */
255 {
256  /* only 3D view */
258  if (area && area->spacetype != SPACE_VIEW3D) {
259  return false;
260  }
261 
262  /* need data to create primitive */
264  if (gpd == NULL) {
265  return false;
266  }
267 
268  /* only in edit and paint modes
269  * - paint as it's the "drawing/creation mode"
270  * - edit as this is more of an atomic editing operation
271  * (similar to copy/paste), and also for consistency
272  */
273  if ((gpd->flag & (GP_DATA_STROKE_PAINTMODE | GP_DATA_STROKE_EDITMODE)) == 0) {
274  CTX_wm_operator_poll_msg_set(C, "Primitives can only be added in Draw or Edit modes");
275  return false;
276  }
277 
278  /* don't allow operator to function if the active layer is locked/hidden
279  * (BUT, if there isn't an active layer, we are free to add new layer when the time comes)
280  */
282  if ((gpl) && (gpl->flag & (GP_LAYER_LOCKED | GP_LAYER_HIDE))) {
284  "Primitives cannot be added as active layer is locked or hidden");
285  return false;
286  }
287 
288  return true;
289 }
290 
291 /* Allocate memory to stroke, adds MAX_EDGES on every call */
293 {
294  tgpi->point_count += (tgpi->type == GP_STROKE_BOX) ? (MAX_EDGES * 4 + 1) : (MAX_EDGES + 1);
295  bGPDstroke *gpsf = tgpi->gpf->strokes.first;
296  gpsf->points = MEM_reallocN(gpsf->points, sizeof(bGPDspoint) * tgpi->point_count);
297  if (gpsf->dvert != NULL) {
298  gpsf->dvert = MEM_reallocN(gpsf->dvert, sizeof(MDeformVert) * tgpi->point_count);
299  }
300  tgpi->points = MEM_reallocN(tgpi->points, sizeof(tGPspoint) * tgpi->point_count);
301 }
302 
303 /* ****************** Primitive Interactive *********************** */
304 
305 /* Helper: Create internal strokes primitives data */
307 {
310  Brush *brush = tgpi->brush;
311  int cfra = CFRA;
312 
314 
315  /* if layer doesn't exist, create a new one */
316  if (gpl == NULL) {
317  gpl = BKE_gpencil_layer_addnew(tgpi->gpd, DATA_("Primitives"), true);
318  }
319  tgpi->gpl = gpl;
320 
321  /* Recalculate layer transform matrix to avoid problems if props are animated. */
322  loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale);
323  invert_m4_m4(gpl->layer_invmat, gpl->layer_mat);
324 
325  /* create a new temporary frame */
326  tgpi->gpf = MEM_callocN(sizeof(bGPDframe), "Temp bGPDframe");
327  tgpi->gpf->framenum = tgpi->cframe = cfra;
328 
329  /* create new temp stroke */
330  bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "Temp bGPDstroke");
331  gps->thickness = 2.0f;
332  gps->fill_opacity_fac = 1.0f;
333  gps->hardeness = 1.0f;
334  copy_v2_fl(gps->aspect_ratio, 1.0f);
335  gps->uv_scale = 1.0f;
336  gps->inittime = 0.0f;
337 
338  /* Apply the vertex color to fill. */
339  ED_gpencil_fill_vertex_color_set(ts, brush, gps);
340 
341  gps->flag &= ~GP_STROKE_SELECT;
343  /* the polygon must be closed, so enabled cyclic */
344  if (ELEM(tgpi->type, GP_STROKE_BOX, GP_STROKE_CIRCLE)) {
345  gps->flag |= GP_STROKE_CYCLIC;
346  }
347 
348  gps->flag |= GP_STROKE_3DSPACE;
349 
351  if (gps->mat_nr < 0) {
352  if (tgpi->ob->actcol - 1 < 0) {
353  gps->mat_nr = 0;
354  }
355  else {
356  gps->mat_nr = tgpi->ob->actcol - 1;
357  }
358  }
359 
360  /* allocate memory for storage points, but keep empty */
361  gps->totpoints = 0;
362  gps->points = MEM_callocN(sizeof(bGPDspoint), "gp_stroke_points");
363  gps->dvert = NULL;
364 
365  /* initialize triangle memory to dummy data */
366  gps->tot_triangles = 0;
367  gps->triangles = NULL;
368 
369  /* add to strokes */
370  BLI_addtail(&tgpi->gpf->strokes, gps);
371 
372  /* allocate memory for storage points */
374 
375  /* Random generator, only init once. */
376  uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
377  tgpi->rng = BLI_rng_new(rng_seed);
378 
380 }
381 
382 /* add new segment to curve */
384 {
385  if (tgpi->tot_stored_edges > 0) {
386  tgpi->tot_stored_edges += (tgpi->tot_edges - 1);
387  }
388  else {
389  tgpi->tot_stored_edges += tgpi->tot_edges;
390  }
392 }
393 
394 /* Helper: set control point */
396  const float p[2],
397  float color[4],
398  int size)
399 {
400  if (tgpi->flag == IN_PROGRESS) {
401  return;
402  }
403 
404  bGPDcontrolpoint *cp_points = tgpi->gpd->runtime.cp_points;
405 
406  if (tgpi->gpd->runtime.tot_cp_points < MAX_CP) {
407  CLAMP(size, 5, 20);
408  bGPDcontrolpoint *cp = &cp_points[tgpi->gpd->runtime.tot_cp_points];
409  copy_v2_v2(&cp->x, p);
410  copy_v4_v4(cp->color, color);
411  color[3] = 0.8f;
412  cp->size = size;
413  tgpi->gpd->runtime.tot_cp_points += 1;
414  }
415 }
416 
417 /* Helper: Draw status message while the user is running the operator */
419 {
420  Scene *scene = tgpi->scene;
421  char status_str[UI_MAX_DRAW_STR];
422  char msg_str[UI_MAX_DRAW_STR];
423 
424  if (tgpi->type == GP_STROKE_LINE) {
425  BLI_strncpy(msg_str,
426  TIP_("Line: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- to "
427  "adjust subdivision number, Shift to align, Alt to center, E: extrude"),
429  }
430  else if (tgpi->type == GP_STROKE_POLYLINE) {
431  BLI_strncpy(msg_str,
432  TIP_("Polyline: ESC to cancel, LMB to set, Enter/MMB to confirm, WHEEL/+- to "
433  "adjust subdivision number, Shift to align"),
435  }
436  else if (tgpi->type == GP_STROKE_BOX) {
437  BLI_strncpy(msg_str,
438  TIP_("Rectangle: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- "
439  "to adjust subdivision number, Shift to square, Alt to center"),
441  }
442  else if (tgpi->type == GP_STROKE_CIRCLE) {
443  BLI_strncpy(msg_str,
444  TIP_("Circle: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision "
445  "number, Shift to square, Alt to center"),
447  }
448  else if (tgpi->type == GP_STROKE_ARC) {
449  BLI_strncpy(
450  msg_str,
451  TIP_("Arc: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision number, "
452  "Shift to square, Alt to center, M: Flip, E: extrude"),
454  }
455  else if (tgpi->type == GP_STROKE_CURVE) {
456  BLI_strncpy(msg_str,
457  TIP_("Curve: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision "
458  "number, Shift to square, Alt to center, E: extrude"),
460  }
461 
462  if (ELEM(tgpi->type,
468  if (hasNumInput(&tgpi->num)) {
469  char str_ofs[NUM_STR_REP_LEN];
470 
471  outputNumInput(&tgpi->num, str_ofs, &scene->unit);
472  BLI_snprintf(status_str, sizeof(status_str), "%s: %s", msg_str, str_ofs);
473  }
474  else {
475  if (tgpi->flag == IN_PROGRESS) {
476  BLI_snprintf(status_str,
477  sizeof(status_str),
478  "%s: %d (%d, %d) (%d, %d)",
479  msg_str,
480  tgpi->tot_edges,
481  (int)tgpi->start[0],
482  (int)tgpi->start[1],
483  (int)tgpi->end[0],
484  (int)tgpi->end[1]);
485  }
486  else {
487  BLI_snprintf(status_str,
488  sizeof(status_str),
489  "%s: %d (%d, %d)",
490  msg_str,
491  tgpi->tot_edges,
492  (int)tgpi->end[0],
493  (int)tgpi->end[1]);
494  }
495  }
496  }
497  else {
498  if (tgpi->flag == IN_PROGRESS) {
499  BLI_snprintf(status_str,
500  sizeof(status_str),
501  "%s: %d (%d, %d) (%d, %d)",
502  msg_str,
503  tgpi->tot_edges,
504  (int)tgpi->start[0],
505  (int)tgpi->start[1],
506  (int)tgpi->end[0],
507  (int)tgpi->end[1]);
508  }
509  else {
510  BLI_snprintf(status_str,
511  sizeof(status_str),
512  "%s: (%d, %d)",
513  msg_str,
514  (int)tgpi->end[0],
515  (int)tgpi->end[1]);
516  }
517  }
518  ED_workspace_status_text(C, status_str);
519 }
520 
521 /* create a rectangle */
523 {
524  float coords[5][2];
525 
526  coords[0][0] = tgpi->start[0];
527  coords[0][1] = tgpi->start[1];
528  coords[1][0] = tgpi->end[0];
529  coords[1][1] = tgpi->start[1];
530  coords[2][0] = tgpi->end[0];
531  coords[2][1] = tgpi->end[1];
532  coords[3][0] = tgpi->start[0];
533  coords[3][1] = tgpi->end[1];
534  coords[4][0] = tgpi->start[0];
535  coords[4][1] = tgpi->start[1];
536 
537  if (tgpi->tot_edges == 1) {
538  for (int j = 0; j < 4; j++) {
539  tGPspoint *p2d = &points2D[j];
540  copy_v2_v2(&p2d->x, coords[j]);
541  }
542  }
543  else {
544  const float step = 1.0f / (float)(tgpi->tot_edges);
545  int i = tgpi->tot_stored_edges;
546  for (int j = 0; j < 4; j++) {
547  float a = 0.0f;
548  for (int k = 0; k < tgpi->tot_edges; k++) {
549  tGPspoint *p2d = &points2D[i];
550  interp_v2_v2v2(&p2d->x, coords[j], coords[j + 1], a);
551  a += step;
552  i++;
553  }
554  }
555  }
556 
557  mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
558  float color[4];
560  gpencil_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
561  if (tgpi->tot_stored_edges) {
563  gpencil_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
564  }
565  else {
566  gpencil_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
567  }
569  gpencil_primitive_set_cp(tgpi, tgpi->midpoint, color, SMALL_SIZE_CTL);
570 }
571 
572 /* create a line */
573 static void gpencil_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D, bool editable)
574 {
575  const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
576  const float step = 1.0f / (float)(tgpi->tot_edges - 1);
577  float a = tgpi->tot_stored_edges ? step : 0.0f;
578 
579  for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
580  tGPspoint *p2d = &points2D[i];
581  interp_v2_v2v2(&p2d->x, tgpi->start, tgpi->end, a);
582  a += step;
583  }
584 
585  if (editable) {
586  float color[4];
588  gpencil_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
589  if (tgpi->tot_stored_edges) {
591  gpencil_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
592  }
593  else {
594  gpencil_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
595  }
596  }
597  else {
598  float color[4];
600  gpencil_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
601  }
602 }
603 
604 /* create an arc */
605 static void gpencil_primitive_arc(tGPDprimitive *tgpi, tGPspoint *points2D)
606 {
607  const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
608  const float step = M_PI_2 / (float)(tgpi->tot_edges - 1);
609  float start[2];
610  float end[2];
611  float cp1[2];
612  float corner[2];
613  float midpoint[2];
614  float a = tgpi->tot_stored_edges ? step : 0.0f;
615 
616  mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
617  copy_v2_v2(start, tgpi->start);
618  copy_v2_v2(end, tgpi->end);
619  copy_v2_v2(cp1, tgpi->cp1);
620  copy_v2_v2(midpoint, tgpi->midpoint);
621 
622  corner[0] = midpoint[0] - (cp1[0] - midpoint[0]);
623  corner[1] = midpoint[1] - (cp1[1] - midpoint[1]);
624 
625  for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
626  tGPspoint *p2d = &points2D[i];
627  p2d->x = corner[0] + (end[0] - corner[0]) * sinf(a) + (start[0] - corner[0]) * cosf(a);
628  p2d->y = corner[1] + (end[1] - corner[1]) * sinf(a) + (start[1] - corner[1]) * cosf(a);
629  a += step;
630  }
631  float color[4];
633  gpencil_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
634  if (tgpi->tot_stored_edges) {
636  gpencil_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
637  }
638  else {
639  gpencil_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
640  }
642  gpencil_primitive_set_cp(tgpi, tgpi->cp1, color, BIG_SIZE_CTL * 0.9f);
643 }
644 
645 /* create a bezier */
646 static void gpencil_primitive_bezier(tGPDprimitive *tgpi, tGPspoint *points2D)
647 {
648  const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
649  const float step = 1.0f / (float)(tgpi->tot_edges - 1);
650  float bcp1[2];
651  float bcp2[2];
652  float bcp3[2];
653  float bcp4[2];
654  float a = tgpi->tot_stored_edges ? step : 0.0f;
655 
656  copy_v2_v2(bcp1, tgpi->start);
657  copy_v2_v2(bcp2, tgpi->cp1);
658  copy_v2_v2(bcp3, tgpi->cp2);
659  copy_v2_v2(bcp4, tgpi->end);
660 
661  for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
662  tGPspoint *p2d = &points2D[i];
663  interp_v2_v2v2v2v2_cubic(&p2d->x, bcp1, bcp2, bcp3, bcp4, a);
664  a += step;
665  }
666  float color[4];
668  gpencil_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
669  if (tgpi->tot_stored_edges) {
671  gpencil_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
672  }
673  else {
674  gpencil_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
675  }
677  gpencil_primitive_set_cp(tgpi, tgpi->cp1, color, BIG_SIZE_CTL * 0.9f);
678  gpencil_primitive_set_cp(tgpi, tgpi->cp2, color, BIG_SIZE_CTL * 0.9f);
679 }
680 
681 /* create a circle */
682 static void gpencil_primitive_circle(tGPDprimitive *tgpi, tGPspoint *points2D)
683 {
684  const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
685  const float step = (2.0f * M_PI) / (float)(tgpi->tot_edges);
686  float center[2];
687  float radius[2];
688  float a = 0.0f;
689 
690  center[0] = tgpi->start[0] + ((tgpi->end[0] - tgpi->start[0]) / 2.0f);
691  center[1] = tgpi->start[1] + ((tgpi->end[1] - tgpi->start[1]) / 2.0f);
692  radius[0] = fabsf(((tgpi->end[0] - tgpi->start[0]) / 2.0f));
693  radius[1] = fabsf(((tgpi->end[1] - tgpi->start[1]) / 2.0f));
694 
695  for (int i = tgpi->tot_stored_edges; i < totpoints; i++) {
696  tGPspoint *p2d = &points2D[i];
697  p2d->x = (center[0] + cosf(a) * radius[0]);
698  p2d->y = (center[1] + sinf(a) * radius[1]);
699  a += step;
700  }
701  float color[4];
703  gpencil_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
704  gpencil_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
707 }
708 
709 /* Helper: Update shape of the stroke */
711 {
712  ToolSettings *ts = tgpi->scene->toolsettings;
713  bGPdata *gpd = tgpi->gpd;
714  Brush *brush = tgpi->brush;
715  BrushGpencilSettings *brush_settings = brush->gpencil_settings;
716  GpRandomSettings random_settings = tgpi->random_settings;
717  bGPDstroke *gps = tgpi->gpf->strokes.first;
718  GP_Sculpt_Settings *gset = &ts->gp_sculpt;
719  int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
720  const char align_flag = ts->gpencil_v3d_align;
721  bool is_depth = (bool)(align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE));
722  const bool is_lock_axis_view = (bool)(ts->gp_sculpt.lock_axis == 0);
723  const bool is_camera = is_lock_axis_view && (tgpi->rv3d->persp == RV3D_CAMOB) && (!is_depth);
724 
725  if (tgpi->type == GP_STROKE_BOX) {
726  tgpi->tot_edges--;
727  gps->totpoints = (tgpi->tot_edges * 4 + tgpi->tot_stored_edges);
728  }
729  else {
730  gps->totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
731  }
732 
733  if (tgpi->tot_stored_edges) {
734  gps->totpoints--;
735  }
736 
737  tgpi->gpd->runtime.tot_cp_points = 0;
738 
739  /* compute screen-space coordinates for points */
740  tGPspoint *points2D = tgpi->points;
741 
742  if (tgpi->tot_edges > 0) {
743  switch (tgpi->type) {
744  case GP_STROKE_BOX:
745  gpencil_primitive_rectangle(tgpi, points2D);
746  break;
747  case GP_STROKE_LINE:
748  gpencil_primitive_line(tgpi, points2D, true);
749  break;
750  case GP_STROKE_POLYLINE:
751  gpencil_primitive_line(tgpi, points2D, false);
752  break;
753  case GP_STROKE_CIRCLE:
754  gpencil_primitive_circle(tgpi, points2D);
755  break;
756  case GP_STROKE_ARC:
757  gpencil_primitive_arc(tgpi, points2D);
758  break;
759  case GP_STROKE_CURVE:
760  gpencil_primitive_bezier(tgpi, points2D);
761  default:
762  break;
763  }
764  }
765 
766  /* convert screen-coordinates to 3D coordinates */
768  gpencil_init_colors(tgpi);
771  }
772  if (brush_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
773  BKE_curvemapping_init(brush_settings->curve_jitter);
774  }
775  if (brush_settings->flag & GP_BRUSH_USE_STRENGTH_PRESSURE) {
776  BKE_curvemapping_init(brush_settings->curve_strength);
777  }
778 
779  /* get an array of depths, far depths are blended */
780  float *depth_arr = NULL;
781  if (is_depth) {
782  int mval_i[2], mval_prev[2] = {0};
783  bool interp_depth = false;
784  bool found_depth = false;
785 
786  /* need to restore the original projection settings before packing up */
789  tgpi->region,
790  tgpi->v3d,
791  NULL,
795  false);
796 
797  depth_arr = MEM_mallocN(sizeof(float) * gps->totpoints, "depth_points");
798  tGPspoint *ptc = &points2D[0];
799  for (int i = 0; i < gps->totpoints; i++, ptc++) {
800  round_v2i_v2fl(mval_i, &ptc->x);
801  if ((ED_view3d_autodist_depth(tgpi->region, mval_i, depth_margin, depth_arr + i) == 0) &&
803  tgpi->region, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) {
804  interp_depth = true;
805  }
806  else {
807  found_depth = true;
808  }
809  copy_v2_v2_int(mval_prev, mval_i);
810  }
811 
812  if (!found_depth) {
813  for (int i = 0; i < gps->totpoints; i++) {
814  depth_arr[i] = 0.9999f;
815  }
816  }
817  else {
818  /* if all depth are too high disable */
819  bool valid_depth = false;
820  for (int i = 0; i < gps->totpoints; i++) {
821  if (depth_arr[i] < 0.9999f) {
822  valid_depth = true;
823  break;
824  }
825  }
826  if (!valid_depth) {
827  MEM_SAFE_FREE(depth_arr);
828  is_depth = false;
829  }
830  else {
834  int first_valid = 0;
835  int last_valid = 0;
836 
837  /* find first valid contact point */
838  int i;
839  for (i = 0; i < gps->totpoints; i++) {
840  if (depth_arr[i] != FLT_MAX) {
841  break;
842  }
843  }
844  first_valid = i;
845 
846  /* find last valid contact point */
848  last_valid = first_valid;
849  }
850  else {
851  for (i = gps->totpoints - 1; i >= 0; i--) {
852  if (depth_arr[i] != FLT_MAX) {
853  break;
854  }
855  }
856  last_valid = i;
857  }
858 
859  /* invalidate any other point, to interpolate between
860  * first and last contact in an imaginary line between them */
861  for (i = 0; i < gps->totpoints; i++) {
862  if (!ELEM(i, first_valid, last_valid)) {
863  depth_arr[i] = FLT_MAX;
864  }
865  }
866  interp_depth = true;
867  }
868 
869  if (interp_depth) {
870  interp_sparse_array(depth_arr, gps->totpoints, FLT_MAX);
871  }
872  }
873  }
874  }
875 
876  /* load stroke points and sbuffer */
877  for (int i = 0; i < gps->totpoints; i++) {
878  bGPDspoint *pt = &gps->points[i];
879  tGPspoint *p2d = &points2D[i];
880 
881  /* set rnd value for reuse */
882  if ((brush_settings->flag & GP_BRUSH_GROUP_RANDOM) && (p2d->rnd_dirty != true)) {
883  p2d->rnd[0] = BLI_rng_get_float(tgpi->rng);
884  p2d->rnd[1] = BLI_rng_get_float(tgpi->rng);
885  p2d->rnd_dirty = true;
886  }
887 
888  /* Copy points to buffer */
889  tGPspoint *tpt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_used);
890 
891  /* Store original points */
892  float tmp_xyp[2];
893  copy_v2_v2(tmp_xyp, &p2d->x);
894 
895  /* calc pressure */
896  float curve_pressure = 1.0;
897  float pressure = 1.0;
898  float strength = brush_settings->draw_strength;
899 
900  /* normalize value to evaluate curve */
902  float value = (float)i / (gps->totpoints - 1);
903  curve_pressure = BKE_curvemapping_evaluateF(gset->cur_primitive, 0, value);
904  pressure = curve_pressure;
905  }
906 
907  /* apply jitter to position */
908  if ((brush_settings->flag & GP_BRUSH_GROUP_RANDOM) && (brush_settings->draw_jitter > 0.0f)) {
909  float jitter;
910 
911  if (brush_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
912  jitter = BKE_curvemapping_evaluateF(brush_settings->curve_jitter, 0, curve_pressure);
913  }
914  else {
915  jitter = brush_settings->draw_jitter;
916  }
917 
918  /* exponential value */
919  const float exfactor = square_f(brush_settings->draw_jitter + 2.0f);
920  const float fac = p2d->rnd[0] * exfactor * jitter;
921 
922  /* vector */
923  float mvec[2], svec[2];
924  if (i > 0) {
925  mvec[0] = (p2d->x - (p2d - 1)->x);
926  mvec[1] = (p2d->y - (p2d - 1)->y);
927  normalize_v2(mvec);
928  }
929  else {
930  zero_v2(mvec);
931  }
932  svec[0] = -mvec[1];
933  svec[1] = mvec[0];
934 
935  if (p2d->rnd[1] > 0.5f) {
936  mul_v2_fl(svec, -fac);
937  }
938  else {
939  mul_v2_fl(svec, fac);
940  }
941  add_v2_v2(&p2d->x, svec);
942  }
943 
944  /* color strength */
945  if (brush_settings->flag & GP_BRUSH_USE_STRENGTH_PRESSURE) {
946  float curvef = BKE_curvemapping_evaluateF(brush_settings->curve_strength, 0, curve_pressure);
947  strength *= curvef;
948  strength *= brush_settings->draw_strength;
949  }
950 
951  CLAMP(strength, GPENCIL_STRENGTH_MIN, 1.0f);
952 
953  if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) {
954  /* Apply randomness to pressure. */
955  if (brush_settings->draw_random_press > 0.0f) {
956  if ((brush_settings->flag2 & GP_BRUSH_USE_PRESS_AT_STROKE) == 0) {
957  float rand = BLI_rng_get_float(tgpi->rng) * 2.0f - 1.0f;
958  pressure *= 1.0 + rand * 2.0 * brush_settings->draw_random_press;
959  }
960  else {
961  pressure *= 1.0 + random_settings.pressure * brush_settings->draw_random_press;
962  }
963 
964  /* Apply random curve. */
965  if (brush_settings->flag2 & GP_BRUSH_USE_PRESSURE_RAND_PRESS) {
966  pressure *= BKE_curvemapping_evaluateF(brush_settings->curve_rand_pressure, 0, pressure);
967  }
968 
969  CLAMP(pressure, 0.1f, 1.0f);
970  }
971 
972  /* Apply randomness to color strength. */
973  if (brush_settings->draw_random_strength) {
974  if ((brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_AT_STROKE) == 0) {
975  float rand = BLI_rng_get_float(tgpi->rng) * 2.0f - 1.0f;
976  strength *= 1.0 + rand * brush_settings->draw_random_strength;
977  }
978  else {
979  strength *= 1.0 + random_settings.strength * brush_settings->draw_random_strength;
980  }
981 
982  /* Apply random curve. */
983  if (brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_RAND_PRESS) {
984  strength *= BKE_curvemapping_evaluateF(brush_settings->curve_rand_strength, 0, pressure);
985  }
986 
987  CLAMP(strength, GPENCIL_STRENGTH_MIN, 1.0f);
988  }
989  }
990 
991  copy_v2_v2(&tpt->x, &p2d->x);
992 
993  tpt->pressure = pressure;
994  tpt->strength = strength;
995  tpt->time = p2d->time;
996 
997  /* Set vertex colors for buffer. */
999  tgpi->ob,
1000  tgpi->scene->toolsettings,
1001  tgpi->brush,
1002  tgpi->material,
1003  tgpi->random_settings.hsv,
1004  strength);
1005 
1006  /* point uv */
1007  if (gpd->runtime.sbuffer_used > 0) {
1008  tGPspoint *tptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
1009  bGPDspoint spt, spt2;
1010 
1011  /* get origin to reproject point */
1012  float origin[3];
1013  ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin);
1014  /* reproject current */
1015  ED_gpencil_tpoint_to_point(tgpi->region, origin, tpt, &spt);
1017  tgpi->scene, tgpi->ob, tgpi->gpl, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt);
1018 
1019  /* reproject previous */
1020  ED_gpencil_tpoint_to_point(tgpi->region, origin, tptb, &spt2);
1022  tgpi->scene, tgpi->ob, tgpi->gpl, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2);
1023  tgpi->totpixlen += len_v3v3(&spt.x, &spt2.x);
1024  tpt->uv_fac = tgpi->totpixlen;
1025  }
1026  else {
1027  tgpi->totpixlen = 0.0f;
1028  tpt->uv_fac = 0.0f;
1029  }
1030 
1031  tpt->uv_rot = 0.0f;
1032 
1033  gpd->runtime.sbuffer_used++;
1034 
1035  /* check if still room in buffer or add more */
1037  gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, false);
1038 
1039  /* add small offset to keep stroke over the surface */
1040  if ((depth_arr) && (gpd->zdepth_offset > 0.0f)) {
1041  depth_arr[i] *= (1.0f - (gpd->zdepth_offset / 1000.0f));
1042  }
1043 
1044  /* convert screen-coordinates to 3D coordinates */
1046  tgpi->scene, tgpi->region, tgpi->ob, p2d, depth_arr ? depth_arr + i : NULL, &pt->x);
1047 
1048  pt->pressure = pressure;
1049  pt->strength = strength;
1050  pt->time = 0.0f;
1051  pt->flag = 0;
1052  pt->uv_fac = tpt->uv_fac;
1053  pt->uv_rot = 0.0f;
1054  ED_gpencil_point_vertex_color_set(ts, brush, pt, tpt);
1055 
1056  if (gps->dvert != NULL) {
1057  MDeformVert *dvert = &gps->dvert[i];
1058  dvert->totweight = 0;
1059  dvert->dw = NULL;
1060  }
1061 
1062  /* Restore original points */
1063  copy_v2_v2(&p2d->x, tmp_xyp);
1064  }
1065 
1066  /* store cps and convert coords */
1067  if (tgpi->gpd->runtime.tot_cp_points > 0) {
1068  bGPDcontrolpoint *cps = tgpi->gpd->runtime.cp_points;
1069  for (int i = 0; i < tgpi->gpd->runtime.tot_cp_points; i++) {
1070  bGPDcontrolpoint *cp = &cps[i];
1072  tgpi->scene, tgpi->region, tgpi->ob, (tGPspoint *)cp, NULL, &cp->x);
1073  }
1074  }
1075 
1076  /* reproject to plane */
1077  if (!is_depth) {
1078  float origin[3];
1079  ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin);
1081  tgpi->scene, tgpi->ob, tgpi->rv3d, tgpi->gpl, gps, origin, ts->gp_sculpt.lock_axis - 1);
1082  }
1083 
1084  /* if parented change position relative to parent object */
1085  for (int i = 0; i < gps->totpoints; i++) {
1086  bGPDspoint *pt = &gps->points[i];
1087  gpencil_apply_parent_point(tgpi->depsgraph, tgpi->ob, tgpi->gpl, pt);
1088  }
1089 
1090  /* If camera view or view projection, reproject flat to view to avoid perspective effect. */
1091  if ((!is_depth) && (((align_flag & GP_PROJECT_VIEWSPACE) && is_lock_axis_view) || (is_camera))) {
1093  }
1094 
1095  /* Calc geometry data. */
1097 
1098  /* Update evaluated data. */
1100 
1101  MEM_SAFE_FREE(depth_arr);
1102 
1106 }
1107 
1108 /* Update screen and stroke */
1110 {
1111  /* update indicator in header */
1113  /* apply... */
1114  tgpi->type = RNA_enum_get(op->ptr, "type");
1115  tgpi->tot_edges = RNA_int_get(op->ptr, "edges");
1116  /* update points position */
1118 }
1119 
1120 /* Initialize mouse points. */
1122 {
1123  copy_v2fl_v2i(tgpi->mval, event->mval);
1124  copy_v2_v2(tgpi->origin, tgpi->mval);
1125  copy_v2_v2(tgpi->start, tgpi->mval);
1126  copy_v2_v2(tgpi->end, tgpi->mval);
1127  copy_v2_v2(tgpi->cp1, tgpi->mval);
1128  copy_v2_v2(tgpi->cp2, tgpi->mval);
1129 }
1130 
1131 /* Exit and free memory */
1133 {
1134  tGPDprimitive *tgpi = op->customdata;
1135  bGPdata *gpd = tgpi->gpd;
1136 
1137  /* don't assume that operator data exists at all */
1138  if (tgpi) {
1139  /* clear status message area */
1141 
1142  MEM_SAFE_FREE(tgpi->points);
1143  tgpi->gpd->runtime.tot_cp_points = 0;
1145  /* finally, free memory used by temp data */
1147  MEM_SAFE_FREE(tgpi->gpf);
1148 
1149  /* free random seed */
1150  if (tgpi->rng != NULL) {
1151  BLI_rng_free(tgpi->rng);
1152  }
1153 
1154  MEM_freeN(tgpi);
1155  }
1156 
1157  /* free stroke buffer */
1158  if ((gpd != NULL) && (gpd->runtime.sbuffer)) {
1160  gpd->runtime.sbuffer = NULL;
1161 
1162  /* clear flags */
1163  gpd->runtime.sbuffer_used = 0;
1164  gpd->runtime.sbuffer_size = 0;
1165  gpd->runtime.sbuffer_sflag = 0;
1166  }
1167 
1170 
1171  /* clear pointer */
1172  op->customdata = NULL;
1173 }
1174 
1175 /* Init new temporary primitive data */
1177 {
1180  Main *bmain = CTX_data_main(C);
1182  Paint *paint = &ts->gp_paint->paint;
1183 
1184  /* create temporary operator data */
1185  tGPDprimitive *tgpi = MEM_callocN(sizeof(tGPDprimitive), "GPencil Primitive Data");
1186  op->customdata = tgpi;
1187 
1188  tgpi->points = MEM_callocN(sizeof(tGPspoint), "gp primitive points2D");
1189 
1190  /* set current scene and window info */
1191  tgpi->bmain = CTX_data_main(C);
1193  tgpi->scene = scene;
1194  tgpi->ob = CTX_data_active_object(C);
1195  tgpi->ob_eval = (Object *)DEG_get_evaluated_object(tgpi->depsgraph, tgpi->ob);
1196  tgpi->area = CTX_wm_area(C);
1197  tgpi->region = CTX_wm_region(C);
1198  tgpi->rv3d = tgpi->region->regiondata;
1199  tgpi->v3d = tgpi->area->spacedata.first;
1200  tgpi->win = CTX_wm_window(C);
1201 
1202  /* save original type */
1203  tgpi->orign_type = RNA_enum_get(op->ptr, "type");
1204 
1205  /* set current frame number */
1206  tgpi->cframe = CFRA;
1207 
1208  /* set GP datablock */
1209  tgpi->gpd = gpd;
1210 
1211  /* Setup space conversions. */
1213 
1214  /* if brush doesn't exist, create a new set (fix damaged files from old versions) */
1215  if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
1216  BKE_brush_gpencil_paint_presets(bmain, ts, true);
1217  }
1218 
1219  /* Set Draw brush. */
1220  Brush *brush = BKE_paint_toolslots_brush_get(paint, 0);
1221 
1222  BKE_brush_tool_set(brush, paint, 0);
1223  BKE_paint_brush_set(paint, brush);
1224  tgpi->brush = brush;
1225 
1226  /* control points */
1228  "gp primitive cpoint");
1229  tgpi->gpd->runtime.tot_cp_points = 0;
1230 
1231  /* getcolor info */
1233  bmain, tgpi->ob, ts);
1234 
1235  /* set parameters */
1236  tgpi->type = RNA_enum_get(op->ptr, "type");
1237 
1238  if (ELEM(tgpi->type, GP_STROKE_ARC, GP_STROKE_CURVE)) {
1239  tgpi->curve = true;
1240  }
1241  else {
1242  tgpi->curve = false;
1243  }
1244 
1245  tgpi->tot_stored_edges = 0;
1246 
1247  tgpi->subdiv = RNA_int_get(op->ptr, "subdivision");
1248  RNA_int_set(op->ptr, "edges", tgpi->subdiv + 2);
1249  tgpi->tot_edges = RNA_int_get(op->ptr, "edges");
1250  tgpi->flag = IDLE;
1251  tgpi->lock_axis = ts->gp_sculpt.lock_axis;
1252 
1253  /* set temp layer, frame and stroke */
1255 }
1256 
1257 /* Invoke handler: Initialize the operator */
1258 static int gpencil_primitive_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1259 {
1260  wmWindow *win = CTX_wm_window(C);
1263  tGPDprimitive *tgpi = NULL;
1264 
1265  if (!IS_AUTOKEY_ON(scene)) {
1267  if ((gpl == NULL) || (gpl->actframe == NULL)) {
1268  BKE_report(op->reports, RPT_INFO, "No available frame for creating stroke");
1269  return OPERATOR_CANCELLED;
1270  }
1271  }
1272 
1273  /* initialize operator runtime data */
1275  tgpi = op->customdata;
1276 
1277  /* Init random settings. */
1279 
1280  const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
1281  if (!is_modal) {
1282  tgpi->flag = IN_PROGRESS;
1284  }
1285 
1286  /* if in tools region, wait till we get to the main (3d-space)
1287  * region before allowing drawing to take place.
1288  */
1290 
1291  /* set cursor to indicate modal */
1293 
1294  /* Updates indicator in header. */
1298 
1299  /* add a modal handler for this operator */
1301 
1302  return OPERATOR_RUNNING_MODAL;
1303 }
1304 
1305 /* Helper to complete a primitive */
1307  wmOperator *op,
1308  wmWindow *win,
1309  tGPDprimitive *tgpi)
1310 {
1311  bGPDframe *gpf;
1312  bGPDstroke *gps;
1313 
1314  ToolSettings *ts = tgpi->scene->toolsettings;
1315  Brush *brush = tgpi->brush;
1316  BrushGpencilSettings *brush_settings = brush->gpencil_settings;
1317 
1318  const int def_nr = tgpi->ob->actdef - 1;
1319  const bool have_weight = (bool)BLI_findlink(&tgpi->ob->defbase, def_nr);
1320 
1321  /* return to normal cursor and header status */
1324 
1325  /* insert keyframes as required... */
1326  short add_frame_mode;
1327  if (IS_AUTOKEY_ON(tgpi->scene)) {
1329  add_frame_mode = GP_GETFRAME_ADD_COPY;
1330  }
1331  else {
1332  add_frame_mode = GP_GETFRAME_ADD_NEW;
1333  }
1334  }
1335  else {
1336  add_frame_mode = GP_GETFRAME_USE_PREV;
1337  }
1338 
1339  bool need_tag = tgpi->gpl->actframe == NULL;
1340  gpf = BKE_gpencil_layer_frame_get(tgpi->gpl, tgpi->cframe, add_frame_mode);
1341  /* Only if there wasn't an active frame, need update. */
1342  if (need_tag) {
1344  }
1345 
1346  /* prepare stroke to get transferred */
1347  gps = tgpi->gpf->strokes.first;
1348  if (gps) {
1349  gps->thickness = brush->size;
1350  gps->hardeness = brush_settings->hardeness;
1351  copy_v2_v2(gps->aspect_ratio, brush_settings->aspect_ratio);
1352 
1353  /* Calc geometry data. */
1355  }
1356 
1357  /* transfer stroke from temporary buffer to the actual frame */
1360  }
1361  else {
1362  BLI_movelisttolist(&gpf->strokes, &tgpi->gpf->strokes);
1363  }
1365 
1366  /* add weights if required */
1367  if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
1369  for (int i = 0; i < gps->totpoints; i++) {
1370  MDeformVert *ve = &gps->dvert[i];
1371  MDeformWeight *dw = BKE_defvert_ensure_index(ve, def_nr);
1372  if (dw) {
1373  dw->weight = ts->vgroup_weight;
1374  }
1375  }
1376  }
1377 
1378  /* Join previous stroke. */
1381  if (gps->prev != NULL) {
1382  int pt_index = 0;
1383  bool doit = true;
1384  while (doit && gps) {
1386  C, &tgpi->gsc, tgpi->gpl, gpf, gps, GPENCIL_MINIMUM_JOIN_DIST, &pt_index);
1387  if (gps_target != NULL) {
1388  gps = ED_gpencil_stroke_join_and_trim(tgpi->gpd, gpf, gps, gps_target, pt_index);
1389  }
1390  else {
1391  doit = false;
1392  }
1393  }
1394  }
1396  }
1398  }
1399 
1400  /* In Multiframe mode, duplicate the stroke in other frames. */
1401  if (GPENCIL_MULTIEDIT_SESSIONS_ON(tgpi->gpd)) {
1402  const bool tail = (ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK);
1403  BKE_gpencil_stroke_copy_to_keyframes(tgpi->gpd, tgpi->gpl, gpf, gps, tail);
1404  }
1405 
1408 
1409  /* clean up temp data */
1411 }
1412 
1413 /* edit event handling */
1415  bContext *C, wmOperator *op, wmWindow *win, const wmEvent *event, tGPDprimitive *tgpi)
1416 {
1417  /* calculate nearest point then set cursor */
1418  int move = MOVE_NONE;
1419  float a = len_v2v2(tgpi->mval, tgpi->start);
1420  float b = len_v2v2(tgpi->mval, tgpi->end);
1421 
1422  float c = len_v2v2(tgpi->mval, tgpi->cp1);
1423  float d = len_v2v2(tgpi->mval, tgpi->cp2);
1424 
1425  if (tgpi->flag == IN_CURVE_EDIT) {
1426  if ((a < BIG_SIZE_CTL && tgpi->tot_stored_edges == 0) || b < BIG_SIZE_CTL) {
1427  move = MOVE_ENDS;
1429  }
1430  else if (tgpi->curve) {
1431  move = MOVE_CP;
1433  }
1434  else {
1436  }
1437  }
1438  else if (tgpi->flag == IN_PROGRESS) {
1440  }
1441 
1442  switch (event->type) {
1443  case LEFTMOUSE: {
1444  if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) {
1445  /* set control points and enter edit mode */
1446  if (ELEM(tgpi->type, GP_STROKE_POLYLINE)) {
1448  copy_v2_v2(tgpi->start, tgpi->end);
1449  copy_v2_v2(tgpi->origin, tgpi->start);
1451 
1452  tgpi->flag = IN_POLYLINE;
1454  }
1455  else {
1456  tgpi->flag = IN_CURVE_EDIT;
1458  gpencil_primitive_update(C, op, tgpi);
1459  }
1460  }
1461  else if ((event->val == KM_PRESS) && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) {
1462  /* find nearest cp based on stroke end points */
1463  if (move == MOVE_ENDS) {
1464  tgpi->sel_cp = (a < b) ? SELECT_START : SELECT_END;
1465  }
1466  else if (move == MOVE_CP) {
1467  tgpi->sel_cp = (c < d) ? SELECT_CP1 : SELECT_CP2;
1468  }
1469  else {
1470  tgpi->sel_cp = SELECT_NONE;
1471  }
1472  break;
1473  }
1474  else {
1475  tgpi->sel_cp = SELECT_NONE;
1476  }
1477  break;
1478  }
1479  case MOUSEMOVE: {
1480  if ((event->val == KM_PRESS) && tgpi->sel_cp != SELECT_NONE) {
1481  if (tgpi->sel_cp == SELECT_START && tgpi->tot_stored_edges == 0) {
1482  copy_v2_v2(tgpi->start, tgpi->mval);
1483  }
1484  else if (tgpi->sel_cp == SELECT_END) {
1485  copy_v2_v2(tgpi->end, tgpi->mval);
1486  }
1487  else if (tgpi->sel_cp == SELECT_CP1 ||
1488  (tgpi->sel_cp == SELECT_CP2 && tgpi->type != GP_STROKE_CURVE)) {
1489  float dx = (tgpi->mval[0] - tgpi->mvalo[0]);
1490  float dy = (tgpi->mval[1] - tgpi->mvalo[1]);
1491  tgpi->cp1[0] += dx;
1492  tgpi->cp1[1] += dy;
1493  if (event->shift) {
1494  copy_v2_v2(tgpi->cp2, tgpi->cp1);
1495  }
1496  }
1497  else if (tgpi->sel_cp == SELECT_CP2) {
1498  float dx = (tgpi->mval[0] - tgpi->mvalo[0]);
1499  float dy = (tgpi->mval[1] - tgpi->mvalo[1]);
1500  tgpi->cp2[0] += dx;
1501  tgpi->cp2[1] += dy;
1502  if (event->shift) {
1503  copy_v2_v2(tgpi->cp1, tgpi->cp2);
1504  }
1505  }
1506  /* update screen */
1507  gpencil_primitive_update(C, op, tgpi);
1508  }
1509  break;
1510  }
1511  case EVT_MKEY: {
1512  if ((event->val == KM_PRESS) && (tgpi->curve) && (ELEM(tgpi->orign_type, GP_STROKE_ARC))) {
1513  tgpi->flip ^= 1;
1515  gpencil_primitive_update(C, op, tgpi);
1516  }
1517  break;
1518  }
1519  case EVT_EKEY: {
1520  if (tgpi->flag == IN_CURVE_EDIT && !ELEM(tgpi->type, GP_STROKE_BOX, GP_STROKE_CIRCLE)) {
1521  tgpi->flag = IN_PROGRESS;
1524  copy_v2_v2(tgpi->start, tgpi->end);
1525  copy_v2_v2(tgpi->origin, tgpi->start);
1527  }
1528  break;
1529  }
1530  }
1531 }
1532 
1533 /* brush strength */
1535 {
1536  Brush *brush = tgpi->brush;
1537  BrushGpencilSettings *brush_settings = brush->gpencil_settings;
1538 
1539  if (brush) {
1540  if (reset) {
1541  brush_settings->draw_strength = tgpi->brush_strength;
1542  tgpi->brush_strength = 0.0f;
1543  }
1544  else {
1545  if (tgpi->brush_strength == 0.0f) {
1546  tgpi->brush_strength = brush_settings->draw_strength;
1547  }
1548  float move[2];
1549  sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo);
1550  float adjust = (move[1] > 0.0f) ? 0.01f : -0.01f;
1551  brush_settings->draw_strength += adjust * fabsf(len_manhattan_v2(move));
1552  }
1553 
1554  /* limit low limit because below 0.2f the stroke is invisible */
1555  CLAMP(brush_settings->draw_strength, 0.2f, 1.0f);
1556  }
1557 }
1558 
1559 /* brush size */
1561 {
1562  Brush *brush = tgpi->brush;
1563  if (brush) {
1564  if (reset) {
1565  brush->size = tgpi->brush_size;
1566  tgpi->brush_size = 0;
1567  }
1568  else {
1569  if (tgpi->brush_size == 0) {
1570  tgpi->brush_size = brush->size;
1571  }
1572  float move[2];
1573  sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo);
1574  int adjust = (move[1] > 0.0f) ? 1 : -1;
1575  brush->size += adjust * (int)fabsf(len_manhattan_v2(move));
1576  }
1577  CLAMP_MIN(brush->size, 1);
1578  }
1579 }
1580 
1581 /* move */
1583 {
1584  float move[2];
1585  zero_v2(move);
1586 
1587  if (reset) {
1588  sub_v2_v2(move, tgpi->move);
1589  zero_v2(tgpi->move);
1590  }
1591  else {
1592  sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo);
1593  add_v2_v2(tgpi->move, move);
1594  }
1595 
1596  bGPDstroke *gps = tgpi->gpf->strokes.first;
1597  tGPspoint *points2D = tgpi->points;
1598 
1599  for (int i = 0; i < gps->totpoints; i++) {
1600  tGPspoint *p2d = &points2D[i];
1601  add_v2_v2(&p2d->x, move);
1602  }
1603 
1604  add_v2_v2(tgpi->start, move);
1605  add_v2_v2(tgpi->end, move);
1606  add_v2_v2(tgpi->cp1, move);
1607  add_v2_v2(tgpi->cp2, move);
1608  add_v2_v2(tgpi->origin, move);
1609 }
1610 
1611 /* Modal handler: Events handling during interactive part */
1612 static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *event)
1613 {
1614  tGPDprimitive *tgpi = op->customdata;
1615  wmWindow *win = CTX_wm_window(C);
1616  const bool has_numinput = hasNumInput(&tgpi->num);
1617 
1618  copy_v2fl_v2i(tgpi->mval, event->mval);
1619 
1620  if (tgpi->flag == IN_MOVE) {
1621 
1622  switch (event->type) {
1623  case MOUSEMOVE: {
1624  gpencil_primitive_move(tgpi, false);
1625  gpencil_primitive_update(C, op, tgpi);
1626  break;
1627  }
1628  case EVT_ESCKEY:
1629  case LEFTMOUSE: {
1630  zero_v2(tgpi->move);
1631  tgpi->flag = IN_CURVE_EDIT;
1632  break;
1633  }
1634  case RIGHTMOUSE: {
1635  if (event->val == KM_RELEASE) {
1636  tgpi->flag = IN_CURVE_EDIT;
1637  gpencil_primitive_move(tgpi, true);
1638  gpencil_primitive_update(C, op, tgpi);
1639  }
1640  break;
1641  }
1642  }
1643  copy_v2_v2(tgpi->mvalo, tgpi->mval);
1644  return OPERATOR_RUNNING_MODAL;
1645  }
1646 
1647  if (tgpi->flag == IN_POLYLINE) {
1648 
1649  switch (event->type) {
1650 
1651  case EVT_ESCKEY: {
1652  /* return to normal cursor and header status */
1655 
1656  /* clean up temp data */
1658 
1659  /* canceled! */
1660  return OPERATOR_CANCELLED;
1661  }
1662  case LEFTMOUSE: {
1663  if (event->val == KM_PRESS) {
1666 
1667  gpencil_primitive_update(C, op, tgpi);
1668  copy_v2_v2(tgpi->start, tgpi->end);
1669  copy_v2_v2(tgpi->origin, tgpi->end);
1670  }
1671  break;
1672  }
1673  case EVT_SPACEKEY: /* confirm */
1674  case MIDDLEMOUSE:
1675  case EVT_RETKEY:
1676  case RIGHTMOUSE: {
1677  if (event->val == KM_PRESS) {
1678  tgpi->flag = IDLE;
1679  int last_edges = tgpi->tot_edges;
1680  tgpi->tot_edges = tgpi->tot_stored_edges ? 1 : 0;
1681  RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
1683  gpencil_primitive_interaction_end(C, op, win, tgpi);
1684  RNA_int_set(op->ptr, "edges", last_edges);
1685  return OPERATOR_FINISHED;
1686  }
1687  break;
1688  }
1689  case MOUSEMOVE: {
1691  copy_v2_v2(tgpi->end, tgpi->mval);
1692 
1693  if (event->shift) {
1694  gpencil_primitive_constrain(tgpi, true);
1695  }
1696 
1697  gpencil_primitive_update(C, op, tgpi);
1698  break;
1699  }
1700  case EVT_PADPLUSKEY:
1701  case WHEELUPMOUSE: {
1702  if ((event->val != KM_RELEASE)) {
1703  tgpi->tot_edges = tgpi->tot_edges + 1;
1705  RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
1706  gpencil_primitive_update(C, op, tgpi);
1707  }
1708  break;
1709  }
1710  case EVT_PADMINUS:
1711  case WHEELDOWNMOUSE: {
1712  if ((event->val != KM_RELEASE)) {
1713  tgpi->tot_edges = tgpi->tot_edges - 1;
1715  RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
1716  gpencil_primitive_update(C, op, tgpi);
1717  }
1718  break;
1719  }
1720  case EVT_FKEY: /* brush thickness/ brush strength */
1721  {
1722  if ((event->val == KM_PRESS)) {
1723  if (event->shift) {
1724  tgpi->prev_flag = tgpi->flag;
1725  tgpi->flag = IN_BRUSH_STRENGTH;
1726  }
1727  else {
1728  tgpi->prev_flag = tgpi->flag;
1729  tgpi->flag = IN_BRUSH_SIZE;
1730  }
1732  }
1733  break;
1734  }
1735  }
1736 
1737  copy_v2_v2(tgpi->mvalo, tgpi->mval);
1738  return OPERATOR_RUNNING_MODAL;
1739  }
1740 
1741  if (tgpi->flag == IN_BRUSH_SIZE) {
1742  switch (event->type) {
1743  case MOUSEMOVE:
1744  gpencil_primitive_size(tgpi, false);
1745  gpencil_primitive_update(C, op, tgpi);
1746  break;
1747  case EVT_ESCKEY:
1748  case MIDDLEMOUSE:
1749  case LEFTMOUSE:
1750  tgpi->brush_size = 0;
1751  tgpi->flag = tgpi->prev_flag;
1752  break;
1753  case RIGHTMOUSE:
1754  if (event->val == KM_RELEASE) {
1755  tgpi->flag = tgpi->prev_flag;
1756  gpencil_primitive_size(tgpi, true);
1757  gpencil_primitive_update(C, op, tgpi);
1758  }
1759  break;
1760  }
1761  copy_v2_v2(tgpi->mvalo, tgpi->mval);
1762  return OPERATOR_RUNNING_MODAL;
1763  }
1764 
1765  if (tgpi->flag == IN_BRUSH_STRENGTH) {
1766  switch (event->type) {
1767  case MOUSEMOVE:
1768  gpencil_primitive_strength(tgpi, false);
1769  gpencil_primitive_update(C, op, tgpi);
1770  break;
1771  case EVT_ESCKEY:
1772  case MIDDLEMOUSE:
1773  case LEFTMOUSE:
1774  tgpi->brush_strength = 0.0f;
1775  tgpi->flag = tgpi->prev_flag;
1776  break;
1777  case RIGHTMOUSE:
1778  if (event->val == KM_RELEASE) {
1779  tgpi->flag = tgpi->prev_flag;
1780  gpencil_primitive_strength(tgpi, true);
1781  gpencil_primitive_update(C, op, tgpi);
1782  }
1783  break;
1784  }
1785  copy_v2_v2(tgpi->mvalo, tgpi->mval);
1786  return OPERATOR_RUNNING_MODAL;
1787  }
1788 
1789  if (!ELEM(tgpi->flag, IDLE) && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) {
1790  gpencil_primitive_edit_event_handling(C, op, win, event, tgpi);
1791  }
1792 
1793  switch (event->type) {
1794  case LEFTMOUSE: {
1795  if ((event->val == KM_PRESS) && (tgpi->flag == IDLE)) {
1796  /* start drawing primitive */
1797  /* TODO: Ignore if not in main region yet */
1798  tgpi->flag = IN_PROGRESS;
1800  if (ELEM(tgpi->type, GP_STROKE_POLYLINE)) {
1801  tgpi->flag = IN_POLYLINE;
1802  gpencil_primitive_update(C, op, tgpi);
1803  return OPERATOR_RUNNING_MODAL;
1804  }
1805  }
1806  else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) &&
1807  (!ELEM(tgpi->type, GP_STROKE_POLYLINE))) {
1808  /* set control points and enter edit mode */
1809  tgpi->flag = IN_CURVE_EDIT;
1811  gpencil_primitive_update(C, op, tgpi);
1812  }
1813  else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) &&
1815  /* stop drawing primitive */
1816  tgpi->flag = IDLE;
1817  gpencil_primitive_interaction_end(C, op, win, tgpi);
1818  /* done! */
1819  return OPERATOR_FINISHED;
1820  }
1821  else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) &&
1822  (ELEM(tgpi->type, GP_STROKE_POLYLINE))) {
1823  /* set control points and enter edit mode */
1824  tgpi->flag = IN_POLYLINE;
1825  gpencil_primitive_update(C, op, tgpi);
1826  copy_v2_v2(tgpi->mvalo, tgpi->mval);
1827  return OPERATOR_RUNNING_MODAL;
1828  }
1829  else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_MOVE)) {
1830  tgpi->flag = IN_CURVE_EDIT;
1831  }
1832  else {
1833  if (G.debug & G_DEBUG) {
1834  printf("GP Add Primitive Modal: LEFTMOUSE %d, Status = %d\n", event->val, tgpi->flag);
1835  }
1836  }
1837  break;
1838  }
1839  case EVT_SPACEKEY: /* confirm */
1840  case MIDDLEMOUSE:
1841  case EVT_PADENTER:
1842  case EVT_RETKEY: {
1843  tgpi->flag = IDLE;
1844  gpencil_primitive_interaction_end(C, op, win, tgpi);
1845  /* done! */
1846  return OPERATOR_FINISHED;
1847  }
1848  case RIGHTMOUSE: {
1849  /* exception to cancel current stroke when we have previous strokes in buffer */
1850  if (tgpi->tot_stored_edges > 0) {
1851  tgpi->flag = IDLE;
1852  tgpi->tot_edges = tgpi->tot_stored_edges ? 1 : 0;
1854  gpencil_primitive_interaction_end(C, op, win, tgpi);
1855  /* done! */
1856  return OPERATOR_FINISHED;
1857  }
1859  }
1860  case EVT_ESCKEY: {
1861  /* return to normal cursor and header status */
1864 
1865  /* clean up temp data */
1867 
1868  /* canceled! */
1869  return OPERATOR_CANCELLED;
1870  }
1871  case EVT_PADPLUSKEY:
1872  case WHEELUPMOUSE: {
1873  if ((event->val != KM_RELEASE)) {
1874  tgpi->tot_edges = tgpi->tot_edges + 1;
1876  RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
1877 
1878  /* update screen */
1879  gpencil_primitive_update(C, op, tgpi);
1880  }
1881  break;
1882  }
1883  case EVT_PADMINUS:
1884  case WHEELDOWNMOUSE: {
1885  if ((event->val != KM_RELEASE)) {
1886  tgpi->tot_edges = tgpi->tot_edges - 1;
1888  RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
1889 
1890  /* update screen */
1891  gpencil_primitive_update(C, op, tgpi);
1892  }
1893  break;
1894  }
1895  case EVT_GKEY: /* grab mode */
1896  {
1897  if ((event->val == KM_PRESS)) {
1898  tgpi->flag = IN_MOVE;
1900  }
1901  break;
1902  }
1903  case EVT_FKEY: /* brush thickness/ brush strength */
1904  {
1905  if ((event->val == KM_PRESS)) {
1906  if (event->shift) {
1907  tgpi->prev_flag = tgpi->flag;
1908  tgpi->flag = IN_BRUSH_STRENGTH;
1909  }
1910  else {
1911  tgpi->prev_flag = tgpi->flag;
1912  tgpi->flag = IN_BRUSH_SIZE;
1913  }
1915  }
1916  break;
1917  }
1918  case EVT_CKEY: /* curve mode */
1919  {
1920  if ((event->val == KM_PRESS) && (tgpi->orign_type == GP_STROKE_CURVE)) {
1921  switch (tgpi->type) {
1922  case GP_STROKE_CURVE:
1923  tgpi->type = GP_STROKE_ARC;
1924  break;
1925  default:
1926  case GP_STROKE_ARC:
1927  tgpi->type = GP_STROKE_CURVE;
1928  break;
1929  }
1930 
1931  RNA_enum_set(op->ptr, "type", tgpi->type);
1933  gpencil_primitive_update(C, op, tgpi);
1934  }
1935  break;
1936  }
1937  case EVT_TABKEY: {
1938  if (tgpi->flag == IN_CURVE_EDIT) {
1939  tgpi->flag = IN_PROGRESS;
1942  gpencil_primitive_update(C, op, tgpi);
1943  }
1944  break;
1945  }
1946  case MOUSEMOVE: /* calculate new position */
1947  {
1948  if (ELEM(tgpi->flag, IN_CURVE_EDIT)) {
1949  break;
1950  }
1951  /* only handle mousemove if not doing numinput */
1952  if (has_numinput == false) {
1953  /* update position of mouse */
1954  copy_v2_v2(tgpi->end, tgpi->mval);
1955  copy_v2_v2(tgpi->start, tgpi->origin);
1956  if (tgpi->flag == IDLE) {
1957  copy_v2_v2(tgpi->origin, tgpi->mval);
1958  }
1959  /* Keep square if shift key */
1960  if (event->shift) {
1962  tgpi, (ELEM(tgpi->type, GP_STROKE_LINE, GP_STROKE_POLYLINE) || tgpi->curve));
1963  }
1964  /* Center primitive if alt key */
1965  if (event->alt && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) {
1966  tgpi->start[0] = tgpi->origin[0] - (tgpi->end[0] - tgpi->origin[0]);
1967  tgpi->start[1] = tgpi->origin[1] - (tgpi->end[1] - tgpi->origin[1]);
1968  }
1970  /* update screen */
1971  gpencil_primitive_update(C, op, tgpi);
1972  }
1973  break;
1974  }
1975  default: {
1976  if (tgpi->flag != IN_CURVE_EDIT && (event->val == KM_PRESS) &&
1977  handleNumInput(C, &tgpi->num, event)) {
1978  float value;
1979 
1980  /* Grab data from numeric input, and store this new value (the user see an int) */
1981  value = tgpi->tot_edges;
1982  applyNumInput(&tgpi->num, &value);
1983  tgpi->tot_edges = value;
1984 
1986  RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
1987 
1988  /* update screen */
1989  gpencil_primitive_update(C, op, tgpi);
1990 
1991  break;
1992  }
1993 
1994  /* unhandled event - allow to pass through */
1996  }
1997  }
1998 
1999  copy_v2_v2(tgpi->mvalo, tgpi->mval);
2000  /* still running... */
2001  return OPERATOR_RUNNING_MODAL;
2002 }
2003 
2004 /* Cancel handler */
2006 {
2007  /* this is just a wrapper around exit() */
2009 }
2010 
2012 {
2013  PropertyRNA *prop;
2014 
2015  prop = RNA_def_int(ot->srna,
2016  "subdivision",
2017  subdiv,
2018  0,
2019  MAX_EDGES,
2020  "Subdivisions",
2021  "Number of subdivision by edges",
2022  0,
2023  MAX_EDGES);
2025 
2026  /* Internal prop. */
2027  prop = RNA_def_int(ot->srna,
2028  "edges",
2029  MIN_EDGES,
2030  MIN_EDGES,
2031  MAX_EDGES,
2032  "Edges",
2033  "Number of points by edge",
2034  MIN_EDGES,
2035  MAX_EDGES);
2037 
2038  RNA_def_enum(ot->srna, "type", gpencil_primitive_type, type, "Type", "Type of shape");
2039 
2040  prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
2042 }
2043 
2045 {
2046  /* identifiers */
2047  ot->name = "Grease Pencil Box Shape";
2048  ot->idname = "GPENCIL_OT_primitive_box";
2049  ot->description = "Create predefined grease pencil stroke box shapes";
2050 
2051  /* callbacks */
2056 
2057  /* flags */
2059 
2060  /* properties */
2062 }
2063 
2065 {
2066  /* identifiers */
2067  ot->name = "Grease Pencil Line Shape";
2068  ot->idname = "GPENCIL_OT_primitive_line";
2069  ot->description = "Create predefined grease pencil stroke lines";
2070 
2071  /* callbacks */
2076 
2077  /* flags */
2079 
2080  /* properties */
2082 }
2083 
2085 {
2086  /* identifiers */
2087  ot->name = "Grease Pencil Polyline Shape";
2088  ot->idname = "GPENCIL_OT_primitive_polyline";
2089  ot->description = "Create predefined grease pencil stroke polylines";
2090 
2091  /* callbacks */
2096 
2097  /* flags */
2099 
2100  /* properties */
2102 }
2103 
2105 {
2106  /* identifiers */
2107  ot->name = "Grease Pencil Circle Shape";
2108  ot->idname = "GPENCIL_OT_primitive_circle";
2109  ot->description = "Create predefined grease pencil stroke circle shapes";
2110 
2111  /* callbacks */
2116 
2117  /* flags */
2119 
2120  /* properties */
2122 }
2123 
2125 {
2126  /* identifiers */
2127  ot->name = "Grease Pencil Curve Shape";
2128  ot->idname = "GPENCIL_OT_primitive_curve";
2129  ot->description = "Create predefined grease pencil stroke curve shapes";
2130 
2131  /* callbacks */
2136 
2137  /* flags */
2139 
2140  /* properties */
2142 }
typedef float(TangentPoint)[2]
void BKE_brush_gpencil_paint_presets(struct Main *bmain, struct ToolSettings *ts, const bool reset)
Definition: brush.c:1308
#define BKE_brush_tool_set(brush, p, tool)
Definition: BKE_brush.h:144
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1200
float BKE_curvemapping_evaluateF(const struct CurveMapping *cumap, int cur, float value)
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 bGPDlayer * CTX_data_active_gpencil_layer(const bContext *C)
Definition: context.c:1376
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
@ G_DEBUG
Definition: BKE_global.h:133
bool BKE_gpencil_free_strokes(struct bGPDframe *gpf)
Definition: gpencil.c:425
struct bGPDlayer * BKE_gpencil_layer_active_get(struct bGPdata *gpd)
Definition: gpencil.c:1650
void BKE_gpencil_stroke_select_index_reset(struct bGPDstroke *gps)
Definition: gpencil.c:1210
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 Material * BKE_gpencil_object_material_ensure_from_active_input_toolsettings(struct Main *bmain, struct Object *ob, struct ToolSettings *ts)
Definition: gpencil.c:1925
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
#define GPENCIL_STRENGTH_MIN
Definition: BKE_gpencil.h:178
struct bGPDlayer * BKE_gpencil_layer_addnew(struct bGPdata *gpd, const char *name, bool setactive)
Definition: gpencil.c:659
@ 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)
void BKE_gpencil_stroke_copy_to_keyframes(struct bGPdata *gpd, struct bGPDlayer *gpl, struct bGPDframe *gpf, struct bGPDstroke *gps, const bool tail)
General operations, lookup, etc. for materials.
short BKE_object_material_slot_find_index(struct Object *ob, struct Material *ma)
Definition: material.c:1064
void BKE_paint_brush_set(struct Paint *paint, struct Brush *br)
Definition: paint.c:609
struct Brush * BKE_paint_toolslots_brush_get(struct Paint *paint, int slot_index)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define ATTR_FALLTHROUGH
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void void void void BLI_movelisttolist_reverse(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define M_PI_2
Definition: BLI_math_base.h:41
MINLINE float square_f(float a)
#define M_PI
Definition: BLI_math_base.h:38
int interp_sparse_array(float *array, const int list_size, const float skipval)
Definition: math_geom.c:4182
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void loc_eul_size_to_mat4(float R[4][4], const float loc[3], const float eul[3], const float size[3])
Definition: math_matrix.c:2653
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])
void interp_v2_v2v2(float r[2], const float a[2], const float b[2], const float t)
Definition: math_vector.c:32
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void rotate_v2_v2fl(float r[2], const float p[2], const float angle)
Definition: math_vector.c:914
MINLINE void sub_v2_v2(float r[2], const float a[2])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v2_v2_int(int r[2], const int a[2])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE float len_manhattan_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
void mid_v2_v2v2(float r[2], const float a[2], const float b[2])
Definition: math_vector.c:277
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void zero_v2(float r[2])
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v2(float r[2])
void interp_v2_v2v2v2v2_cubic(float p[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2], const float u)
Definition: math_vector.c:168
MINLINE void copy_v2_fl(float r[2], float f)
Random number functions.
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition: rand.cc:76
struct RNG * BLI_rng_new(unsigned int seed)
Definition: rand.cc:54
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: rand.cc:120
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned int uint
Definition: BLI_sys_types.h:83
#define ELEM(...)
#define CLAMP_MIN(a, b)
#define TIP_(msgid)
#define DATA_(msgid)
void DEG_id_tag_update(struct ID *id, int flag)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:599
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:654
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ GP_BRUSH_USE_STRENGTH_RAND_PRESS
@ GP_BRUSH_USE_STRENGTH_AT_STROKE
@ GP_BRUSH_USE_PRESS_AT_STROKE
@ GP_BRUSH_USE_PRESSURE_RAND_PRESS
@ GP_BRUSH_GROUP_RANDOM
@ GP_BRUSH_USE_STRENGTH_PRESSURE
@ GP_BRUSH_USE_JITTER_PRESSURE
@ GP_STROKE_SELECT
@ GP_STROKE_CYCLIC
@ GP_STROKE_3DSPACE
#define GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)
@ GP_LAYER_LOCKED
@ GP_LAYER_HIDE
@ GP_DATA_STROKE_PAINTMODE
@ GP_DATA_STROKE_EDITMODE
Object is a sort of wrapper for general info.
@ GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE
#define CFRA
@ GP_PROJECT_VIEWSPACE
@ GP_PROJECT_DEPTH_VIEW
@ GP_PROJECT_DEPTH_STROKE_ENDPOINTS
@ GP_PROJECT_DEPTH_STROKE
@ GP_PROJECT_DEPTH_STROKE_FIRST
@ GP_TOOL_FLAG_RETAIN_LAST
@ GP_TOOL_FLAG_PAINT_ONBACK
@ GP_TOOL_FLAG_AUTOMERGE_STROKE
@ GP_TOOL_FLAG_CREATE_WEIGHTS
@ SPACE_VIEW3D
#define RV3D_CAMOB
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ OP_IS_MODAL_CURSOR_REGION
#define GPENCIL_MINIMUM_JOIN_DIST
Definition: ED_gpencil.h:65
#define IS_AUTOKEY_ON(scene)
void outputNumInput(NumInput *n, char *str, struct UnitSettings *unit_settings)
Definition: numinput.c:102
#define NUM_STR_REP_LEN
Definition: ED_numinput.h:27
bool applyNumInput(NumInput *n, float *vec)
Definition: numinput.c:207
bool hasNumInput(const NumInput *n)
Definition: numinput.c:185
bool handleNumInput(struct bContext *C, NumInput *n, const struct wmEvent *event)
void ED_workspace_status_text(struct bContext *C, const char *str)
Definition: area.c:840
@ V3D_DEPTH_NO_GPENCIL
Definition: ED_view3d.h:148
@ V3D_DEPTH_GPENCIL_ONLY
Definition: ED_view3d.h:149
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
_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 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 y
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
Group RGB to Bright Vector Camera CLAMP
Platform independent time functions.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
@ PROP_HIDDEN
Definition: RNA_types.h:202
#define C
Definition: RandGen.cpp:39
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:90
@ TH_REDALERT
Definition: UI_resources.h:50
@ TH_GIZMO_PRIMARY
Definition: UI_resources.h:321
@ TH_GIZMO_SECONDARY
Definition: UI_resources.h:322
void UI_GetThemeColor4fv(int colorid, float col[4])
Definition: resources.c:1199
@ OPTYPE_BLOCKING
Definition: WM_types.h:157
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define NA_EDITED
Definition: WM_types.h:462
#define KM_PRESS
Definition: WM_types.h:242
#define NC_GPENCIL
Definition: WM_types.h:300
#define KM_RELEASE
Definition: WM_types.h:243
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
void reset()
clear internal cached data and reset random seed
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
Scene scene
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)
@ GP_STROKE_POLYLINE
@ GP_STROKE_CURVE
@ GP_STROKE_ARC
@ GP_STROKE_CIRCLE
@ GP_STROKE_LINE
@ GP_STROKE_BOX
void gpencil_stroke_convertcoords_tpoint(struct Scene *scene, struct ARegion *region, struct Object *ob, const struct tGPspoint *point2D, float *depth, float out[3])
static void gpencil_primitive_cancel(bContext *C, wmOperator *op)
static void gpencil_primitive_update(bContext *C, wmOperator *op, tGPDprimitive *tgpi)
static void gpencil_primitive_common_props(wmOperatorType *ot, int subdiv, int type)
#define SELECT_NONE
#define SELECT_END
void GPENCIL_OT_primitive_line(wmOperatorType *ot)
#define SELECT_START
void GPENCIL_OT_primitive_curve(wmOperatorType *ot)
static const EnumPropertyItem gpencil_primitive_type[]
static void gpencil_primitive_rotate_line(float va[2], float vb[2], const float a[2], const float b[2], const float angle)
#define IN_MOVE
static void gpencil_primitive_strength(tGPDprimitive *tgpi, bool reset)
#define MAX_EDGES
static void gpencil_primitive_circle(tGPDprimitive *tgpi, tGPspoint *points2D)
static void gpencil_primitive_rectangle(tGPDprimitive *tgpi, tGPspoint *points2D)
#define SELECT_CP1
static void gpencil_primitive_init(bContext *C, wmOperator *op)
static void gpencil_primitive_update_cps(tGPDprimitive *tgpi)
#define SELECT_CP2
static void gpencil_rotate_v2_v2v2fl(float v[2], const float p[2], const float origin[2], const float angle)
static int gpencil_primitive_invoke(bContext *C, wmOperator *op, const wmEvent *event)
#define MOVE_CP
static void gpencil_primitive_add_segment(tGPDprimitive *tgpi)
static void gpencil_primitive_set_cp(tGPDprimitive *tgpi, const float p[2], float color[4], int size)
#define MOVE_NONE
#define IN_PROGRESS
static void gpencil_session_validatebuffer(tGPDprimitive *p)
static void gpencil_primitive_size(tGPDprimitive *tgpi, bool reset)
static void gpencil_primitive_interaction_end(bContext *C, wmOperator *op, wmWindow *win, tGPDprimitive *tgpi)
#define SMALL_SIZE_CTL
void GPENCIL_OT_primitive_polyline(wmOperatorType *ot)
#define MIN_EDGES
static void gpencil_init_colors(tGPDprimitive *p)
static bool gpencil_primitive_add_poll(bContext *C)
#define IN_CURVE_EDIT
#define BIG_SIZE_CTL
static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void gpencil_primitive_interaction_begin(tGPDprimitive *tgpi, const wmEvent *event)
#define IDLE
static void gpencil_primitive_arc(tGPDprimitive *tgpi, tGPspoint *points2D)
void GPENCIL_OT_primitive_box(wmOperatorType *ot)
#define MAX_CP
static void gpencil_primitive_bezier(tGPDprimitive *tgpi, tGPspoint *points2D)
static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi)
#define IN_BRUSH_STRENGTH
#define IN_POLYLINE
static void gpencil_primitive_edit_event_handling(bContext *C, wmOperator *op, wmWindow *win, const wmEvent *event, tGPDprimitive *tgpi)
static void gpencil_primitive_allocate_memory(tGPDprimitive *tgpi)
static void gpencil_primitive_to_square(tGPDprimitive *tgpi, const float x, const float y)
static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
static void gpencil_primitive_constrain(tGPDprimitive *tgpi, bool line_mode)
static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
static void gpencil_primitive_exit(bContext *C, wmOperator *op)
static void gpencil_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D, bool editable)
#define MOVE_ENDS
void GPENCIL_OT_primitive_circle(wmOperatorType *ot)
#define IN_BRUSH_SIZE
static void gpencil_primitive_move(tGPDprimitive *tgpi, bool reset)
void ED_gpencil_stroke_close_by_distance(bGPDstroke *gps, const float threshold)
void ED_gpencil_project_point_to_plane(const Scene *scene, const Object *ob, bGPDlayer *gpl, const RegionView3D *rv3d, const float origin[3], const int axis, bGPDspoint *pt)
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)
bGPDstroke * ED_gpencil_stroke_join_and_trim(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *gps_dst, const int pt_index)
void ED_gpencil_fill_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDstroke *gps)
void ED_gpencil_init_random_settings(Brush *brush, const int mval[2], GpRandomSettings *random_settings)
void ED_gpencil_sbuffer_update_eval(bGPdata *gpd, Object *ob_eval)
void ED_gpencil_point_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDspoint *pt, tGPspoint *tpt)
void ED_gpencil_tpoint_to_point(ARegion *region, float origin[3], const tGPspoint *tpt, bGPDspoint *pt)
void ED_gpencil_drawing_reference_get(const Scene *scene, const Object *ob, char align_flag, float r_vec[3])
void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph, Object *ob, ToolSettings *ts, Brush *brush, Material *material, float random_color[3], float pen_pressure)
bGPDstroke * ED_gpencil_stroke_nearest_to_ends(bContext *C, GP_SpaceConversion *gsc, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, const float radius, int *r_index)
tGPspoint * ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array, int *buffer_size, int *buffer_used, const bool clear)
#define UINT_MAX
Definition: hash_md5.c:58
#define sinf(x)
#define cosf(x)
#define atan2f(x, y)
#define fabsf(x)
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 c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
static void area(int d1, int d2, int e1, int e2, float weights[2])
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6319
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
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
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3585
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
void * regiondata
struct CurveMapping * curve_strength
struct CurveMapping * curve_jitter
struct CurveMapping * curve_rand_pressure
struct CurveMapping * curve_rand_strength
struct BrushGpencilSettings * gpencil_settings
struct CurveMapping * cur_primitive
void * first
Definition: DNA_listBase.h:47
struct MDeformWeight * dw
Definition: BKE_main.h:116
ListBase defbase
unsigned short actdef
struct Brush * brush
struct ToolSettings * toolsettings
struct UnitSettings unit
ListBase spacedata
GpPaint * gp_paint
struct GP_Sculpt_Settings gp_sculpt
ListBase strokes
bGPDframe * actframe
float layer_mat[4][4]
float layer_invmat[4][4]
float rotation[3]
float scale[3]
float location[3]
struct bGPDstroke * prev
bGPDspoint * points
float fill_opacity_fac
float aspect_ratio[2]
bGPDtriangle * triangles
struct MDeformVert * dvert
bGPDcontrolpoint * cp_points
float zdepth_offset
bGPdata_Runtime runtime
struct Object * ob
tGPspoint * points
struct ScrArea * area
struct bGPdata * gpd
struct Scene * scene
struct Object * ob_eval
struct Depsgraph * depsgraph
struct RNG * rng
struct Brush * brush
struct wmWindow * win
GP_SpaceConversion gsc
struct bGPDlayer * gpl
GpRandomSettings random_settings
struct bGPDframe * gpf
struct Main * bmain
struct ARegion * region
struct Material * material
float midpoint[2]
struct View3D * v3d
struct RegionView3D * rv3d
float x
Definition: ED_gpencil.h:97
float y
Definition: ED_gpencil.h:97
float pressure
Definition: ED_gpencil.h:99
float uv_rot
Definition: ED_gpencil.h:107
bool rnd_dirty
Definition: ED_gpencil.h:111
float time
Definition: ED_gpencil.h:103
float strength
Definition: ED_gpencil.h:101
float rnd[3]
Definition: ED_gpencil.h:109
float uv_fac
Definition: ED_gpencil.h:105
short shift
Definition: WM_types.h:618
short val
Definition: WM_types.h:579
int mval[2]
Definition: WM_types.h:583
short alt
Definition: WM_types.h:618
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
long int PIL_check_seconds_timer_i(void)
Definition: time.c:90
#define G(x, y, z)
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
@ WM_CURSOR_HAND
Definition: wm_cursors.h:40
@ WM_CURSOR_NSEW_SCROLL
Definition: wm_cursors.h:67
@ WM_CURSOR_CROSS
Definition: wm_cursors.h:42
@ WM_CURSOR_NS_SCROLL
Definition: wm_cursors.h:68
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ RIGHTMOUSE
@ EVT_EKEY
@ EVT_FKEY
@ EVT_CKEY
@ EVT_GKEY
@ EVT_TABKEY
@ WHEELUPMOUSE
@ EVT_PADENTER
@ EVT_SPACEKEY
@ WHEELDOWNMOUSE
@ MOUSEMOVE
@ EVT_MKEY
@ EVT_PADMINUS
@ LEFTMOUSE
@ MIDDLEMOUSE
@ EVT_ESCKEY
@ EVT_PADPLUSKEY
@ EVT_RETKEY
wmOperatorType * ot
Definition: wm_files.c:3156