Blender  V3.3
transform_convert_gpencil.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include "DNA_gpencil_types.h"
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "BLI_ghash.h"
13 #include "BLI_listbase.h"
14 #include "BLI_math.h"
15 
16 #include "BKE_colortools.h"
17 #include "BKE_context.h"
18 #include "BKE_curve.h"
19 #include "BKE_gpencil.h"
20 #include "BKE_gpencil_curve.h"
21 #include "BKE_gpencil_geom.h"
22 
23 #include "ED_gpencil.h"
24 #include "ED_keyframing.h"
25 
26 #include "transform.h"
27 #include "transform_convert.h"
28 
29 /* -------------------------------------------------------------------- */
33 static void createTransGPencil_center_get(bGPDstroke *gps, float r_center[3])
34 {
35  bGPDspoint *pt;
36  int i;
37 
38  zero_v3(r_center);
39  int tot_sel = 0;
40  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
41  if (pt->flag & GP_SPOINT_SELECT) {
42  add_v3_v3(r_center, &pt->x);
43  tot_sel++;
44  }
45  }
46 
47  if (tot_sel > 0) {
48  mul_v3_fl(r_center, 1.0f / tot_sel);
49  }
50 }
51 
52 static short get_bezt_sel_triple_flag(BezTriple *bezt, const bool handles_visible)
53 {
54 #define SEL_F1 (1 << 0)
55 #define SEL_F2 (1 << 1)
56 #define SEL_F3 (1 << 2)
57 #define SEL_ALL ((1 << 0) | (1 << 1) | (1 << 2))
58 
59  short flag = 0;
60 
61  if (handles_visible) {
62  flag = ((bezt->f1 & SELECT) ? SEL_F1 : 0) | ((bezt->f2 & SELECT) ? SEL_F2 : 0) |
63  ((bezt->f3 & SELECT) ? SEL_F3 : 0);
64  }
65  else if (bezt->f2 & SELECT) {
66  flag = SEL_ALL;
67  }
68 
69  /* Special case for auto & aligned handles */
70  if ((flag != SEL_ALL) && (flag & SEL_F2)) {
71  if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) && ELEM(bezt->h2, HD_AUTO, HD_ALIGN)) {
72  flag = SEL_ALL;
73  }
74  }
75 
76 #undef SEL_F1
77 #undef SEL_F2
78 #undef SEL_F3
79  return flag;
80 }
81 
83  TransInfo *t,
85  ToolSettings *ts,
86  Object *obact,
87  bGPdata *gpd,
88  const int cfra_scene,
89  const bool is_multiedit,
90  const bool use_multiframe_falloff,
91  const bool is_prop_edit,
92  const bool is_prop_edit_connected,
93  const bool is_scale_thickness)
94 {
95 #define SEL_F1 (1 << 0)
96 #define SEL_F2 (1 << 1)
97 #define SEL_F3 (1 << 2)
98 
99  View3D *v3d = t->view;
101  const bool handle_only_selected_visible = (v3d->overlay.handle_display == CURVE_HANDLE_SELECTED);
102  const bool handle_all_visible = (v3d->overlay.handle_display == CURVE_HANDLE_ALL);
103 
105  tc->data_len = 0;
106 
107  /* Number of selected curve points */
108  uint32_t tot_curve_points = 0, tot_sel_curve_points = 0, tot_points = 0, tot_sel_points = 0;
109  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
110  /* Only editable and visible layers are considered. */
111  if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
112  bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
113  for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
114  if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
115  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
116  /* skip strokes that are invalid for current view */
117  if (ED_gpencil_stroke_can_use(C, gps) == false) {
118  continue;
119  }
120  /* Check if the color is editable. */
121  if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
122  continue;
123  }
124  /* Check if stroke has an editcurve */
125  if (gps->editcurve == NULL) {
126  continue;
127  }
128 
129  bGPDcurve *gpc = gps->editcurve;
130  for (int i = 0; i < gpc->tot_curve_points; i++) {
131  bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
132  BezTriple *bezt = &gpc_pt->bezt;
133  if (bezt->hide) {
134  continue;
135  }
136 
137  const bool handles_visible = (handle_all_visible ||
138  (handle_only_selected_visible &&
139  (gpc_pt->flag & GP_CURVE_POINT_SELECT)));
140 
141  const short sel_flag = get_bezt_sel_triple_flag(bezt, handles_visible);
142  if (sel_flag & (SEL_F1 | SEL_F2 | SEL_F3)) {
143  if (sel_flag & SEL_F1) {
144  tot_sel_points++;
145  }
146  if (sel_flag & SEL_F2) {
147  tot_sel_points++;
148  }
149  if (sel_flag & SEL_F3) {
150  tot_sel_points++;
151  }
152  tot_sel_curve_points++;
153  }
154 
155  if (is_prop_edit) {
156  tot_points += 3;
157  tot_curve_points++;
158  }
159  }
160  }
161  }
162 
163  /* If not multi-edit out of loop. */
164  if (!is_multiedit) {
165  break;
166  }
167  }
168  }
169  }
170 
171  if (((is_prop_edit && !is_prop_edit_connected) ? tot_curve_points : tot_sel_points) == 0) {
172  tc->data_len = 0;
173  return;
174  }
175 
176  int data_len_pt = 0;
177 
178  if (is_prop_edit) {
179  tc->data_len = tot_points;
180  data_len_pt = tot_curve_points;
181  }
182  else {
183  tc->data_len = tot_sel_points;
184  data_len_pt = tot_sel_curve_points;
185  }
186 
187  if (tc->data_len == 0) {
188  return;
189  }
190 
192 
193  tc->data = MEM_callocN(tc->data_len * sizeof(TransData), __func__);
194  TransData *td = tc->data;
195 
196  const bool use_around_origins_for_handles_test = ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
198 
199  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
200  /* Only editable and visible layers are considered. */
201  if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
202  const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
203  bGPDframe *gpf = gpl->actframe;
204  bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
205  float diff_mat[4][4], mtx[3][3];
206  float smtx[3][3];
207 
208  /* Init multiframe falloff options. */
209  int f_init = 0;
210  int f_end = 0;
211 
212  if (use_multiframe_falloff) {
213  BKE_gpencil_frame_range_selected(gpl, &f_init, &f_end);
214  }
215 
216  if ((gpf->framenum != cfra) && (!is_multiedit)) {
217  if (IS_AUTOKEY_ON(scene)) {
218  gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
219  }
220  /* in some weird situations (framelock enabled) return NULL */
221  if (gpf == NULL) {
222  continue;
223  }
224  if (!is_multiedit) {
225  init_gpf = gpf;
226  }
227  }
228 
229  /* Calculate difference matrix. */
230  BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
231  copy_m3_m4(mtx, diff_mat);
233 
234  for (gpf = init_gpf; gpf; gpf = gpf->next) {
235  if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
236  /* If multi-frame and falloff, recalculate and save value. */
237  float falloff = 1.0f; /* by default no falloff */
238  if ((is_multiedit) && (use_multiframe_falloff)) {
239  /* Falloff depends on distance to active frame
240  * (relative to the overall frame range). */
242  gpf, gpl->actframe->framenum, f_init, f_end, ts->gp_sculpt.cur_falloff);
243  }
244 
245  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
246  /* skip strokes that are invalid for current view */
247  if (ED_gpencil_stroke_can_use(C, gps) == false) {
248  continue;
249  }
250  /* Check if the color is editable. */
251  if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
252  continue;
253  }
254  /* Check if stroke has an editcurve */
255  if (gps->editcurve == NULL) {
256  continue;
257  }
258  TransData *head, *tail;
259  head = tail = td;
260 
261  gps->runtime.multi_frame_falloff = falloff;
262  bool need_handle_recalc = false;
263 
264  bGPDcurve *gpc = gps->editcurve;
265  const bool is_cyclic = gps->flag & GP_STROKE_CYCLIC;
266  for (int i = 0; i < gpc->tot_curve_points; i++) {
267  bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
268  BezTriple *bezt = &gpc_pt->bezt;
269  if (bezt->hide) {
270  continue;
271  }
272 
274  bool bezt_use = false;
275  const bool handles_visible = (handle_all_visible ||
276  (handle_only_selected_visible &&
277  (gpc_pt->flag & GP_CURVE_POINT_SELECT)));
278  const short sel_flag = get_bezt_sel_triple_flag(bezt, handles_visible);
279  /* Iterate over bezier triple */
280  for (int j = 0; j < 3; j++) {
281  bool is_ctrl_point = (j == 1);
282  bool sel = sel_flag & (1 << j);
283 
284  if (is_prop_edit || sel) {
285  copy_v3_v3(td->iloc, bezt->vec[j]);
286  td->loc = bezt->vec[j];
287  bool rotate_around_ctrl = !handles_visible ||
288  (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
289  (bezt->f2 & SELECT);
290  copy_v3_v3(td->center, bezt->vec[rotate_around_ctrl ? 1 : j]);
291 
292  if (!handles_visible || is_ctrl_point) {
293  if (bezt->f2 & SELECT) {
294  td->flag = TD_SELECTED;
295  }
296  else {
297  td->flag = 0;
298  }
299  }
300  else if (handles_visible) {
301  if (sel) {
302  td->flag = TD_SELECTED;
303  }
304  else {
305  td->flag = 0;
306  }
307  }
308 
309  td->ext = NULL;
310  if (is_ctrl_point) {
311  if (t->mode != TFM_MIRROR) {
312  if (t->mode != TFM_GPENCIL_OPACITY) {
313  if (is_scale_thickness) {
314  td->val = &(gpc_pt->pressure);
315  td->ival = gpc_pt->pressure;
316  }
317  }
318  else {
319  td->val = &(gpc_pt->strength);
320  td->ival = gpc_pt->strength;
321  }
322  }
323  }
324  else {
325  td->val = NULL;
326  }
327 
328  if (hdata == NULL) {
329  if (is_ctrl_point && ((sel_flag & SEL_F1 & SEL_F3) == 0)) {
330  hdata = initTransDataCurveHandles(td, bezt);
331  }
332  else if (!is_ctrl_point) {
333  hdata = initTransDataCurveHandles(td, bezt);
334  }
335  }
336 
337  td->extra = gps;
338  td->ob = obact;
339 
340  copy_m3_m3(td->smtx, smtx);
341  copy_m3_m3(td->mtx, mtx);
342  copy_m3_m3(td->axismtx, mtx);
343 
344  td++;
345  tail++;
346  }
347 
348  bezt_use |= sel;
349  }
350 
351  /* Update the handle types so transformation is possible */
352  if (bezt_use && !ELEM(t->mode, TFM_GPENCIL_OPACITY, TFM_GPENCIL_SHRINKFATTEN)) {
354  bezt, SELECT, handles_visible, use_around_origins_for_handles_test);
355  need_handle_recalc = true;
356  }
357  }
358 
359  if (is_prop_edit && (head != tail)) {
360  calc_distanceCurveVerts(head, tail - 1, is_cyclic);
361  }
362 
363  if (need_handle_recalc) {
365  }
366  }
367  }
368 
369  /* If not multi-edit out of loop. */
370  if (!is_multiedit) {
371  break;
372  }
373  }
374  }
375  }
376 #undef SEL_F1
377 #undef SEL_F2
378 #undef SEL_F3
379 }
380 
382  TransInfo *t,
384  ToolSettings *ts,
385  Object *obact,
386  bGPdata *gpd,
387  const int cfra_scene,
388  const bool is_multiedit,
389  const bool use_multiframe_falloff,
390  const bool is_prop_edit,
391  const bool is_prop_edit_connected,
392  const bool is_scale_thickness)
393 {
395  TransData *td = NULL;
396  float mtx[3][3], smtx[3][3];
397 
399  /* == Grease Pencil Strokes to Transform Data ==
400  * Grease Pencil stroke points can be a mixture of 2D (screen-space),
401  * or 3D coordinates. However, they're always saved as 3D points.
402  * For now, we just do these without creating TransData2D for the 2D
403  * strokes. This may cause issues in future though.
404  */
405  tc->data_len = 0;
406 
407  /* First Pass: Count the number of data-points required for the strokes,
408  * (and additional info about the configuration - e.g. 2D/3D?).
409  */
410  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
411  /* Only editable and visible layers are considered. */
412  if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
413  bGPDframe *gpf;
414  bGPDstroke *gps;
415  bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
416 
417  for (gpf = init_gpf; gpf; gpf = gpf->next) {
418  if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
419  for (gps = gpf->strokes.first; gps; gps = gps->next) {
420  /* skip strokes that are invalid for current view */
421  if (ED_gpencil_stroke_can_use(C, gps) == false) {
422  continue;
423  }
424  /* Check if the color is editable. */
425  if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
426  continue;
427  }
428 
429  if (is_prop_edit) {
430  /* Proportional Editing... */
431  if (is_prop_edit_connected) {
432  /* Connected only - so only if selected. */
433  if (gps->flag & GP_STROKE_SELECT) {
434  tc->data_len += gps->totpoints;
435  }
436  }
437  else {
438  /* Everything goes - connection status doesn't matter. */
439  tc->data_len += gps->totpoints;
440  }
441  }
442  else {
443  /* Only selected stroke points are considered. */
444  if (gps->flag & GP_STROKE_SELECT) {
445  bGPDspoint *pt;
446  int i;
447 
448  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
449  if (pt->flag & GP_SPOINT_SELECT) {
450  tc->data_len++;
451  }
452  }
453  }
454  }
455  }
456  }
457  /* If not multi-edit out of loop. */
458  if (!is_multiedit) {
459  break;
460  }
461  }
462  }
463  }
464 
465  /* Stop trying if nothing selected. */
466  if (tc->data_len == 0) {
467  return;
468  }
469 
470  /* Allocate memory for data */
471  tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(GPencil)");
472  td = tc->data;
473 
474  unit_m3(smtx);
475  unit_m3(mtx);
476 
477  /* Second Pass: Build transdata array. */
478  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
479  /* only editable and visible layers are considered */
480  if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
481  const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
482  bGPDframe *gpf = gpl->actframe;
483  float diff_mat[3][3];
484  float inverse_diff_mat[3][3];
485 
486  bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
487  /* Init multiframe falloff options. */
488  int f_init = 0;
489  int f_end = 0;
490 
491  if (use_multiframe_falloff) {
492  BKE_gpencil_frame_range_selected(gpl, &f_init, &f_end);
493  }
494 
495  /* Calculate difference matrix. */
496  {
497  float diff_mat_tmp[4][4];
498  BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat_tmp);
499  copy_m3_m4(diff_mat, diff_mat_tmp);
500  }
501 
502  /* Use safe invert for cases where the input matrix has zero axes. */
503  invert_m3_m3_safe_ortho(inverse_diff_mat, diff_mat);
504 
505  /* Make a new frame to work on if the layer's frame
506  * and the current scene frame don't match up.
507  *
508  * - This is useful when animating as it saves that "uh-oh" moment when you realize you've
509  * spent too much time editing the wrong frame...
510  */
511  if ((gpf->framenum != cfra) && (!is_multiedit)) {
512  if (IS_AUTOKEY_ON(scene)) {
513  gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
514  }
515  /* in some weird situations (framelock enabled) return NULL */
516  if (gpf == NULL) {
517  continue;
518  }
519  if (!is_multiedit) {
520  init_gpf = gpf;
521  }
522  }
523 
524  /* Loop over strokes, adding TransData for points as needed... */
525  for (gpf = init_gpf; gpf; gpf = gpf->next) {
526  if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
527 
528  /* If multi-frame and falloff, recalculate and save value. */
529  float falloff = 1.0f; /* by default no falloff */
530  if ((is_multiedit) && (use_multiframe_falloff)) {
531  /* Falloff depends on distance to active frame
532  * (relative to the overall frame range). */
534  gpf, gpl->actframe->framenum, f_init, f_end, ts->gp_sculpt.cur_falloff);
535  }
536 
537  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
538  TransData *head = td;
539  TransData *tail = td;
540  bool stroke_ok;
541 
542  /* skip strokes that are invalid for current view */
543  if (ED_gpencil_stroke_can_use(C, gps) == false) {
544  continue;
545  }
546  /* check if the color is editable */
547  if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
548  continue;
549  }
550  /* What we need to include depends on proportional editing settings... */
551  if (is_prop_edit) {
552  if (is_prop_edit_connected) {
553  /* A) "Connected" - Only those in selected strokes */
554  stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
555  }
556  else {
557  /* B) All points, always */
558  stroke_ok = true;
559  }
560  }
561  else {
562  /* C) Only selected points in selected strokes */
563  stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
564  }
565 
566  /* Do stroke... */
567  if (stroke_ok && gps->totpoints) {
568  bGPDspoint *pt;
569  int i;
570 
571  /* save falloff factor */
572  gps->runtime.multi_frame_falloff = falloff;
573 
574  /* calculate stroke center */
575  float center[3];
577 
578  /* add all necessary points... */
579  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
580  bool point_ok;
581 
582  /* include point? */
583  if (is_prop_edit) {
584  /* Always all points in strokes that get included. */
585  point_ok = true;
586  }
587  else {
588  /* Only selected points in selected strokes. */
589  point_ok = (pt->flag & GP_SPOINT_SELECT) != 0;
590  }
591 
592  /* do point... */
593  if (point_ok) {
594  copy_v3_v3(td->iloc, &pt->x);
595  /* Only copy center in local origins.
596  * This allows get interesting effects also when move
597  * using proportional editing. */
598  if ((gps->flag & GP_STROKE_SELECT) &&
600  copy_v3_v3(td->center, center);
601  }
602  else {
603  copy_v3_v3(td->center, &pt->x);
604  }
605 
606  td->loc = &pt->x;
607 
608  td->flag = 0;
609 
610  if (pt->flag & GP_SPOINT_SELECT) {
611  td->flag |= TD_SELECTED;
612  }
613 
614  /* For other transform modes (e.g. shrink-fatten), need to additional data
615  * but never for mirror.
616  */
617  if (t->mode != TFM_MIRROR) {
618  if (t->mode != TFM_GPENCIL_OPACITY) {
619  if (is_scale_thickness) {
620  td->val = &pt->pressure;
621  td->ival = pt->pressure;
622  }
623  }
624  else {
625  td->val = &pt->strength;
626  td->ival = pt->strength;
627  }
628  }
629 
630  /* screenspace needs special matrices... */
631  if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) ==
632  0) {
633  /* screenspace */
635  }
636  else {
637  /* configure 2D dataspace points so that they don't play up... */
638  if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) {
640  }
641  }
642  /* apply parent transformations */
643  copy_m3_m3(td->smtx, inverse_diff_mat); /* final position */
644  copy_m3_m3(td->mtx, diff_mat); /* display position */
645  copy_m3_m3(td->axismtx, diff_mat); /* axis orientation */
646 
647  /* Triangulation must be calculated again,
648  * so save the stroke for recalc function */
649  td->extra = gps;
650 
651  /* save pointer to object */
652  td->ob = obact;
653 
654  td++;
655  tail++;
656  }
657  }
658 
659  /* March over these points, and calculate the proportional editing distances */
660  if (is_prop_edit && (head != tail)) {
661  calc_distanceCurveVerts(head, tail - 1, false);
662  }
663  }
664  }
665  }
666  /* If not multi-edit out of loop. */
667  if (!is_multiedit) {
668  break;
669  }
670  }
671  }
672  }
673 }
674 
676 {
677  if (t->data_container_len == 0) {
678  return;
679  }
680 
682  const Scene *scene = CTX_data_scene(C);
684  Object *obact = OBACT(t->view_layer);
685  bGPdata *gpd = obact->data;
686  BLI_assert(gpd != NULL);
687 
688  const int cfra_scene = scene->r.cfra;
689 
690  const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
691  const bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) !=
692  0;
693 
694  const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
695  const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
696  const bool is_scale_thickness = ((t->mode == TFM_GPENCIL_SHRINKFATTEN) ||
698 
699  const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
700 
701  /* initialize falloff curve */
702  if (is_multiedit) {
704  }
705 
706  if (gpd == NULL) {
707  return;
708  }
709 
710  if (is_curve_edit) {
712  t,
713  depsgraph,
714  ts,
715  obact,
716  gpd,
717  cfra_scene,
718  is_multiedit,
719  use_multiframe_falloff,
720  is_prop_edit,
721  is_prop_edit_connected,
722  is_scale_thickness);
723  }
724  else {
726  t,
727  depsgraph,
728  ts,
729  obact,
730  gpd,
731  cfra_scene,
732  is_multiedit,
733  use_multiframe_falloff,
734  is_prop_edit,
735  is_prop_edit_connected,
736  is_scale_thickness);
737  }
738 }
739 
741 {
743  GHash *strokes = BLI_ghash_ptr_new(__func__);
744 
745  TransData *td = tc->data;
746  bGPdata *gpd = td->ob->data;
747  const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
748  for (int i = 0; i < tc->data_len; i++, td++) {
749  bGPDstroke *gps = td->extra;
750 
751  if ((gps != NULL) && (!BLI_ghash_haskey(strokes, gps))) {
752  BLI_ghash_insert(strokes, gps, gps);
753  if (is_curve_edit && gps->editcurve != NULL) {
756  }
757  /* Calc geometry data. */
759  }
760  }
761  BLI_ghash_free(strokes, NULL, NULL);
762 }
763 
767  /* flags */ (T_EDIT | T_POINTS),
768  /* createTransData */ createTransGPencil,
769  /* recalcData */ recalcData_gpencil_strokes,
770  /* special_aftertrans_update */ NULL,
771 };
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1235
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
void BKE_nurb_bezt_handle_test(struct BezTriple *bezt, eBezTriple_Flag__Alias sel_flag, bool use_handle, bool use_around_local)
Definition: curve.cc:4049
struct bGPDframe * BKE_gpencil_frame_addcopy(struct bGPDlayer *gpl, int cframe)
Definition: gpencil.c:567
float BKE_gpencil_multiframe_falloff_calc(struct bGPDframe *gpf, int actnum, int f_init, int f_end, struct CurveMapping *cur_falloff)
Definition: gpencil.c:1917
bool BKE_gpencil_layer_is_editable(const struct bGPDlayer *gpl)
void BKE_gpencil_frame_range_selected(struct bGPDlayer *gpl, int *r_initframe, int *r_endframe)
Definition: gpencil.c:1900
void BKE_gpencil_layer_transform_matrix_get(const struct Depsgraph *depsgraph, struct Object *obact, struct bGPDlayer *gpl, float diff_mat[4][4])
void BKE_gpencil_editcurve_recalculate_handles(struct bGPDstroke *gps)
void BKE_gpencil_stroke_geometry_update(struct bGPdata *gpd, struct bGPDstroke *gps)
#define BLI_assert(a)
Definition: BLI_assert.h:46
bool BLI_ghash_haskey(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:822
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:710
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:71
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
#define PSEUDOINVERSE_EPSILON
void invert_m3_m3_safe_ortho(float Ainv[3][3], const float A[3][3])
Definition: math_matrix.c:3199
void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon)
Definition: math_matrix.c:3107
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ HD_AUTO
@ HD_ALIGN
@ GP_STROKE_2DIMAGE
@ GP_STROKE_NEEDS_CURVE_UPDATE
@ GP_STROKE_SELECT
@ GP_STROKE_CYCLIC
@ GP_STROKE_2DSPACE
@ GP_STROKE_3DSPACE
#define GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)
@ GP_LAYER_FRAMELOCK
@ GP_FRAME_SELECT
#define GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)
@ GP_CURVE_POINT_SELECT
@ GP_SPOINT_SELECT
@ OB_LOCK_ROTZ
@ OB_LOCK_SCALEZ
@ OB_LOCK_LOCZ
@ GP_SCULPT_SETT_FLAG_FRAME_FALLOFF
@ GP_SCULPT_SETT_FLAG_SCALE_THICKNESS
#define OBACT(_view_layer)
@ V3D_AROUND_LOCAL_ORIGINS
@ CURVE_HANDLE_ALL
@ CURVE_HANDLE_SELECTED
#define IS_AUTOKEY_ON(scene)
@ TFM_GPENCIL_SHRINKFATTEN
Definition: ED_transform.h:48
@ TFM_GPENCIL_OPACITY
Definition: ED_transform.h:64
@ TFM_MIRROR
Definition: ED_transform.h:43
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 t
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:25
#define SELECT
Scene scene
const Depsgraph * depsgraph
static bool is_cyclic(const Nurb *nu)
bool ED_gpencil_stroke_material_editable(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps)
bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps)
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define TRANS_DATA_CONTAINER_FIRST_SINGLE(t)
unsigned int uint32_t
Definition: stdint.h:80
uint8_t h1
uint8_t f3
float vec[3][3]
uint8_t f1
uint8_t f2
uint8_t h2
struct CurveMapping * cur_falloff
void * first
Definition: DNA_listBase.h:31
void * data
struct ToolSettings * toolsettings
struct RenderData r
char transform_pivot_point
struct GP_Sculpt_Settings gp_sculpt
float smtx[3][3]
short protectflag
float axismtx[3][3]
float mtx[3][3]
TransDataExtension * ext
float * val
struct Object * ob
View3DOverlay overlay
bGPDcurve_point * curve_points
struct bGPDframe * next
ListBase strokes
bGPDspoint_Runtime runtime
bGPDspoint * points
struct bGPDcurve * editcurve
struct bGPDstroke * next
ListBase layers
void calc_distanceCurveVerts(TransData *head, TransData *tail, bool cyclic)
void transform_around_single_fallback_ex(TransInfo *t, int data_len_all)
bool transform_mode_use_local_origins(const TransInfo *t)
TransDataCurveHandleFlags * initTransDataCurveHandles(TransData *td, struct BezTriple *bezt)
conversion and adaptation of different datablocks to a common struct.
static void createTransGPencil_center_get(bGPDstroke *gps, float r_center[3])
TransConvertTypeInfo TransConvertType_GPencil
static void createTransGPencil_strokes(bContext *C, TransInfo *t, Depsgraph *depsgraph, ToolSettings *ts, Object *obact, bGPdata *gpd, const int cfra_scene, const bool is_multiedit, const bool use_multiframe_falloff, const bool is_prop_edit, const bool is_prop_edit_connected, const bool is_scale_thickness)
static short get_bezt_sel_triple_flag(BezTriple *bezt, const bool handles_visible)
#define SEL_ALL
#define SEL_F1
#define SEL_F2
static void createTransGPencil(bContext *C, TransInfo *t)
#define SEL_F3
static void createTransGPencil_curves(bContext *C, TransInfo *t, Depsgraph *depsgraph, ToolSettings *ts, Object *obact, bGPdata *gpd, const int cfra_scene, const bool is_multiedit, const bool use_multiframe_falloff, const bool is_prop_edit, const bool is_prop_edit_connected, const bool is_scale_thickness)
static void recalcData_gpencil_strokes(TransInfo *t)
@ TD_SELECTED