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