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