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