Blender V4.3
transform_convert.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
9#include "DNA_anim_types.h"
11#include "DNA_mesh_types.h"
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_kdtree.h"
16#include "BLI_linklist_stack.h"
17#include "BLI_listbase.h"
18#include "BLI_math_matrix.h"
19#include "BLI_math_vector.h"
20#include "BLI_math_vector.hh"
21
22#include "BKE_action.hh"
23#include "BKE_anim_data.hh"
24#include "BKE_context.hh"
25#include "BKE_global.hh"
26#include "BKE_layer.hh"
27#include "BKE_lib_id.hh"
28#include "BKE_modifier.hh"
29#include "BKE_nla.hh"
30#include "BKE_scene.hh"
31
32#include "ED_particle.hh"
33#include "ED_screen.hh"
34#include "ED_screen_types.hh"
35#include "ED_sequencer.hh"
36
37#include "ANIM_keyframing.hh"
38#include "ANIM_nla.hh"
39
40#include "UI_view2d.hh"
41
42#include "WM_types.hh"
43
45
46#include "transform.hh"
47
48/* Own include. */
49#include "transform_convert.hh"
50
51using namespace blender;
52
57
59{
60 if (data_len_all != 1) {
61 return;
62 }
64 return;
65 }
67 return;
68 }
69 if (t->flag & T_OVERRIDE_CENTER) {
70 return;
71 }
72
74}
75
80
81/* -------------------------------------------------------------------- */
85static int trans_data_compare_dist(const void *a, const void *b)
86{
87 const TransData *td_a = (const TransData *)a;
88 const TransData *td_b = (const TransData *)b;
89
90 if (td_a->dist < td_b->dist) {
91 return -1;
92 }
93 if (td_a->dist > td_b->dist) {
94 return 1;
95 }
96 return 0;
97}
98
99static int trans_data_compare_rdist(const void *a, const void *b)
100{
101 const TransData *td_a = (const TransData *)a;
102 const TransData *td_b = (const TransData *)b;
103
104 if (td_a->rdist < td_b->rdist) {
105 return -1;
106 }
107 if (td_a->rdist > td_b->rdist) {
108 return 1;
109 }
110 return 0;
111}
112
114{
115 TransData *start = tc->data;
116 int i;
117
118 for (i = 0; i < tc->data_len && start->flag & TD_SELECTED; i++) {
119 start++;
120 }
121
122 if (i < tc->data_len) {
123 if (t->flag & T_PROP_CONNECTED) {
124 qsort(start, size_t(tc->data_len) - i, sizeof(TransData), trans_data_compare_dist);
125 }
126 else {
127 qsort(start, size_t(tc->data_len) - i, sizeof(TransData), trans_data_compare_rdist);
128 }
129 }
130}
137
142{
143 TransData *sel, *unsel;
144 TransData temp;
145 unsel = tc->data;
146 sel = &tc->data[tc->data_len - 1];
147 while (sel > unsel) {
148 while (unsel->flag & TD_SELECTED) {
149 unsel++;
150 if (unsel == sel) {
151 return;
152 }
153 }
154 while (!(sel->flag & TD_SELECTED)) {
155 sel--;
156 if (unsel == sel) {
157 return;
158 }
159 }
160 temp = *unsel;
161 *unsel = *sel;
162 *sel = temp;
163 sel--;
164 unsel++;
165 }
166}
173
175 const TransData *td,
176 const bool use_island,
177 const float proj_vec[3])
178{
179 float3 r_vec;
180
181 if (use_island) {
182 if (tc->use_local_mat) {
183 mul_v3_m4v3(r_vec, tc->mat, td->iloc);
184 }
185 else {
186 mul_v3_m3v3(r_vec, td->mtx, td->iloc);
187 }
188 }
189 else {
190 if (tc->use_local_mat) {
191 mul_v3_m4v3(r_vec, tc->mat, td->center);
192 }
193 else {
194 mul_v3_m3v3(r_vec, td->mtx, td->center);
195 }
196 }
197
198 if (proj_vec) {
199 float vec_p[3];
200 project_v3_v3v3(vec_p, r_vec, proj_vec);
201 sub_v3_v3(r_vec, vec_p);
202 }
203
204 return r_vec;
205}
206
210static void set_prop_dist(TransInfo *t, const bool with_dist)
211{
212 int a;
213
214 float _proj_vec[3];
215 const float *proj_vec = nullptr;
216
217 /* Support for face-islands. */
218 const bool use_island = transdata_check_local_islands(t, t->around);
219
220 if (t->flag & T_PROP_PROJECTED) {
221 if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) {
222 RegionView3D *rv3d = static_cast<RegionView3D *>(t->region->regiondata);
223 normalize_v3_v3(_proj_vec, rv3d->viewinv[2]);
224 proj_vec = _proj_vec;
225 }
226 }
227
228 /* Count number of selected. */
229 int td_table_len = 0;
231 TransData *td = tc->data;
232 for (a = 0; a < tc->data_len; a++, td++) {
233 if (td->flag & TD_SELECTED) {
234 td_table_len++;
235 }
236 else {
237 /* By definition transform-data has selected items in beginning. */
238 break;
239 }
240 }
241 }
242
243 /* Pointers to selected's #TransData.
244 * Used to find #TransData from the index returned by #BLI_kdtree_find_nearest. */
245 TransData **td_table = static_cast<TransData **>(
246 MEM_mallocN(sizeof(*td_table) * td_table_len, __func__));
247
248 /* Create and fill KD-tree of selected's positions - in global or proj_vec space. */
249 KDTree_3d *td_tree = BLI_kdtree_3d_new(td_table_len);
250
251 int td_table_index = 0;
253 TransData *td = tc->data;
254 for (a = 0; a < tc->data_len; a++, td++) {
255 if (td->flag & TD_SELECTED) {
256 /* Initialize, it was malloced. */
257 td->rdist = 0.0f;
258
259 const float3 vec = prop_dist_loc_get(tc, td, use_island, proj_vec);
260
261 BLI_kdtree_3d_insert(td_tree, td_table_index, vec);
262 td_table[td_table_index++] = td;
263 }
264 else {
265 /* By definition transform-data has selected items in beginning. */
266 break;
267 }
268 }
269 }
270 BLI_assert(td_table_index == td_table_len);
271
272 BLI_kdtree_3d_balance(td_tree);
273
274 /* For each non-selected vertex, find distance to the nearest selected vertex. */
276 TransData *td = tc->data;
277 for (a = 0; a < tc->data_len; a++, td++) {
278 if ((td->flag & TD_SELECTED) == 0) {
279 const float3 vec = prop_dist_loc_get(tc, td, use_island, proj_vec);
280
281 KDTreeNearest_3d nearest;
282 const int td_index = BLI_kdtree_3d_find_nearest(td_tree, vec, &nearest);
283
284 td->rdist = -1.0f;
285 if (td_index != -1) {
286 td->rdist = nearest.dist;
287 if (use_island) {
288 copy_v3_v3(td->center, td_table[td_index]->center);
289 copy_m3_m3(td->axismtx, td_table[td_index]->axismtx);
290 }
291 }
292
293 if (with_dist) {
294 td->dist = td->rdist;
295 }
296 }
297 }
298 }
299
300 BLI_kdtree_3d_free(td_tree);
301 MEM_freeN(td_table);
302}
303
306/* -------------------------------------------------------------------- */
311static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
312{
313 bool changed = false;
314
315 /* Don't bother to search if no valid constraints. */
316 if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_NO_TARGET)) == 0) {
317 return changed;
318 }
319
320 /* Check if pchan has ik-constraint. */
321 LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
322 if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
323 continue;
324 }
325 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
326 bKinematicConstraint *data = static_cast<bKinematicConstraint *>(con->data);
327
328 /* Only accept if a temporary one (for auto-IK). */
329 if (data->flag & CONSTRAINT_IK_TEMP) {
330 /* `chainlen` is new `chainlen`, but is limited by maximum `chainlen`. */
331 const int old_rootbone = data->rootbone;
332 if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
333 data->rootbone = data->max_rootbone;
334 }
335 else {
336 data->rootbone = chainlen;
337 }
338 changed |= (data->rootbone != old_rootbone);
339 }
340 }
341 }
342
343 return changed;
344}
345
347{
348 Main *bmain = CTX_data_main(t->context);
349
350 short *chainlen = &t->settings->autoik_chainlen;
351
352 /* `mode` determines what change to apply to `chainlen`. */
353 if (mode == 1) {
354 /* `mode==1` is from WHEELMOUSEDOWN: increases len. */
355 (*chainlen)++;
356 }
357 else if (mode == -1) {
358 /* `mode==-1` is from WHEELMOUSEUP: decreases len. */
359 if (*chainlen > 0) {
360 (*chainlen)--;
361 }
362 else {
363 /* IK length did not change, skip updates. */
364 return;
365 }
366 }
367
368 /* Apply to all pose-channels. */
369 bool changed = false;
370
372
373 /* Sanity checks (don't assume `t->poseobj` is set, or that it is an armature). */
374 if (ELEM(nullptr, tc->poseobj, tc->poseobj->pose)) {
375 continue;
376 }
377
378 LISTBASE_FOREACH (bPoseChannel *, pchan, &tc->poseobj->pose->chanbase) {
379 changed |= pchan_autoik_adjust(pchan, *chainlen);
380 }
381 }
382
383 if (changed) {
384 /* TODO(sergey): Consider doing partial update only. */
386 }
387}
388
391/* -------------------------------------------------------------------- */
395void calc_distanceCurveVerts(TransData *head, TransData *tail, bool cyclic)
396{
397 TransData *td;
399 BLI_LINKSTACK_INIT(queue);
400 for (td = head; td <= tail; td++) {
401 if (td->flag & TD_SELECTED) {
402 td->dist = 0.0f;
403 BLI_LINKSTACK_PUSH(queue, td);
404 }
405 else {
406 td->dist = FLT_MAX;
407 }
408 }
409
410 while ((td = BLI_LINKSTACK_POP(queue))) {
411 float dist;
412 float vec[3];
413
414 TransData *next_td = nullptr;
415
416 if (td + 1 <= tail) {
417 next_td = td + 1;
418 }
419 else if (cyclic) {
420 next_td = head;
421 }
422
423 if (next_td != nullptr) {
424 sub_v3_v3v3(vec, next_td->center, td->center);
425 mul_m3_v3(head->mtx, vec);
426 dist = len_v3(vec) + td->dist;
427
428 if (dist < next_td->dist) {
429 next_td->dist = dist;
430 BLI_LINKSTACK_PUSH(queue, next_td);
431 }
432 }
433
434 next_td = nullptr;
435
436 if (td - 1 >= head) {
437 next_td = td - 1;
438 }
439 else if (cyclic) {
440 next_td = tail;
441 }
442
443 if (next_td != nullptr) {
444 sub_v3_v3v3(vec, next_td->center, td->center);
445 mul_m3_v3(head->mtx, vec);
446 dist = len_v3(vec) + td->dist;
447
448 if (dist < next_td->dist) {
449 next_td->dist = dist;
450 BLI_LINKSTACK_PUSH(queue, next_td);
451 }
452 }
453 }
454 BLI_LINKSTACK_FREE(queue);
455}
456
458{
460 td->flag |= TD_BEZTRIPLE;
461 hdata = td->hdata = static_cast<TransDataCurveHandleFlags *>(
462 MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data"));
463 hdata->ih1 = bezt->h1;
464 hdata->h1 = &bezt->h1;
465 hdata->ih2 = bezt->h2; /* In case the second is not selected. */
466 hdata->h2 = &bezt->h2;
467 return hdata;
468}
469
472/* -------------------------------------------------------------------- */
477{
478 /* NOTE(@ideasman42): Often used to clip UV's after proportional editing:
479 * In this case the radius of the proportional region can end outside the clipping area,
480 * while not ideal an elegant solution here would likely be computationally expensive
481 * as it would need to calculate the transform value that would meet the UV bounds.
482 * While it would be technically correct to handle this properly,
483 * there isn't a strong use case for it. */
484
486 TransData *td = tc->data;
487 for (int a = 0; a < tc->data_len; a++, td++) {
488 if ((td->flag & TD_SKIP) || (!td->loc)) {
489 continue;
490 }
491
492 td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), t->aspect[0]);
493 td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), t->aspect[1]);
494 }
495 }
496}
497
500/* -------------------------------------------------------------------- */
505{
506 char r_dir;
507 float center[2];
508 if (t->flag & T_MODAL) {
510 (View2D *)t->view, t->mouse.imval[0], t->mouse.imval[1], &center[0], &center[1]);
511 r_dir = (center[0] > cframe) ? 'R' : 'L';
512 {
513 /* XXX: This saves the direction in the "mirror" property to be used for redo! */
514 if (r_dir == 'R') {
515 t->flag |= T_NO_MIRROR;
516 }
517 }
518 }
519 else {
520 r_dir = (t->flag & T_NO_MIRROR) ? 'R' : 'L';
521 }
522
523 return r_dir;
524}
525
526bool FrameOnMouseSide(char side, float frame, float cframe)
527{
528 /* Both sides, so it doesn't matter. */
529 if (side == 'B') {
530 return true;
531 }
532
533 /* Only on the named side. */
534 if (side == 'R') {
535 return (frame >= cframe);
536 }
537 return (frame <= cframe);
538}
539
542/* -------------------------------------------------------------------- */
547{
548 /* Loop through constraints, checking if there's one of the mentioned
549 * constraints needing special crazy-space corrections. */
550 if (list) {
551 LISTBASE_FOREACH (bConstraint *, con, list) {
552 /* Only consider constraint if it is enabled, and has influence on result. */
553 if ((con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) == 0 && (con->enforce != 0.0f)) {
554 /* Affirmative: returns for specific constraints here. */
555 /* Constraints that require this regardless. */
556 if (ELEM(con->type,
562 {
563 return true;
564 }
565
566 /* Constraints that require this only under special conditions. */
567 if (con->type == CONSTRAINT_TYPE_CHILDOF) {
568 /* ChildOf constraint only works when using all location components, see #42256. */
569 bChildOfConstraint *data = (bChildOfConstraint *)con->data;
570
571 if ((data->flag & CHILDOF_LOCX) && (data->flag & CHILDOF_LOCY) &&
572 (data->flag & CHILDOF_LOCZ))
573 {
574 return true;
575 }
576 }
577 else if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
578 /* CopyRot constraint only does this when rotating, and offset is on. */
579 bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
580
581 if (ELEM(data->mix_mode, ROTLIKE_MIX_OFFSET, ROTLIKE_MIX_BEFORE) &&
583 {
584 return true;
585 }
586 }
587 else if (con->type == CONSTRAINT_TYPE_TRANSLIKE) {
588 /* Copy Transforms constraint only does this in the Before mode. */
589 bTransLikeConstraint *data = (bTransLikeConstraint *)con->data;
590
593 {
594 return true;
595 }
596 if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE_SPLIT) && ELEM(t->mode, TFM_ROTATION)) {
597 return true;
598 }
599 }
600 else if (con->type == CONSTRAINT_TYPE_ACTION) {
601 /* The Action constraint only does this in the Before mode. */
602 bActionConstraint *data = (bActionConstraint *)con->data;
603
604 if (ELEM(data->mix_mode, ACTCON_MIX_BEFORE, ACTCON_MIX_BEFORE_FULL) &&
606 {
607 return true;
608 }
609 if (ELEM(data->mix_mode, ACTCON_MIX_BEFORE_SPLIT) && ELEM(t->mode, TFM_ROTATION)) {
610 return true;
611 }
612 }
613 else if (con->type == CONSTRAINT_TYPE_TRANSFORM) {
614 /* Transform constraint needs it for rotation at least (r.57309),
615 * but doing so when translating may also mess things up, see: #36203. */
616 bTransformConstraint *data = (bTransformConstraint *)con->data;
617
618 if (data->to == TRANS_ROTATION) {
619 if (t->mode == TFM_ROTATION && data->mix_mode_rot == TRANS_MIXROT_BEFORE) {
620 return true;
621 }
622 }
623 }
624 }
625 }
626 }
627
628 /* No appropriate candidates found. */
629 return false;
630}
631
634/* -------------------------------------------------------------------- */
639{
640 /* NOTE: Sequencer freeing has its own function now because of a conflict
641 * with transform's order of freeing (campbell).
642 * Order changed, the sequencer stuff should go back in here. */
643
644 /* Early out when nothing happened. */
645 if (t->data_len_all == 0 || t->mode == TFM_DUMMY) {
646 return;
647 }
648
650 return;
651 }
652
655}
656
658{
659 if (t->options & CTX_CURSOR) {
660 return G_TRANSFORM_CURSOR;
661 }
662 if (t->spacetype == SPACE_SEQ) {
663 return G_TRANSFORM_SEQ;
664 }
665 if (t->spacetype == SPACE_GRAPH) {
666 return G_TRANSFORM_FCURVES;
667 }
668 if ((t->flag & T_EDIT) || (t->options & CTX_POSE_BONE)) {
669 return G_TRANSFORM_EDIT;
670 }
671 if (t->options & (CTX_OBJECT | CTX_TEXTURE_SPACE)) {
672 return G_TRANSFORM_OBJ;
673 }
674
675 return 0;
676}
677
680/* -------------------------------------------------------------------- */
685{
686 BLI_assert(ELEM(t->data_len_all, 0, -1));
687 t->data_len_all = 0;
688 int data_container_len_orig = t->data_container_len;
689 for (TransDataContainer *th_end = t->data_container - 1,
690 *tc = &t->data_container[t->data_container_len - 1];
691 tc != th_end;
692 tc--)
693 {
694 if (tc->data_len == 0) {
695 uint index = tc - t->data_container;
696 if (index + 1 != t->data_container_len) {
697 std::swap(t->data_container[index], t->data_container[t->data_container_len - 1]);
698 }
699 t->data_container_len -= 1;
700 }
701 else {
702 t->data_len_all += tc->data_len;
703 }
704 }
705 if (data_container_len_orig != t->data_container_len) {
706 t->data_container = static_cast<TransDataContainer *>(
708 }
709 return t->data_len_all;
710}
711
713{
714 /* NOTE: Proportional editing is not usable in pose mode yet #32444. */
715 /* NOTE: This `ELEM` uses more than 16 elements and so has been split. */
716 if (!(ELEM(t->data_type,
734 {
735 /* Disable proportional editing. */
736 t->options |= CTX_NO_PET;
737 t->flag &= ~T_PROP_EDIT_ALL;
738 return;
739 }
740
741 if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
743 /* Selected objects are already first, no need to presort. */
744 }
745 else {
747 }
748
750 /* Distance has already been set. */
751 }
752 else if (ELEM(t->data_type,
756 {
757 if (t->flag & T_PROP_CONNECTED) {
758 /* Already calculated by transform_convert_mesh_connectivity_distance. */
759 }
760 else {
761 set_prop_dist(t, false);
762 }
763 }
764 else if (t->data_type == &TransConvertType_MeshUV && t->flag & T_PROP_CONNECTED) {
765 /* Already calculated by uv_set_connectivity_distance. */
766 }
769 set_prop_dist(t, false);
770 }
771 else {
772 set_prop_dist(t, true);
773 }
774
776 }
777 else if (ELEM(t->obedit_type, OB_CURVES_LEGACY)) {
778 /* Needed because bezier handles can be partially selected
779 * and are still added into transform data. */
781 }
782}
783
784/* For multi object editing. */
786{
787 if (!ELEM(t->data_type,
801 {
802 /* Does not support Multi object editing. */
803 return;
804 }
805
806 const eObjectMode object_mode = eObjectMode(obact ? obact->mode : OB_MODE_OBJECT);
807 const short object_type = obact ? obact->type : -1;
808
809 if ((object_mode & OB_MODE_EDIT) || (t->data_type == &TransConvertType_GPencil) ||
811 ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE)))
812 {
813 if (t->data_container) {
815 }
816
817 Vector<Object *> local_objects;
818 if (objects.is_empty()) {
820 params.object_mode = object_mode;
821 /* Pose transform operates on `ob->pose` so don't skip duplicate object-data. */
822 params.no_dup_data = (object_mode & OB_MODE_POSE) == 0;
824 t->scene,
825 t->view_layer,
826 static_cast<const View3D *>((t->spacetype == SPACE_VIEW3D) ? t->view : nullptr),
827 &params);
828 objects = local_objects;
829 }
830
831 t->data_container = static_cast<TransDataContainer *>(
832 MEM_callocN(sizeof(*t->data_container) * objects.size(), __func__));
833 t->data_container_len = objects.size();
834
835 for (int i = 0; i < objects.size(); i++) {
837 if (!(t->flag & T_NO_MIRROR) && (objects[i]->type == OB_MESH)) {
838 tc->use_mirror_axis_x = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_X) != 0;
839 tc->use_mirror_axis_y = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Y) != 0;
840 tc->use_mirror_axis_z = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Z) != 0;
841 }
842
843 if (object_mode & OB_MODE_EDIT) {
844 tc->obedit = objects[i];
845 /* Check needed for UVs. */
846 if ((t->flag & T_2D_EDIT) == 0) {
847 tc->use_local_mat = true;
848 }
849 }
850 else if (object_mode & OB_MODE_POSE) {
851 tc->poseobj = objects[i];
852 tc->use_local_mat = true;
853 }
854 else if (t->data_type == &TransConvertType_GPencil) {
855 tc->use_local_mat = true;
856 }
858 tc->use_local_mat = true;
859 }
860
861 if (tc->use_local_mat) {
862 BLI_assert((t->flag & T_2D_EDIT) == 0);
863 copy_m4_m4(tc->mat, objects[i]->object_to_world().ptr());
864 copy_m3_m4(tc->mat3, tc->mat);
865 /* For non-invertible scale matrices, #invert_m4_m4_fallback()
866 * can still provide a valid pivot. */
868 invert_m3_m3(tc->imat3, tc->mat3);
870 }
871 /* Otherwise leave as zero. */
872 }
873 }
874}
875
876static TransConvertTypeInfo *convert_type_get(const TransInfo *t, Object **r_obj_armature)
877{
878 ViewLayer *view_layer = t->view_layer;
881
882 /* If tests must match recalc_data for correct updates. */
883 if (t->options & CTX_CURSOR) {
884 if (t->spacetype == SPACE_IMAGE) {
886 }
887
888 if (t->spacetype == SPACE_SEQ) {
890 }
891
893 }
894 if (!(t->options & CTX_PAINT_CURVE) && (t->spacetype == SPACE_VIEW3D) && ob &&
895 (ob->mode == OB_MODE_SCULPT) && ob->sculpt)
896 {
898 }
899 if (t->options & CTX_TEXTURE_SPACE) {
901 }
902 if (t->options & CTX_EDGE_DATA) {
904 }
905 if (t->options & CTX_GPENCIL_STROKES) {
906 if (t->obedit_type == OB_GREASE_PENCIL) {
908 }
909 else if (t->obedit_type == OB_GPENCIL_LEGACY) {
911 }
912 return nullptr;
913 }
914 if (t->spacetype == SPACE_IMAGE) {
915 if (t->options & CTX_MASK) {
916 return &TransConvertType_Mask;
917 }
918 if (t->options & CTX_PAINT_CURVE) {
919 if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
921 }
922 }
923 else if (t->obedit_type == OB_MESH) {
925 }
926 return nullptr;
927 }
928 if (t->spacetype == SPACE_ACTION) {
930 }
931 if (t->spacetype == SPACE_NLA) {
932 return &TransConvertType_NLA;
933 }
934 if (t->spacetype == SPACE_SEQ) {
935 if (t->options & CTX_SEQUENCER_IMAGE) {
937 }
940 }
942 }
943 if (t->spacetype == SPACE_GRAPH) {
945 }
946 if (t->spacetype == SPACE_NODE) {
947 return &TransConvertType_Node;
948 }
949 if (t->spacetype == SPACE_CLIP) {
950 if (t->options & CTX_MOVIECLIP) {
953 }
955 }
956 if (t->options & CTX_MASK) {
957 return &TransConvertType_Mask;
958 }
959 return nullptr;
960 }
961 if (t->obedit_type != -1) {
962 if (t->obedit_type == OB_MESH) {
963 if (t->mode == TFM_SKIN_RESIZE) {
965 }
968 }
969 return &TransConvertType_Mesh;
970 }
973 }
974 if (t->obedit_type == OB_LATTICE) {
976 }
977 if (t->obedit_type == OB_MBALL) {
979 }
980 if (t->obedit_type == OB_ARMATURE) {
982 }
983 if (t->obedit_type == OB_CURVES) {
985 }
986 return nullptr;
987 }
988 if (ob && (ob->mode & OB_MODE_POSE)) {
989 return &TransConvertType_Pose;
990 }
991 if (ob && (ob->mode & OB_MODE_ALL_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) {
993 if (ob_armature) {
994 *r_obj_armature = ob_armature;
995 return &TransConvertType_Pose;
996 }
997 return nullptr;
998 }
999 if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) &&
1001 {
1003 }
1004 if (ob && ((ob->mode & OB_MODE_ALL_PAINT) || (ob->mode & OB_MODE_SCULPT_CURVES))) {
1007 }
1008 return nullptr;
1009 }
1010 if (ob && (ob->mode & OB_MODE_ALL_PAINT_GPENCIL)) {
1011 /* In grease pencil all transformations must be canceled if not Object or Edit. */
1012 return nullptr;
1013 }
1015}
1016
1018{
1019 t->data_len_all = -1;
1020
1021 Object *ob_armature = nullptr;
1022 t->data_type = convert_type_get(t, &ob_armature);
1023 if (t->data_type == nullptr) {
1024 printf("edit type not implemented!\n");
1025 BLI_assert(t->data_len_all == -1);
1026 t->data_len_all = 0;
1027 return;
1028 }
1029
1030 t->flag |= eTFlag(t->data_type->flags);
1031
1032 if (ob_armature) {
1033 init_TransDataContainers(t, ob_armature, {ob_armature});
1034 }
1035 else {
1038 init_TransDataContainers(t, ob, {});
1039 }
1040
1042 t->options |= CTX_OBJECT;
1043
1044 /* Needed for correct Object.obmat after duplication, see: #62135. */
1046
1049 }
1052 }
1054 /* Check if we're transforming the camera from the camera. */
1055 if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
1056 View3D *v3d = static_cast<View3D *>(t->view);
1057 RegionView3D *rv3d = static_cast<RegionView3D *>(t->region->regiondata);
1058 if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) {
1059 /* We could have a flag to easily check an object is being transformed. */
1060 if (v3d->camera->id.tag & ID_TAG_DOIT) {
1061 t->options |= CTX_CAMERA;
1062 }
1063 }
1064 else if (v3d->ob_center && v3d->ob_center->id.tag & ID_TAG_DOIT) {
1065 t->options |= CTX_CAMERA;
1066 }
1067 }
1068 }
1069 else {
1070 if (t->data_type == &TransConvertType_Pose) {
1071 t->options |= CTX_POSE_BONE;
1072 }
1073 else if (t->data_type == &TransConvertType_Sequencer) {
1074 /* Sequencer has no use for floating point transform. */
1075 t->num.flag |= NUM_NO_FRACTION;
1076 }
1078 t->obedit_type = -1;
1079 }
1080 t->data_type->create_trans_data(C, t);
1081 }
1082
1084
1086}
1087
1090/* -------------------------------------------------------------------- */
1095{
1096 Object *ob = tc->obedit;
1097 ModifierData *md = static_cast<ModifierData *>(ob->modifiers.first);
1098
1099 for (; md; md = md->next) {
1100 if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
1102
1103 if ((mmd->flag & MOD_MIR_CLIPPING) == 0) {
1104 continue;
1105 }
1106
1107 if ((mmd->flag & (MOD_MIR_AXIS_X | MOD_MIR_AXIS_Y | MOD_MIR_AXIS_Z)) == 0) {
1108 continue;
1109 }
1110
1111 float mtx[4][4], imtx[4][4];
1112
1113 if (mmd->mirror_ob) {
1114 float obinv[4][4];
1115
1116 invert_m4_m4(obinv, mmd->mirror_ob->object_to_world().ptr());
1117 mul_m4_m4m4(mtx, obinv, ob->object_to_world().ptr());
1118 invert_m4_m4(imtx, mtx);
1119 }
1120
1121 TransData *td = tc->data;
1122 for (int i = 0; i < tc->data_len; i++, td++) {
1123 float loc[3], iloc[3];
1124
1125 if (td->loc == nullptr) {
1126 break;
1127 }
1128
1129 if (td->flag & TD_SKIP) {
1130 continue;
1131 }
1132
1133 copy_v3_v3(loc, td->loc);
1134 copy_v3_v3(iloc, td->iloc);
1135
1136 if (mmd->mirror_ob) {
1137 mul_m4_v3(mtx, loc);
1138 mul_m4_v3(mtx, iloc);
1139 }
1140
1141 bool is_clipping = false;
1142 if (mmd->flag & MOD_MIR_AXIS_X) {
1143 if (fabsf(iloc[0]) <= mmd->tolerance || loc[0] * iloc[0] < 0.0f) {
1144 loc[0] = 0.0f;
1145 is_clipping = true;
1146 }
1147 }
1148
1149 if (mmd->flag & MOD_MIR_AXIS_Y) {
1150 if (fabsf(iloc[1]) <= mmd->tolerance || loc[1] * iloc[1] < 0.0f) {
1151 loc[1] = 0.0f;
1152 is_clipping = true;
1153 }
1154 }
1155 if (mmd->flag & MOD_MIR_AXIS_Z) {
1156 if (fabsf(iloc[2]) <= mmd->tolerance || loc[2] * iloc[2] < 0.0f) {
1157 loc[2] = 0.0f;
1158 is_clipping = true;
1159 }
1160 }
1161
1162 if (is_clipping) {
1163 if (mmd->mirror_ob) {
1164 mul_m4_v3(imtx, loc);
1165 }
1166 copy_v3_v3(td->loc, loc);
1167 }
1168 }
1169 }
1170 }
1171}
1172
1174{
1175 Scene *scene = t->scene;
1176 wmTimer *animtimer = t->animtimer;
1177 ScreenAnimData *sad = static_cast<ScreenAnimData *>((animtimer) ? animtimer->customdata :
1178 nullptr);
1179
1180 /* Sanity checks. */
1181 if (ELEM(nullptr, scene, id, sad)) {
1182 return;
1183 }
1184
1185 /* Check if we need a new strip if:
1186 * - If `animtimer` is running.
1187 * - We're not only keying for available channels.
1188 * - The option to add new actions for each round is not enabled.
1189 */
1191 (scene->toolsettings->keying_flag & AUTOKEY_FLAG_LAYERED_RECORD))
1192 {
1193 /* If playback has just looped around,
1194 * we need to add a new NLA track+strip to allow a clean pass to occur. */
1195 if ((sad) && (sad->flag & ANIMPLAY_FLAG_JUMPED)) {
1196 AnimData *adt = BKE_animdata_from_id(id);
1197 const bool is_first = (adt) && (adt->nla_tracks.first == nullptr);
1198
1199 /* Perform push-down manually with some differences
1200 * NOTE: #BKE_nla_action_pushdown() sync warning. */
1201 if ((adt->action) && !(adt->flag & ADT_NLA_EDIT_ON)) {
1202 /* Only push down if action is more than 1-2 frames long. */
1203 const float2 frame_range = adt->action->wrap().get_frame_range_of_keys(true);
1204 if (frame_range[1] > frame_range[0] + 2.0f) {
1205 /* TODO: call BKE_nla_action_pushdown() instead? */
1206
1207 /* Add a new NLA strip to the track, which references the active action + slot.*/
1209 {*id, *adt}, adt->action, ID_IS_OVERRIDE_LIBRARY(id));
1210 BLI_assert(strip);
1212
1213 /* Clear reference to action now that we've pushed it onto the stack. */
1214 const bool unassign_ok = animrig::unassign_action(*id);
1216 unassign_ok,
1217 "Expecting un-assigning an action to always work when pushing down an NLA strip");
1218 UNUSED_VARS_NDEBUG(unassign_ok);
1219
1220 /* Adjust blending + extend so that they will behave correctly. */
1224
1225 /* Copy current "action blending" settings from adt to the strip,
1226 * as it was keyframed with these settings, so omitting them will
1227 * change the effect, see: #54766. */
1228 if (is_first == false) {
1229 strip->blendmode = adt->act_blendmode;
1230 strip->influence = adt->act_influence;
1231
1232 if (adt->act_influence < 1.0f) {
1233 /* Enable "user-controlled" influence (which will insert a default keyframe)
1234 * so that the influence doesn't get lost on the new update.
1235 *
1236 * NOTE: An alternative way would have been to instead hack the influence
1237 * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
1238 * is disabled but auto-blending isn't being used. However, that approach
1239 * is a bit hacky/hard to discover, and may cause backwards compatibility issues,
1240 * so it's better to just do it this way. */
1243 }
1244 }
1245
1246 /* Also, adjust the AnimData's action extend mode to be on
1247 * 'nothing' so that previous result still play. */
1249 }
1250 }
1251 }
1252 }
1253}
1254
1255void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, const float y_fac)
1256{
1257 float delta_x = td->loc[0] - td->iloc[0];
1258 float delta_y = (td->loc[1] - td->iloc[1]) * y_fac;
1259
1260 /* If the handles are to be moved too
1261 * (as side-effect of keyframes moving, to keep the general effect)
1262 * offset them by the same amount so that the general angles are maintained
1263 * (i.e. won't change while handles are free-to-roam and keyframes are snap-locked).
1264 */
1265 if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
1266 td2d->h1[0] = td2d->ih1[0] + delta_x;
1267 td2d->h1[1] = td2d->ih1[1] + delta_y;
1268 }
1269 if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
1270 td2d->h2[0] = td2d->ih2[0] + delta_x;
1271 td2d->h2[1] = td2d->ih2[1] + delta_y;
1272 }
1273}
1274
1276{
1277 if (!t->data_type || !t->data_type->recalc_data) {
1278 return;
1279 }
1280 t->data_type->recalc_data(t);
1281}
1282
Functions to insert, delete or modify keyframes.
Blender kernel action and pose functionality.
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:89
Main * CTX_data_main(const bContext *C)
@ G_TRANSFORM_OBJ
@ G_TRANSFORM_CURSOR
@ G_TRANSFORM_SEQ
@ G_TRANSFORM_EDIT
@ G_TRANSFORM_FCURVES
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_mode_params(const Scene *scene, ViewLayer *view_layer, const View3D *v3d, const ObjectsInModeParams *params)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
NlaStrip * BKE_nlastack_add_strip(OwnedAnimData owned_adt, bAction *act, bool is_liboverride)
void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
void BKE_scene_graph_evaluated_ensure(Depsgraph *depsgraph, Main *bmain)
Definition scene.cc:2573
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
A KD-tree for nearest neighbor search.
#define LISTBASE_FOREACH(type, var, list)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
void mul_m3_v3(const float M[3][3], float r[3])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void normalize_m3_m3(float R[3][3], const float M[3][3]) ATTR_NONNULL()
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void mul_m4_v3(const float M[4][4], float r[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
bool invert_m4_m4_fallback(float inverse[4][4], const float mat[4][4])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
void DEG_relations_tag_update(Main *bmain)
@ ID_TAG_DOIT
Definition DNA_ID.h:1003
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:683
@ PCHAN_HAS_NO_TARGET
@ PCHAN_HAS_IK
@ NLASTRIP_FLAG_ACTIVE
@ NLASTRIP_FLAG_USR_INFLUENCE
@ NLASTRIP_FLAG_AUTO_BLENDS
@ NLASTRIP_FLAG_SELECT
@ ADT_NLA_EDIT_ON
@ NLASTRIP_EXTEND_NOTHING
@ CONSTRAINT_OFF
@ CONSTRAINT_DISABLE
@ CONSTRAINT_IK_TEMP
@ ROTLIKE_MIX_OFFSET
@ ROTLIKE_MIX_BEFORE
@ CONSTRAINT_TYPE_CHILDOF
@ CONSTRAINT_TYPE_TRANSFORM
@ CONSTRAINT_TYPE_FOLLOWTRACK
@ CONSTRAINT_TYPE_OBJECTSOLVER
@ CONSTRAINT_TYPE_ARMATURE
@ CONSTRAINT_TYPE_ROTLIKE
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_TYPE_TRANSLIKE
@ CONSTRAINT_TYPE_CLAMPTO
@ CONSTRAINT_TYPE_ACTION
@ CONSTRAINT_TYPE_FOLLOWPATH
@ ACTCON_MIX_BEFORE
@ ACTCON_MIX_BEFORE_SPLIT
@ ACTCON_MIX_BEFORE_FULL
@ TRANSLIKE_MIX_BEFORE
@ TRANSLIKE_MIX_BEFORE_SPLIT
@ TRANSLIKE_MIX_BEFORE_FULL
@ TRANS_ROTATION
@ TRANS_MIXROT_BEFORE
@ ME_SYMMETRY_X
@ ME_SYMMETRY_Y
@ ME_SYMMETRY_Z
@ eModifierMode_Realtime
@ eModifierType_Mirror
@ MOD_MIR_AXIS_Z
@ MOD_MIR_CLIPPING
@ MOD_MIR_AXIS_X
@ MOD_MIR_AXIS_Y
#define OB_MODE_ALL_PAINT
#define OB_MODE_ALL_WEIGHT_PAINT
#define OB_MODE_ALL_PAINT_GPENCIL
eObjectMode
@ OB_MODE_PARTICLE_EDIT
@ OB_MODE_EDIT
@ OB_MODE_SCULPT
@ OB_MODE_SCULPT_CURVES
@ OB_MODE_POSE
@ OB_MODE_OBJECT
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVES_LEGACY
@ OB_GPENCIL_LEGACY
@ OB_CURVES
@ SCE_XFORM_SKIP_CHILDREN
@ SCE_XFORM_DATA_ORIGIN
@ RGN_TYPE_WINDOW
@ RGN_TYPE_PREVIEW
@ SPACE_CLIP
@ SPACE_ACTION
@ SPACE_NODE
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_IMAGE
@ SPACE_GRAPH
@ SPACE_VIEW3D
@ AUTOKEY_FLAG_LAYERED_RECORD
@ AUTOKEY_FLAG_INSERTAVAILABLE
@ V3D_AROUND_ACTIVE
@ V3D_AROUND_CENTER_BOUNDS
@ V3D_AROUND_CENTER_MEDIAN
@ V3D_AROUND_LOCAL_ORIGINS
@ RV3D_CAMOB
@ NUM_NO_FRACTION
PTCacheEdit * PE_get_current(Depsgraph *depsgraph, Scene *scene, Object *ob)
int PE_start_edit(PTCacheEdit *edit)
@ ANIMPLAY_FLAG_JUMPED
bool sequencer_retiming_mode_is_active(const bContext *C)
@ TFM_RESIZE
@ TFM_SKIN_RESIZE
@ TFM_SHEAR
@ TFM_SHRINKFATTEN
@ TFM_VERT_CREASE
@ TFM_ROTATION
@ TFM_BWEIGHT
@ TFM_TRANSLATION
@ TFM_DUMMY
@ TFM_TRACKBALL
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
Definition view2d.cc:1663
local_group_size(16, 16) .push_constant(Type b
#define printf
#define fabsf(x)
bool transdata_check_local_islands(TransInfo *t, short around)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
ActionSlotAssignmentResult assign_action_slot_handle(NlaStrip &strip, slot_handle_t slot_handle, ID &animated_id)
bool unassign_action(ID &animated_id)
bool is_keying_flag(const Scene *scene, eKeying_Flag flag)
#define FLT_MAX
Definition stdcycles.h:14
void * regiondata
bAction * action
short act_blendmode
float act_influence
int32_t slot_handle
short act_extendmode
ListBase nla_tracks
Definition DNA_ID.h:413
int tag
Definition DNA_ID.h:434
void * first
struct Object * mirror_ob
struct ModifierData * next
blender::float2 imval
Definition transform.hh:383
short blendmode
float influence
short extendmode
short flag
ListBase modifiers
struct SculptSession * sculpt
float viewinv[4][4]
void(* create_trans_data)(bContext *C, TransInfo *t)
void(* special_aftertrans_update)(bContext *C, TransInfo *t)
void(* recalc_data)(TransInfo *t)
float mat3_unit[3][3]
Definition transform.hh:469
float mat3[3][3]
Definition transform.hh:465
float mat[4][4]
Definition transform.hh:462
TransData * data
Definition transform.hh:445
float imat3[3][3]
Definition transform.hh:466
float imat[4][4]
Definition transform.hh:463
TransDataCurveHandleFlags * hdata
float axismtx[3][3]
float mtx[3][3]
eTfmMode mode
Definition transform.hh:517
short around
Definition transform.hh:580
void * view
Definition transform.hh:647
char spacetype
Definition transform.hh:582
int data_len_all
Definition transform.hh:510
wmTimer * animtimer
Definition transform.hh:657
ToolSettings * settings
Definition transform.hh:656
NumInput num
Definition transform.hh:540
float aspect[3]
Definition transform.hh:553
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
ARegion * region
Definition transform.hh:652
MouseInput mouse
Definition transform.hh:543
short obedit_type
Definition transform.hh:584
TransDataContainer * data_container
Definition transform.hh:505
Depsgraph * depsgraph
Definition transform.hh:653
bContext * context
Definition transform.hh:649
TransConvertTypeInfo * data_type
Definition transform.hh:513
eTContext options
Definition transform.hh:521
struct Object * camera
struct Object * ob_center
void * customdata
Definition WM_types.hh:922
@ CTX_MOVIECLIP
Definition transform.hh:70
@ CTX_PAINT_CURVE
Definition transform.hh:72
@ CTX_SEQUENCER_IMAGE
Definition transform.hh:75
@ CTX_CURSOR
Definition transform.hh:66
@ CTX_OBMODE_XFORM_OBDATA
Definition transform.hh:80
@ CTX_POSE_BONE
Definition transform.hh:73
@ CTX_OBMODE_XFORM_SKIP_CHILDREN
Definition transform.hh:82
@ CTX_OBJECT
Definition transform.hh:71
@ CTX_EDGE_DATA
Definition transform.hh:67
@ CTX_GPENCIL_STROKES
Definition transform.hh:68
@ CTX_MASK
Definition transform.hh:69
@ CTX_TEXTURE_SPACE
Definition transform.hh:74
@ CTX_NO_PET
Definition transform.hh:77
@ CTX_CAMERA
Definition transform.hh:65
eTFlag
Definition transform.hh:89
@ T_OVERRIDE_CENTER
Definition transform.hh:129
@ T_MODAL
Definition transform.hh:118
@ T_PROP_CONNECTED
Definition transform.hh:99
@ T_NO_MIRROR
Definition transform.hh:111
@ T_PROP_EDIT
Definition transform.hh:98
@ T_2D_EDIT
Definition transform.hh:104
@ T_EDIT
Definition transform.hh:91
@ T_PROP_PROJECTED
Definition transform.hh:100
Object * transform_object_deform_pose_armature_get(const TransInfo *t, Object *ob)
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:854
void calc_distanceCurveVerts(TransData *head, TransData *tail, bool cyclic)
void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, const float y_fac)
void transform_autoik_update(TransInfo *t, short mode)
void special_aftertrans_update(bContext *C, TransInfo *t)
void transform_convert_clip_mirror_modifier_apply(TransDataContainer *tc)
void sort_trans_data_dist(TransInfo *t)
bool FrameOnMouseSide(char side, float frame, float cframe)
void transform_around_single_fallback(TransInfo *t)
static void sort_trans_data_dist_container(const TransInfo *t, TransDataContainer *tc)
static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
void clipUVData(TransInfo *t)
static void init_proportional_edit(TransInfo *t)
void animrecord_check_state(TransInfo *t, ID *id)
static void init_TransDataContainers(TransInfo *t, Object *obact, Span< Object * > objects)
static int countAndCleanTransDataContainer(TransInfo *t)
void recalc_data(TransInfo *t)
static TransConvertTypeInfo * convert_type_get(const TransInfo *t, Object **r_obj_armature)
TransDataCurveHandleFlags * initTransDataCurveHandles(TransData *td, BezTriple *bezt)
void transform_around_single_fallback_ex(TransInfo *t, int data_len_all)
static void sort_trans_data_selected_first(TransInfo *t)
static float3 prop_dist_loc_get(const TransDataContainer *tc, const TransData *td, const bool use_island, const float proj_vec[3])
bool transform_mode_use_local_origins(const TransInfo *t)
int special_transform_moving(TransInfo *t)
bool constraints_list_needinv(TransInfo *t, ListBase *list)
static void sort_trans_data_selected_first_container(TransDataContainer *tc)
static int trans_data_compare_rdist(const void *a, const void *b)
static void set_prop_dist(TransInfo *t, const bool with_dist)
void create_trans_data(bContext *C, TransInfo *t)
char transform_convert_frame_side_dir_get(TransInfo *t, float cframe)
static int trans_data_compare_dist(const void *a, const void *b)
conversion and adaptation of different datablocks to a common struct.
TransConvertTypeInfo TransConvertType_Action
TransConvertTypeInfo TransConvertType_CursorImage
TransConvertTypeInfo TransConvertType_GPencil
TransConvertTypeInfo TransConvertType_MeshSkin
TransConvertTypeInfo TransConvertType_GreasePencil
TransConvertTypeInfo TransConvertType_TrackingCurves
TransConvertTypeInfo TransConvertType_MeshVertCData
TransConvertTypeInfo TransConvertType_Cursor3D
TransConvertTypeInfo TransConvertType_Mask
TransConvertTypeInfo TransConvertType_NLA
TransConvertTypeInfo TransConvertType_Particle
TransConvertTypeInfo TransConvertType_PaintCurve
TransConvertTypeInfo TransConvertType_Sequencer
TransConvertTypeInfo TransConvertType_MeshUV
TransConvertTypeInfo TransConvertType_CursorSequencer
TransConvertTypeInfo TransConvertType_MeshEdge
TransConvertTypeInfo TransConvertType_Sculpt
TransConvertTypeInfo TransConvertType_ObjectTexSpace
TransConvertTypeInfo TransConvertType_Tracking
TransConvertTypeInfo TransConvertType_MBall
TransConvertTypeInfo TransConvertType_Graph
TransConvertTypeInfo TransConvertType_Curve
TransConvertTypeInfo TransConvertType_Node
TransConvertTypeInfo TransConvertType_Lattice
TransConvertTypeInfo TransConvertType_SequencerRetiming
TransConvertTypeInfo TransConvertType_EditArmature
TransConvertTypeInfo TransConvertType_SequencerImage
TransConvertTypeInfo TransConvertType_Curves
TransConvertTypeInfo TransConvertType_Mesh
TransConvertTypeInfo TransConvertType_Pose
TransConvertTypeInfo TransConvertType_Object
@ TD_BEZTRIPLE
@ TD_MOVEHANDLE1
@ TD_SELECTED
@ TD_SKIP
@ TD_MOVEHANDLE2