Memory: Fix guarded aligned malloc with small alignment
[blender.git] / source / blender / editors / transform / transform_conversions.c
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
20 /** \file
21  * \ingroup edtransform
22  */
23
24 #include <string.h>
25 #include <math.h>
26 #include <limits.h>
27
28 #include "DNA_anim_types.h"
29 #include "DNA_brush_types.h"
30 #include "DNA_armature_types.h"
31 #include "DNA_lattice_types.h"
32 #include "DNA_mesh_types.h"
33 #include "DNA_meta_types.h"
34 #include "DNA_node_types.h"
35 #include "DNA_screen_types.h"
36 #include "DNA_space_types.h"
37 #include "DNA_sequence_types.h"
38 #include "DNA_view3d_types.h"
39 #include "DNA_constraint_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_meshdata_types.h"
42 #include "DNA_gpencil_types.h"
43 #include "DNA_movieclip_types.h"
44 #include "DNA_mask_types.h"
45
46 #include "MEM_guardedalloc.h"
47
48 #include "BLI_math.h"
49 #include "BLI_utildefines.h"
50 #include "BLI_listbase.h"
51 #include "BLI_linklist_stack.h"
52 #include "BLI_string.h"
53 #include "BLI_bitmap.h"
54 #include "BLI_rect.h"
55 #include "BLI_kdtree.h"
56
57 #include "BKE_action.h"
58 #include "BKE_animsys.h"
59 #include "BKE_armature.h"
60 #include "BKE_constraint.h"
61 #include "BKE_context.h"
62 #include "BKE_crazyspace.h"
63 #include "BKE_curve.h"
64 #include "BKE_fcurve.h"
65 #include "BKE_global.h"
66 #include "BKE_gpencil.h"
67 #include "BKE_layer.h"
68 #include "BKE_key.h"
69 #include "BKE_main.h"
70 #include "BKE_mesh.h"
71 #include "BKE_mesh_mapping.h"
72 #include "BKE_modifier.h"
73 #include "BKE_movieclip.h"
74 #include "BKE_nla.h"
75 #include "BKE_node.h"
76 #include "BKE_object.h"
77 #include "BKE_particle.h"
78 #include "BKE_paint.h"
79 #include "BKE_pointcache.h"
80 #include "BKE_report.h"
81 #include "BKE_rigidbody.h"
82 #include "BKE_scene.h"
83 #include "BKE_sequencer.h"
84 #include "BKE_editmesh.h"
85 #include "BKE_tracking.h"
86 #include "BKE_mask.h"
87 #include "BKE_colortools.h"
88
89 #include "BIK_api.h"
90
91 #include "ED_anim_api.h"
92 #include "ED_armature.h"
93 #include "ED_particle.h"
94 #include "ED_image.h"
95 #include "ED_keyframing.h"
96 #include "ED_keyframes_edit.h"
97 #include "ED_object.h"
98 #include "ED_markers.h"
99 #include "ED_mesh.h"
100 #include "ED_node.h"
101 #include "ED_uvedit.h"
102 #include "ED_clip.h"
103 #include "ED_mask.h"
104 #include "ED_gpencil.h"
105
106 #include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
107 #include "WM_types.h"
108
109 #include "UI_view2d.h"
110 #include "UI_interface.h"
111
112 #include "RNA_access.h"
113
114 #include "DEG_depsgraph.h"
115 #include "DEG_depsgraph_build.h"
116 #include "DEG_depsgraph_query.h"
117
118 #include "transform.h"
119 #include "bmesh.h"
120
121 /**
122  * Transforming around ourselves is no use, fallback to individual origins,
123  * useful for curve/armatures.
124  */
125 static void transform_around_single_fallback(TransInfo *t)
126 {
127   if ((t->data_len_all == 1) &&
128       (ELEM(t->around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEDIAN, V3D_AROUND_ACTIVE)) &&
129       (ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL))) {
130     t->around = V3D_AROUND_LOCAL_ORIGINS;
131   }
132 }
133
134 /* when transforming islands */
135 struct TransIslandData {
136   float co[3];
137   float axismtx[3][3];
138 };
139
140 /* local function prototype - for Object/Bone Constraints */
141 static bool constraints_list_needinv(TransInfo *t, ListBase *list);
142
143 /* ************************** Functions *************************** */
144
145 static int trans_data_compare_dist(const void *a, const void *b)
146 {
147   const TransData *td_a = (const TransData *)a;
148   const TransData *td_b = (const TransData *)b;
149
150   if (td_a->dist < td_b->dist) {
151     return -1;
152   }
153   else if (td_a->dist > td_b->dist) {
154     return 1;
155   }
156   else {
157     return 0;
158   }
159 }
160
161 static int trans_data_compare_rdist(const void *a, const void *b)
162 {
163   const TransData *td_a = (const TransData *)a;
164   const TransData *td_b = (const TransData *)b;
165
166   if (td_a->rdist < td_b->rdist) {
167     return -1;
168   }
169   else if (td_a->rdist > td_b->rdist) {
170     return 1;
171   }
172   else {
173     return 0;
174   }
175 }
176
177 static void sort_trans_data_dist_container(const TransInfo *t, TransDataContainer *tc)
178 {
179   TransData *start = tc->data;
180   int i;
181
182   for (i = 0; i < tc->data_len && start->flag & TD_SELECTED; i++) {
183     start++;
184   }
185
186   if (i < tc->data_len) {
187     if (t->flag & T_PROP_CONNECTED) {
188       qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_dist);
189     }
190     else {
191       qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_rdist);
192     }
193   }
194 }
195 void sort_trans_data_dist(TransInfo *t)
196 {
197   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
198     sort_trans_data_dist_container(t, tc);
199   }
200 }
201
202 /**
203  * Make #TD_SELECTED first in the array.
204  */
205 static void sort_trans_data_selected_first_container(TransDataContainer *tc)
206 {
207   TransData *sel, *unsel;
208   TransData temp;
209   unsel = tc->data;
210   sel = tc->data;
211   sel += tc->data_len - 1;
212   while (sel > unsel) {
213     while (unsel->flag & TD_SELECTED) {
214       unsel++;
215       if (unsel == sel) {
216         return;
217       }
218     }
219     while (!(sel->flag & TD_SELECTED)) {
220       sel--;
221       if (unsel == sel) {
222         return;
223       }
224     }
225     temp = *unsel;
226     *unsel = *sel;
227     *sel = temp;
228     sel--;
229     unsel++;
230   }
231 }
232 static void sort_trans_data_selected_first(TransInfo *t)
233 {
234   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
235     sort_trans_data_selected_first_container(tc);
236   }
237 }
238
239 /**
240  * Distance calculated from not-selected vertex to nearest selected vertex.
241  */
242 static void set_prop_dist(TransInfo *t, const bool with_dist)
243 {
244   int a;
245
246   float _proj_vec[3];
247   const float *proj_vec = NULL;
248
249   /* support for face-islands */
250   const bool use_island = transdata_check_local_islands(t, t->around);
251
252   if (t->flag & T_PROP_PROJECTED) {
253     if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
254       RegionView3D *rv3d = t->ar->regiondata;
255       normalize_v3_v3(_proj_vec, rv3d->viewinv[2]);
256       proj_vec = _proj_vec;
257     }
258   }
259
260   /* Count number of selected. */
261   int td_table_len = 0;
262   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
263     TransData *td = tc->data;
264     for (a = 0; a < tc->data_len; a++, td++) {
265       if (td->flag & TD_SELECTED) {
266         td_table_len++;
267       }
268       else {
269         /* By definition transform-data has selected items in beginning. */
270         break;
271       }
272     }
273   }
274
275   /* Pointers to selected's #TransData.
276    * Used to find #TransData from the index returned by #BLI_kdtree_find_nearest. */
277   TransData **td_table = MEM_mallocN(sizeof(*td_table) * td_table_len, __func__);
278
279   /* Create and fill kd-tree of selected's positions - in global or proj_vec space. */
280   KDTree_3d *td_tree = BLI_kdtree_3d_new(td_table_len);
281
282   int td_table_index = 0;
283   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
284     TransData *td = tc->data;
285     for (a = 0; a < tc->data_len; a++, td++) {
286       if (td->flag & TD_SELECTED) {
287         /* Initialize, it was mallocced. */
288         float vec[3];
289         td->rdist = 0.0f;
290
291         if (use_island) {
292           if (tc->use_local_mat) {
293             mul_v3_m4v3(vec, tc->mat, td->iloc);
294           }
295           else {
296             mul_v3_m3v3(vec, td->mtx, td->iloc);
297           }
298         }
299         else {
300           if (tc->use_local_mat) {
301             mul_v3_m4v3(vec, tc->mat, td->center);
302           }
303           else {
304             mul_v3_m3v3(vec, td->mtx, td->center);
305           }
306         }
307
308         if (proj_vec) {
309           float vec_p[3];
310           project_v3_v3v3(vec_p, vec, proj_vec);
311           sub_v3_v3(vec, vec_p);
312         }
313
314         BLI_kdtree_3d_insert(td_tree, td_table_index, vec);
315         td_table[td_table_index++] = td;
316       }
317       else {
318         /* By definition transform-data has selected items in beginning. */
319         break;
320       }
321     }
322   }
323   BLI_assert(td_table_index == td_table_len);
324
325   BLI_kdtree_3d_balance(td_tree);
326
327   /* For each non-selected vertex, find distance to the nearest selected vertex. */
328   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
329     TransData *td = tc->data;
330     for (a = 0; a < tc->data_len; a++, td++) {
331       if ((td->flag & TD_SELECTED) == 0) {
332         float vec[3];
333
334         if (use_island) {
335           if (tc->use_local_mat) {
336             mul_v3_m4v3(vec, tc->mat, td->iloc);
337           }
338           else {
339             mul_v3_m3v3(vec, td->mtx, td->iloc);
340           }
341         }
342         else {
343           if (tc->use_local_mat) {
344             mul_v3_m4v3(vec, tc->mat, td->center);
345           }
346           else {
347             mul_v3_m3v3(vec, td->mtx, td->center);
348           }
349         }
350
351         if (proj_vec) {
352           float vec_p[3];
353           project_v3_v3v3(vec_p, vec, proj_vec);
354           sub_v3_v3(vec, vec_p);
355         }
356
357         KDTreeNearest_3d nearest;
358         const int td_index = BLI_kdtree_3d_find_nearest(td_tree, vec, &nearest);
359
360         td->rdist = -1.0f;
361         if (td_index != -1) {
362           td->rdist = nearest.dist;
363           if (use_island) {
364             copy_v3_v3(td->center, td_table[td_index]->center);
365             copy_m3_m3(td->axismtx, td_table[td_index]->axismtx);
366           }
367         }
368
369         if (with_dist) {
370           td->dist = td->rdist;
371         }
372       }
373     }
374   }
375
376   BLI_kdtree_3d_free(td_tree);
377   MEM_freeN(td_table);
378 }
379
380 /* ************************** CONVERSIONS ************************* */
381
382 /* ********************* texture space ********* */
383
384 static void createTransTexspace(TransInfo *t)
385 {
386   ViewLayer *view_layer = t->view_layer;
387   TransData *td;
388   Object *ob;
389   ID *id;
390   short *texflag;
391
392   ob = OBACT(view_layer);
393
394   if (ob == NULL) {  // Shouldn't logically happen, but still...
395     return;
396   }
397
398   id = ob->data;
399   if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) {
400     BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform");
401     return;
402   }
403
404   if (BKE_object_obdata_is_libdata(ob)) {
405     BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
406     return;
407   }
408
409   {
410     BLI_assert(t->data_container_len == 1);
411     TransDataContainer *tc = t->data_container;
412     tc->data_len = 1;
413     td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
414     td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
415   }
416
417   td->flag = TD_SELECTED;
418   copy_v3_v3(td->center, ob->obmat[3]);
419   td->ob = ob;
420
421   copy_m3_m4(td->mtx, ob->obmat);
422   copy_m3_m4(td->axismtx, ob->obmat);
423   normalize_m3(td->axismtx);
424   pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
425
426   if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
427     ob->dtx |= OB_TEXSPACE;
428     *texflag &= ~ME_AUTOSPACE;
429   }
430
431   copy_v3_v3(td->iloc, td->loc);
432   copy_v3_v3(td->ext->irot, td->ext->rot);
433   copy_v3_v3(td->ext->isize, td->ext->size);
434 }
435
436 /* -------------------------------------------------------------------- */
437 /** \name Cursor Transform Creation
438  *
439  * Instead of transforming the selection, move the 2D/3D cursor.
440  *
441  * \{ */
442
443 static void createTransCursor_image(TransInfo *t)
444 {
445   TransData *td;
446   SpaceImage *sima = t->sa->spacedata.first;
447   float *cursor_location = sima->cursor;
448
449   {
450     BLI_assert(t->data_container_len == 1);
451     TransDataContainer *tc = t->data_container;
452     tc->data_len = 1;
453     td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
454     td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
455   }
456
457   td->flag = TD_SELECTED;
458   copy_v3_v3(td->center, cursor_location);
459   td->ob = NULL;
460
461   unit_m3(td->mtx);
462   unit_m3(td->axismtx);
463   pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
464
465   td->loc = cursor_location;
466   copy_v3_v3(td->iloc, cursor_location);
467 }
468
469 static void createTransCursor_view3d(TransInfo *t)
470 {
471   TransData *td;
472
473   Scene *scene = t->scene;
474   if (ID_IS_LINKED(scene)) {
475     BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
476     return;
477   }
478
479   View3DCursor *cursor = &scene->cursor;
480   {
481     BLI_assert(t->data_container_len == 1);
482     TransDataContainer *tc = t->data_container;
483     tc->data_len = 1;
484     td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
485     td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
486   }
487
488   td->flag = TD_SELECTED;
489   copy_v3_v3(td->center, cursor->location);
490   td->ob = NULL;
491
492   unit_m3(td->mtx);
493   BKE_scene_cursor_rot_to_mat3(cursor, td->axismtx);
494   normalize_m3(td->axismtx);
495   pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
496
497   td->loc = cursor->location;
498   copy_v3_v3(td->iloc, cursor->location);
499
500   if (cursor->rotation_mode > 0) {
501     td->ext->rot = cursor->rotation_euler;
502     td->ext->rotAxis = NULL;
503     td->ext->rotAngle = NULL;
504     td->ext->quat = NULL;
505
506     copy_v3_v3(td->ext->irot, cursor->rotation_euler);
507   }
508   else if (cursor->rotation_mode == ROT_MODE_AXISANGLE) {
509     td->ext->rot = NULL;
510     td->ext->rotAxis = cursor->rotation_axis;
511     td->ext->rotAngle = &cursor->rotation_angle;
512     td->ext->quat = NULL;
513
514     td->ext->irotAngle = cursor->rotation_angle;
515     copy_v3_v3(td->ext->irotAxis, cursor->rotation_axis);
516   }
517   else {
518     td->ext->rot = NULL;
519     td->ext->rotAxis = NULL;
520     td->ext->rotAngle = NULL;
521     td->ext->quat = cursor->rotation_quaternion;
522
523     copy_qt_qt(td->ext->iquat, cursor->rotation_quaternion);
524   }
525   td->ext->rotOrder = cursor->rotation_mode;
526 }
527
528 /** \} */
529
530 /* ********************* edge (for crease) ***** */
531
532 static void createTransEdge(TransInfo *t)
533 {
534   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
535
536     BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
537     TransData *td = NULL;
538     BMEdge *eed;
539     BMIter iter;
540     float mtx[3][3], smtx[3][3];
541     int count = 0, countsel = 0;
542     const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
543     int cd_edge_float_offset;
544
545     BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
546       if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
547         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
548           countsel++;
549         }
550         if (is_prop_edit) {
551           count++;
552         }
553       }
554     }
555
556     if (countsel == 0) {
557       tc->data_len = 0;
558       continue;
559     }
560
561     if (is_prop_edit) {
562       tc->data_len = count;
563     }
564     else {
565       tc->data_len = countsel;
566     }
567
568     td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransCrease");
569
570     copy_m3_m4(mtx, tc->obedit->obmat);
571     pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
572
573     /* create data we need */
574     if (t->mode == TFM_BWEIGHT) {
575       BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_BWEIGHT);
576       cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
577     }
578     else {  // if (t->mode == TFM_CREASE) {
579       BLI_assert(t->mode == TFM_CREASE);
580       BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_CREASE);
581       cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
582     }
583
584     BLI_assert(cd_edge_float_offset != -1);
585
586     BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
587       if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) &&
588           (BM_elem_flag_test(eed, BM_ELEM_SELECT) || is_prop_edit)) {
589         float *fl_ptr;
590         /* need to set center for center calculations */
591         mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
592
593         td->loc = NULL;
594         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
595           td->flag = TD_SELECTED;
596         }
597         else {
598           td->flag = 0;
599         }
600
601         copy_m3_m3(td->smtx, smtx);
602         copy_m3_m3(td->mtx, mtx);
603
604         td->ext = NULL;
605
606         fl_ptr = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_float_offset);
607         td->val = fl_ptr;
608         td->ival = *fl_ptr;
609
610         td++;
611       }
612     }
613   }
614 }
615
616 /* ********************* pose mode ************* */
617
618 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
619 {
620   bConstraint *con = pchan->constraints.first;
621
622   for (; con; con = con->next) {
623     if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
624       bKinematicConstraint *data = con->data;
625
626       if (data->tar == NULL) {
627         return data;
628       }
629       if (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0) {
630         return data;
631       }
632     }
633   }
634   return NULL;
635 }
636
637 static short apply_targetless_ik(Object *ob)
638 {
639   bPoseChannel *pchan, *parchan, *chanlist[256];
640   bKinematicConstraint *data;
641   int segcount, apply = 0;
642
643   /* now we got a difficult situation... we have to find the
644    * target-less IK pchans, and apply transformation to the all
645    * pchans that were in the chain */
646
647   for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
648     data = has_targetless_ik(pchan);
649     if (data && (data->flag & CONSTRAINT_IK_AUTO)) {
650
651       /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
652       segcount = 0;
653
654       /* exclude tip from chain? */
655       if (!(data->flag & CONSTRAINT_IK_TIP)) {
656         parchan = pchan->parent;
657       }
658       else {
659         parchan = pchan;
660       }
661
662       /* Find the chain's root & count the segments needed */
663       for (; parchan; parchan = parchan->parent) {
664         chanlist[segcount] = parchan;
665         segcount++;
666
667         if (segcount == data->rootbone || segcount > 255) {
668           break;  // 255 is weak
669         }
670       }
671       for (; segcount; segcount--) {
672         Bone *bone;
673         float rmat[4][4] /*, tmat[4][4], imat[4][4]*/;
674
675         /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK  */
676         /* we put in channel the entire result of rmat = (channel * constraint * IK) */
677         /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat  */
678         /* rmat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone ) */
679
680         parchan = chanlist[segcount - 1];
681         bone = parchan->bone;
682         bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
683
684         BKE_armature_mat_pose_to_bone(parchan, parchan->pose_mat, rmat);
685
686         /* apply and decompose, doesn't work for constraints or non-uniform scale well */
687         {
688           float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3];
689           copy_m3_m4(rmat3, rmat);
690
691           /* rotation */
692           /* [#22409] is partially caused by this, as slight numeric error introduced during
693            * the solving process leads to locked-axis values changing. However, we cannot modify
694            * the values here, or else there are huge discrepancies between IK-solver (interactive)
695            * and applied poses. */
696           BKE_pchan_mat3_to_rot(parchan, rmat3, false);
697
698           /* for size, remove rotation */
699           /* causes problems with some constraints (so apply only if needed) */
700           if (data->flag & CONSTRAINT_IK_STRETCH) {
701             BKE_pchan_rot_to_mat3(parchan, qrmat);
702             invert_m3_m3(imat3, qrmat);
703             mul_m3_m3m3(smat, rmat3, imat3);
704             mat3_to_size(parchan->size, smat);
705           }
706
707           /* causes problems with some constraints (e.g. childof), so disable this */
708           /* as it is IK shouldn't affect location directly */
709           /* copy_v3_v3(parchan->loc, rmat[3]); */
710         }
711       }
712
713       apply = 1;
714       data->flag &= ~CONSTRAINT_IK_AUTO;
715     }
716   }
717
718   return apply;
719 }
720
721 static void add_pose_transdata(
722     TransInfo *t, bPoseChannel *pchan, Object *ob, TransDataContainer *tc, TransData *td)
723 {
724   Bone *bone = pchan->bone;
725   float pmat[3][3], omat[3][3];
726   float cmat[3][3], tmat[3][3];
727   float vec[3];
728
729   copy_v3_v3(vec, pchan->pose_mat[3]);
730   copy_v3_v3(td->center, vec);
731
732   td->ob = ob;
733   td->flag = TD_SELECTED;
734   if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
735     td->flag |= TD_NOCENTER;
736   }
737
738   if (bone->flag & BONE_TRANSFORM_CHILD) {
739     td->flag |= TD_NOCENTER;
740     td->flag |= TD_NO_LOC;
741   }
742
743   td->protectflag = pchan->protectflag;
744
745   td->loc = pchan->loc;
746   copy_v3_v3(td->iloc, pchan->loc);
747
748   td->ext->size = pchan->size;
749   copy_v3_v3(td->ext->isize, pchan->size);
750
751   if (pchan->rotmode > 0) {
752     td->ext->rot = pchan->eul;
753     td->ext->rotAxis = NULL;
754     td->ext->rotAngle = NULL;
755     td->ext->quat = NULL;
756
757     copy_v3_v3(td->ext->irot, pchan->eul);
758   }
759   else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
760     td->ext->rot = NULL;
761     td->ext->rotAxis = pchan->rotAxis;
762     td->ext->rotAngle = &pchan->rotAngle;
763     td->ext->quat = NULL;
764
765     td->ext->irotAngle = pchan->rotAngle;
766     copy_v3_v3(td->ext->irotAxis, pchan->rotAxis);
767   }
768   else {
769     td->ext->rot = NULL;
770     td->ext->rotAxis = NULL;
771     td->ext->rotAngle = NULL;
772     td->ext->quat = pchan->quat;
773
774     copy_qt_qt(td->ext->iquat, pchan->quat);
775   }
776   td->ext->rotOrder = pchan->rotmode;
777
778   /* proper way to get parent transform + own transform + constraints transform */
779   copy_m3_m4(omat, ob->obmat);
780
781   /* New code, using "generic" BKE_bone_parent_transform_calc_from_pchan(). */
782   {
783     BoneParentTransform bpt;
784     float rpmat[3][3];
785
786     BKE_bone_parent_transform_calc_from_pchan(pchan, &bpt);
787     if (t->mode == TFM_TRANSLATION) {
788       copy_m3_m4(pmat, bpt.loc_mat);
789     }
790     else {
791       copy_m3_m4(pmat, bpt.rotscale_mat);
792     }
793
794     /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal,
795      * and want align snapping, we just need both loc_mat and rotscale_mat.
796      * So simply always store rotscale mat in td->ext, and always use it to apply rotations...
797      * Ugly to need such hacks! :/ */
798     copy_m3_m4(rpmat, bpt.rotscale_mat);
799
800     if (constraints_list_needinv(t, &pchan->constraints)) {
801       copy_m3_m4(tmat, pchan->constinv);
802       invert_m3_m3(cmat, tmat);
803       mul_m3_series(td->mtx, cmat, omat, pmat);
804       mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat);
805     }
806     else {
807       mul_m3_series(td->mtx, omat, pmat);
808       mul_m3_series(td->ext->r_mtx, omat, rpmat);
809     }
810     invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx);
811   }
812
813   pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
814
815   /* exceptional case: rotate the pose bone which also applies transformation
816    * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */
817   if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) &&
818       (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) {
819     if (pchan->parent) {
820       /* same as td->smtx but without pchan->bone->bone_mat */
821       td->flag |= TD_PBONE_LOCAL_MTX_C;
822       mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx);
823     }
824     else {
825       td->flag |= TD_PBONE_LOCAL_MTX_P;
826     }
827   }
828
829   /* for axismat we use bone's own transform */
830   copy_m3_m4(pmat, pchan->pose_mat);
831   mul_m3_m3m3(td->axismtx, omat, pmat);
832   normalize_m3(td->axismtx);
833
834   if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
835     bArmature *arm = tc->poseobj->data;
836
837     if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
838       td->loc = NULL;
839       td->val = &bone->dist;
840       td->ival = bone->dist;
841     }
842     else {
843       // abusive storage of scale in the loc pointer :)
844       td->loc = &bone->xwidth;
845       copy_v3_v3(td->iloc, td->loc);
846       td->val = NULL;
847     }
848   }
849
850   /* in this case we can do target-less IK grabbing */
851   if (t->mode == TFM_TRANSLATION) {
852     bKinematicConstraint *data = has_targetless_ik(pchan);
853     if (data) {
854       if (data->flag & CONSTRAINT_IK_TIP) {
855         copy_v3_v3(data->grabtarget, pchan->pose_tail);
856       }
857       else {
858         copy_v3_v3(data->grabtarget, pchan->pose_head);
859       }
860       td->loc = data->grabtarget;
861       copy_v3_v3(td->iloc, td->loc);
862       data->flag |= CONSTRAINT_IK_AUTO;
863
864       /* only object matrix correction */
865       copy_m3_m3(td->mtx, omat);
866       pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
867     }
868   }
869
870   /* store reference to first constraint */
871   td->con = pchan->constraints.first;
872 }
873
874 static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
875 {
876   Bone *bone = lb->first;
877
878   for (; bone; bone = bone->next) {
879     if ((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED)) {
880       bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
881     }
882     else if ((bone->flag & BONE_TRANSFORM) && (mode == TFM_ROTATION || mode == TFM_TRACKBALL) &&
883              (around == V3D_AROUND_LOCAL_ORIGINS)) {
884       bone->flag |= BONE_TRANSFORM_CHILD;
885     }
886     else {
887       bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
888     }
889
890     bone_children_clear_transflag(mode, around, &bone->childbase);
891   }
892 }
893
894 /* sets transform flags in the bones
895  * returns total number of bones with BONE_TRANSFORM */
896 int count_set_pose_transflags(Object *ob,
897                               const int mode,
898                               const short around,
899                               bool has_translate_rotate[2])
900 {
901   bArmature *arm = ob->data;
902   bPoseChannel *pchan;
903   Bone *bone;
904   int total = 0;
905
906   for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
907     bone = pchan->bone;
908     if (PBONE_VISIBLE(arm, bone)) {
909       if ((bone->flag & BONE_SELECTED)) {
910         bone->flag |= BONE_TRANSFORM;
911       }
912       else {
913         bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
914       }
915
916       bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
917       bone->flag &= ~BONE_TRANSFORM_CHILD;
918     }
919     else {
920       bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR);
921     }
922   }
923
924   /* make sure no bone can be transformed when a parent is transformed */
925   /* since pchans are depsgraph sorted, the parents are in beginning of list */
926   if (!ELEM(mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
927     for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
928       bone = pchan->bone;
929       if (bone->flag & BONE_TRANSFORM) {
930         bone_children_clear_transflag(mode, around, &bone->childbase);
931       }
932     }
933   }
934   /* now count, and check if we have autoIK or have to switch from translate to rotate */
935   for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
936     bone = pchan->bone;
937     if (bone->flag & BONE_TRANSFORM) {
938       total++;
939
940       if (has_translate_rotate != NULL) {
941         if (has_targetless_ik(pchan) == NULL) {
942           if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
943             if (pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
944               has_translate_rotate[0] = true;
945             }
946           }
947           else {
948             if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC) {
949               has_translate_rotate[0] = true;
950             }
951           }
952           if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT) {
953             has_translate_rotate[1] = true;
954           }
955         }
956         else {
957           has_translate_rotate[0] = true;
958         }
959       }
960     }
961   }
962
963   return total;
964 }
965
966 /* -------- Auto-IK ---------- */
967
968 /* adjust pose-channel's auto-ik chainlen */
969 static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
970 {
971   bConstraint *con;
972   bool changed = false;
973
974   /* don't bother to search if no valid constraints */
975   if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) {
976     return changed;
977   }
978
979   /* check if pchan has ik-constraint */
980   for (con = pchan->constraints.first; con; con = con->next) {
981     if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
982       bKinematicConstraint *data = con->data;
983
984       /* only accept if a temporary one (for auto-ik) */
985       if (data->flag & CONSTRAINT_IK_TEMP) {
986         /* chainlen is new chainlen, but is limited by maximum chainlen */
987         const int old_rootbone = data->rootbone;
988         if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
989           data->rootbone = data->max_rootbone;
990         }
991         else {
992           data->rootbone = chainlen;
993         }
994         changed |= (data->rootbone != old_rootbone);
995       }
996     }
997   }
998
999   return changed;
1000 }
1001
1002 /* change the chain-length of auto-ik */
1003 void transform_autoik_update(TransInfo *t, short mode)
1004 {
1005   Main *bmain = CTX_data_main(t->context);
1006
1007   short *chainlen = &t->settings->autoik_chainlen;
1008   bPoseChannel *pchan;
1009
1010   /* mode determines what change to apply to chainlen */
1011   if (mode == 1) {
1012     /* mode=1 is from WHEELMOUSEDOWN... increases len */
1013     (*chainlen)++;
1014   }
1015   else if (mode == -1) {
1016     /* mode==-1 is from WHEELMOUSEUP... decreases len */
1017     if (*chainlen > 0) {
1018       (*chainlen)--;
1019     }
1020     else {
1021       /* IK length did not change, skip updates. */
1022       return;
1023     }
1024   }
1025
1026   /* apply to all pose-channels */
1027   bool changed = false;
1028
1029   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1030
1031     /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
1032     if (ELEM(NULL, tc->poseobj, tc->poseobj->pose)) {
1033       continue;
1034     }
1035
1036     for (pchan = tc->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
1037       changed |= pchan_autoik_adjust(pchan, *chainlen);
1038     }
1039   }
1040
1041   if (changed) {
1042     /* TODO(sergey): Consider doing partial update only. */
1043     DEG_relations_tag_update(bmain);
1044   }
1045 }
1046
1047 /* frees temporal IKs */
1048 static void pose_grab_with_ik_clear(Main *bmain, Object *ob)
1049 {
1050   bKinematicConstraint *data;
1051   bPoseChannel *pchan;
1052   bConstraint *con, *next;
1053   bool relations_changed = false;
1054
1055   for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1056     /* clear all temporary lock flags */
1057     pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP | BONE_IK_NO_YDOF_TEMP | BONE_IK_NO_ZDOF_TEMP);
1058
1059     pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
1060
1061     /* remove all temporary IK-constraints added */
1062     for (con = pchan->constraints.first; con; con = next) {
1063       next = con->next;
1064       if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
1065         data = con->data;
1066         if (data->flag & CONSTRAINT_IK_TEMP) {
1067           relations_changed = true;
1068
1069           /* iTaSC needs clear for removed constraints */
1070           BIK_clear_data(ob->pose);
1071
1072           BLI_remlink(&pchan->constraints, con);
1073           MEM_freeN(con->data);
1074           MEM_freeN(con);
1075           continue;
1076         }
1077         pchan->constflag |= PCHAN_HAS_IK;
1078         if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0)) {
1079           pchan->constflag |= PCHAN_HAS_TARGET;
1080         }
1081       }
1082     }
1083   }
1084
1085   if (relations_changed) {
1086     /* TODO(sergey): Consider doing partial update only. */
1087     DEG_relations_tag_update(bmain);
1088   }
1089 }
1090
1091 /* adds the IK to pchan - returns if added */
1092 static short pose_grab_with_ik_add(bPoseChannel *pchan)
1093 {
1094   bKinematicConstraint *targetless = NULL;
1095   bKinematicConstraint *data;
1096   bConstraint *con;
1097
1098   /* Sanity check */
1099   if (pchan == NULL) {
1100     return 0;
1101   }
1102
1103   /* Rule: not if there's already an IK on this channel */
1104   for (con = pchan->constraints.first; con; con = con->next) {
1105     if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
1106       data = con->data;
1107
1108       if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == '\0')) {
1109         /* make reference to constraint to base things off later
1110          * (if it's the last targetless constraint encountered) */
1111         targetless = (bKinematicConstraint *)con->data;
1112
1113         /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
1114         if (con->enforce != 0.0f) {
1115           data->flag |= CONSTRAINT_IK_AUTO;
1116
1117           /* if no chain length has been specified,
1118            * just make things obey standard rotation locks too */
1119           if (data->rootbone == 0) {
1120             for (; pchan; pchan = pchan->parent) {
1121               /* here, we set ik-settings for bone from pchan->protectflag */
1122               // XXX: careful with quats/axis-angle rotations where we're locking 4d components
1123               if (pchan->protectflag & OB_LOCK_ROTX) {
1124                 pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
1125               }
1126               if (pchan->protectflag & OB_LOCK_ROTY) {
1127                 pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
1128               }
1129               if (pchan->protectflag & OB_LOCK_ROTZ) {
1130                 pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
1131               }
1132             }
1133           }
1134
1135           return 0;
1136         }
1137       }
1138
1139       if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) {
1140         return 0;
1141       }
1142     }
1143   }
1144
1145   con = BKE_constraint_add_for_pose(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
1146
1147   /* for draw, but also for detecting while pose solving */
1148   pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET);
1149
1150   data = con->data;
1151   if (targetless) {
1152     /* if exists, use values from last targetless (but disabled) IK-constraint as base */
1153     *data = *targetless;
1154   }
1155   else {
1156     data->flag = CONSTRAINT_IK_TIP;
1157   }
1158   data->flag |= CONSTRAINT_IK_TEMP | CONSTRAINT_IK_AUTO | CONSTRAINT_IK_POS;
1159   copy_v3_v3(data->grabtarget, pchan->pose_tail);
1160
1161   /* watch-it! has to be 0 here, since we're still on the
1162    * same bone for the first time through the loop T25885. */
1163   data->rootbone = 0;
1164
1165   /* we only include bones that are part of a continual connected chain */
1166   do {
1167     /* here, we set ik-settings for bone from pchan->protectflag */
1168     // XXX: careful with quats/axis-angle rotations where we're locking 4d components
1169     if (pchan->protectflag & OB_LOCK_ROTX) {
1170       pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
1171     }
1172     if (pchan->protectflag & OB_LOCK_ROTY) {
1173       pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
1174     }
1175     if (pchan->protectflag & OB_LOCK_ROTZ) {
1176       pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
1177     }
1178
1179     /* now we count this pchan as being included */
1180     data->rootbone++;
1181
1182     /* continue to parent, but only if we're connected to it */
1183     if (pchan->bone->flag & BONE_CONNECTED) {
1184       pchan = pchan->parent;
1185     }
1186     else {
1187       pchan = NULL;
1188     }
1189   } while (pchan);
1190
1191   /* make a copy of maximum chain-length */
1192   data->max_rootbone = data->rootbone;
1193
1194   return 1;
1195 }
1196
1197 /* bone is a candidate to get IK, but we don't do it if it has children connected */
1198 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
1199 {
1200   Bone *bonec;
1201   short wentdeeper = 0, added = 0;
1202
1203   /* go deeper if children & children are connected */
1204   for (bonec = bone->childbase.first; bonec; bonec = bonec->next) {
1205     if (bonec->flag & BONE_CONNECTED) {
1206       wentdeeper = 1;
1207       added += pose_grab_with_ik_children(pose, bonec);
1208     }
1209   }
1210   if (wentdeeper == 0) {
1211     bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
1212     if (pchan) {
1213       added += pose_grab_with_ik_add(pchan);
1214     }
1215   }
1216
1217   return added;
1218 }
1219
1220 /* main call which adds temporal IK chains */
1221 static short pose_grab_with_ik(Main *bmain, Object *ob)
1222 {
1223   bArmature *arm;
1224   bPoseChannel *pchan, *parent;
1225   Bone *bonec;
1226   short tot_ik = 0;
1227
1228   if ((ob == NULL) || (ob->pose == NULL) || (ob->mode & OB_MODE_POSE) == 0) {
1229     return 0;
1230   }
1231
1232   arm = ob->data;
1233
1234   /* Rule: allow multiple Bones
1235    * (but they must be selected, and only one ik-solver per chain should get added) */
1236   for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1237     if (pchan->bone->layer & arm->layer) {
1238       if (pchan->bone->flag & BONE_SELECTED) {
1239         /* Rule: no IK for solitatry (unconnected) bones */
1240         for (bonec = pchan->bone->childbase.first; bonec; bonec = bonec->next) {
1241           if (bonec->flag & BONE_CONNECTED) {
1242             break;
1243           }
1244         }
1245         if ((pchan->bone->flag & BONE_CONNECTED) == 0 && (bonec == NULL)) {
1246           continue;
1247         }
1248
1249         /* rule: if selected Bone is not a root bone, it gets a temporal IK */
1250         if (pchan->parent) {
1251           /* only adds if there's no IK yet (and no parent bone was selected) */
1252           for (parent = pchan->parent; parent; parent = parent->parent) {
1253             if (parent->bone->flag & BONE_SELECTED) {
1254               break;
1255             }
1256           }
1257           if (parent == NULL) {
1258             tot_ik += pose_grab_with_ik_add(pchan);
1259           }
1260         }
1261         else {
1262           /* rule: go over the children and add IK to the tips */
1263           tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
1264         }
1265       }
1266     }
1267   }
1268
1269   /* iTaSC needs clear for new IK constraints */
1270   if (tot_ik) {
1271     BIK_clear_data(ob->pose);
1272     /* TODO(sergey): Consider doing partial update only. */
1273     DEG_relations_tag_update(bmain);
1274   }
1275
1276   return (tot_ik) ? 1 : 0;
1277 }
1278
1279 static void pose_mirror_info_init(PoseInitData_Mirror *pid,
1280                                   bPoseChannel *pchan,
1281                                   bPoseChannel *pchan_orig,
1282                                   bool is_mirror_relative)
1283 {
1284   pid->pchan = pchan;
1285   copy_v3_v3(pid->orig.loc, pchan->loc);
1286   copy_v3_v3(pid->orig.size, pchan->size);
1287   pid->orig.curve_in_x = pchan->curve_in_x;
1288   pid->orig.curve_out_x = pchan->curve_out_x;
1289   pid->orig.roll1 = pchan->roll1;
1290   pid->orig.roll2 = pchan->roll2;
1291
1292   if (pchan->rotmode > 0) {
1293     copy_v3_v3(pid->orig.eul, pchan->eul);
1294   }
1295   else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1296     copy_v3_v3(pid->orig.axis_angle, pchan->rotAxis);
1297     pid->orig.axis_angle[3] = pchan->rotAngle;
1298   }
1299   else {
1300     copy_qt_qt(pid->orig.quat, pchan->quat);
1301   }
1302
1303   if (is_mirror_relative) {
1304     float pchan_mtx[4][4];
1305     float pchan_mtx_mirror[4][4];
1306
1307     float flip_mtx[4][4];
1308     unit_m4(flip_mtx);
1309     flip_mtx[0][0] = -1;
1310
1311     BKE_pchan_to_mat4(pchan_orig, pchan_mtx_mirror);
1312     BKE_pchan_to_mat4(pchan, pchan_mtx);
1313
1314     mul_m4_m4m4(pchan_mtx_mirror, pchan_mtx_mirror, flip_mtx);
1315     mul_m4_m4m4(pchan_mtx_mirror, flip_mtx, pchan_mtx_mirror);
1316
1317     invert_m4(pchan_mtx_mirror);
1318     mul_m4_m4m4(pid->offset_mtx, pchan_mtx, pchan_mtx_mirror);
1319   }
1320   else {
1321     unit_m4(pid->offset_mtx);
1322   }
1323 }
1324
1325 static void pose_mirror_info_restore(const PoseInitData_Mirror *pid)
1326 {
1327   bPoseChannel *pchan = pid->pchan;
1328   copy_v3_v3(pchan->loc, pid->orig.loc);
1329   copy_v3_v3(pchan->size, pid->orig.size);
1330   pchan->curve_in_x = pid->orig.curve_in_x;
1331   pchan->curve_out_x = pid->orig.curve_out_x;
1332   pchan->roll1 = pid->orig.roll1;
1333   pchan->roll2 = pid->orig.roll2;
1334
1335   if (pchan->rotmode > 0) {
1336     copy_v3_v3(pchan->eul, pid->orig.eul);
1337   }
1338   else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1339     copy_v3_v3(pchan->rotAxis, pid->orig.axis_angle);
1340     pchan->rotAngle = pid->orig.axis_angle[3];
1341   }
1342   else {
1343     copy_qt_qt(pchan->quat, pid->orig.quat);
1344   }
1345 }
1346
1347 /**
1348  * When objects array is NULL, use 't->data_container' as is.
1349  */
1350 static void createTransPose(TransInfo *t)
1351 {
1352   Main *bmain = CTX_data_main(t->context);
1353
1354   t->data_len_all = 0;
1355
1356   bool has_translate_rotate_buf[2] = {false, false};
1357   bool *has_translate_rotate = (t->mode == TFM_TRANSLATION) ? has_translate_rotate_buf : NULL;
1358
1359   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1360     Object *ob = tc->poseobj;
1361     bPose *pose = ob->pose;
1362
1363     bArmature *arm;
1364
1365     /* check validity of state */
1366     arm = BKE_armature_from_object(tc->poseobj);
1367     if ((arm == NULL) || (pose == NULL)) {
1368       continue;
1369     }
1370
1371     const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
1372
1373     /* set flags and count total */
1374     tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate);
1375     if (tc->data_len == 0) {
1376       continue;
1377     }
1378
1379     if (arm->flag & ARM_RESTPOS) {
1380       if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) {
1381         BKE_report(t->reports, RPT_ERROR, "Cannot change Pose when 'Rest Position' is enabled");
1382         tc->data_len = 0;
1383         continue;
1384       }
1385     }
1386
1387     /* do we need to add temporal IK chains? */
1388     if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) {
1389       if (pose_grab_with_ik(bmain, ob)) {
1390         t->flag |= T_AUTOIK;
1391         has_translate_rotate[0] = true;
1392       }
1393     }
1394
1395     if (mirror) {
1396       int total_mirrored = 0;
1397       for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1398         if ((pchan->bone->flag & BONE_TRANSFORM) &&
1399             BKE_pose_channel_get_mirrored(ob->pose, pchan->name)) {
1400           total_mirrored++;
1401         }
1402       }
1403
1404       PoseInitData_Mirror *pid = MEM_mallocN((total_mirrored + 1) * sizeof(PoseInitData_Mirror),
1405                                              "PoseInitData_Mirror");
1406
1407       /* Trick to terminate iteration. */
1408       pid[total_mirrored].pchan = NULL;
1409
1410       tc->custom.type.data = pid;
1411       tc->custom.type.use_free = true;
1412     }
1413   }
1414
1415   /* if there are no translatable bones, do rotation */
1416   if ((t->mode == TFM_TRANSLATION) && !has_translate_rotate[0]) {
1417     if (has_translate_rotate[1]) {
1418       t->mode = TFM_ROTATION;
1419     }
1420     else {
1421       t->mode = TFM_RESIZE;
1422     }
1423   }
1424
1425   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1426     if (tc->data_len == 0) {
1427       continue;
1428     }
1429     Object *ob = tc->poseobj;
1430     TransData *td;
1431     TransDataExtension *tdx;
1432     int i;
1433
1434     PoseInitData_Mirror *pid = tc->custom.type.data;
1435     int pid_index = 0;
1436     bPose *pose = ob->pose;
1437
1438     if (pose == NULL) {
1439       continue;
1440     }
1441
1442     const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
1443     const bool is_mirror_relative = ((pose->flag & POSE_MIRROR_RELATIVE) != 0);
1444
1445     tc->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */
1446
1447     /* init trans data */
1448     td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransPoseBone");
1449     tdx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
1450                                      "TransPoseBoneExt");
1451     for (i = 0; i < tc->data_len; i++, td++, tdx++) {
1452       td->ext = tdx;
1453       td->val = NULL;
1454     }
1455
1456     /* use pose channels to fill trans data */
1457     td = tc->data;
1458     for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1459       if (pchan->bone->flag & BONE_TRANSFORM) {
1460         add_pose_transdata(t, pchan, ob, tc, td);
1461
1462         if (mirror) {
1463           bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name);
1464           if (pchan_mirror) {
1465             pose_mirror_info_init(&pid[pid_index], pchan_mirror, pchan, is_mirror_relative);
1466             pid_index++;
1467           }
1468         }
1469
1470         td++;
1471       }
1472     }
1473
1474     if (td != (tc->data + tc->data_len)) {
1475       BKE_report(t->reports, RPT_DEBUG, "Bone selection count error");
1476     }
1477
1478     /* initialize initial auto=ik chainlen's? */
1479     if (t->flag & T_AUTOIK) {
1480       transform_autoik_update(t, 0);
1481     }
1482   }
1483
1484   t->flag |= T_POSE;
1485   /* disable PET, its not usable in pose mode yet [#32444] */
1486   t->flag &= ~T_PROP_EDIT_ALL;
1487 }
1488
1489 void restoreMirrorPoseBones(TransDataContainer *tc)
1490 {
1491   bPose *pose = tc->poseobj->pose;
1492
1493   if (!(pose->flag & POSE_MIRROR_EDIT)) {
1494     return;
1495   }
1496
1497   for (PoseInitData_Mirror *pid = tc->custom.type.data; pid->pchan; pid++) {
1498     pose_mirror_info_restore(pid);
1499   }
1500 }
1501
1502 void restoreBones(TransDataContainer *tc)
1503 {
1504   bArmature *arm;
1505   BoneInitData *bid = tc->custom.type.data;
1506   EditBone *ebo;
1507
1508   if (tc->obedit) {
1509     arm = tc->obedit->data;
1510   }
1511   else {
1512     BLI_assert(tc->poseobj != NULL);
1513     arm = tc->poseobj->data;
1514   }
1515
1516   while (bid->bone) {
1517     ebo = bid->bone;
1518
1519     ebo->dist = bid->dist;
1520     ebo->rad_tail = bid->rad_tail;
1521     ebo->roll = bid->roll;
1522     ebo->xwidth = bid->xwidth;
1523     ebo->zwidth = bid->zwidth;
1524     copy_v3_v3(ebo->head, bid->head);
1525     copy_v3_v3(ebo->tail, bid->tail);
1526
1527     if (arm->flag & ARM_MIRROR_EDIT) {
1528       EditBone *ebo_child;
1529
1530       /* Also move connected ebo_child, in case ebo_child's name aren't mirrored properly */
1531       for (ebo_child = arm->edbo->first; ebo_child; ebo_child = ebo_child->next) {
1532         if ((ebo_child->flag & BONE_CONNECTED) && (ebo_child->parent == ebo)) {
1533           copy_v3_v3(ebo_child->head, ebo->tail);
1534           ebo_child->rad_head = ebo->rad_tail;
1535         }
1536       }
1537
1538       /* Also move connected parent, in case parent's name isn't mirrored properly */
1539       if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
1540         EditBone *parent = ebo->parent;
1541         copy_v3_v3(parent->tail, ebo->head);
1542         parent->rad_tail = ebo->rad_head;
1543       }
1544     }
1545
1546     bid++;
1547   }
1548 }
1549
1550 /* ********************* armature ************** */
1551 static void createTransArmatureVerts(TransInfo *t)
1552 {
1553   t->data_len_all = 0;
1554
1555   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1556     EditBone *ebo, *eboflip;
1557     bArmature *arm = tc->obedit->data;
1558     ListBase *edbo = arm->edbo;
1559     bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
1560     int total_mirrored = 0;
1561
1562     tc->data_len = 0;
1563     for (ebo = edbo->first; ebo; ebo = ebo->next) {
1564       const int data_len_prev = tc->data_len;
1565
1566       if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
1567         if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
1568           if (ebo->flag & BONE_SELECTED) {
1569             tc->data_len++;
1570           }
1571         }
1572         else if (t->mode == TFM_BONE_ROLL) {
1573           if (ebo->flag & BONE_SELECTED) {
1574             tc->data_len++;
1575           }
1576         }
1577         else {
1578           if (ebo->flag & BONE_TIPSEL) {
1579             tc->data_len++;
1580           }
1581           if (ebo->flag & BONE_ROOTSEL) {
1582             tc->data_len++;
1583           }
1584         }
1585       }
1586
1587       if (mirror && (data_len_prev < tc->data_len)) {
1588         eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
1589         if (eboflip) {
1590           total_mirrored++;
1591         }
1592       }
1593     }
1594     if (!tc->data_len) {
1595       continue;
1596     }
1597
1598     if (mirror) {
1599       BoneInitData *bid = MEM_mallocN((total_mirrored + 1) * sizeof(BoneInitData), "BoneInitData");
1600
1601       /* trick to terminate iteration */
1602       bid[total_mirrored].bone = NULL;
1603
1604       tc->custom.type.data = bid;
1605       tc->custom.type.use_free = true;
1606     }
1607     t->data_len_all += tc->data_len;
1608   }
1609
1610   transform_around_single_fallback(t);
1611   t->data_len_all = -1;
1612
1613   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1614     if (!tc->data_len) {
1615       continue;
1616     }
1617
1618     EditBone *ebo, *eboflip;
1619     bArmature *arm = tc->obedit->data;
1620     ListBase *edbo = arm->edbo;
1621     TransData *td, *td_old;
1622     float mtx[3][3], smtx[3][3], bonemat[3][3];
1623     bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
1624     BoneInitData *bid = tc->custom.type.data;
1625
1626     copy_m3_m4(mtx, tc->obedit->obmat);
1627     pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
1628
1629     td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransEditBone");
1630     int i = 0;
1631
1632     for (ebo = edbo->first; ebo; ebo = ebo->next) {
1633       td_old = td;
1634       ebo->oldlength =
1635           ebo->length;  // length==0.0 on extrude, used for scaling radius of bone points
1636
1637       if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
1638         if (t->mode == TFM_BONE_ENVELOPE) {
1639           if (ebo->flag & BONE_ROOTSEL) {
1640             td->val = &ebo->rad_head;
1641             td->ival = *td->val;
1642
1643             copy_v3_v3(td->center, ebo->head);
1644             td->flag = TD_SELECTED;
1645
1646             copy_m3_m3(td->smtx, smtx);
1647             copy_m3_m3(td->mtx, mtx);
1648
1649             td->loc = NULL;
1650             td->ext = NULL;
1651             td->ob = tc->obedit;
1652
1653             td++;
1654           }
1655           if (ebo->flag & BONE_TIPSEL) {
1656             td->val = &ebo->rad_tail;
1657             td->ival = *td->val;
1658             copy_v3_v3(td->center, ebo->tail);
1659             td->flag = TD_SELECTED;
1660
1661             copy_m3_m3(td->smtx, smtx);
1662             copy_m3_m3(td->mtx, mtx);
1663
1664             td->loc = NULL;
1665             td->ext = NULL;
1666             td->ob = tc->obedit;
1667
1668             td++;
1669           }
1670         }
1671         else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
1672           if (ebo->flag & BONE_SELECTED) {
1673             if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
1674               td->loc = NULL;
1675               td->val = &ebo->dist;
1676               td->ival = ebo->dist;
1677             }
1678             else {
1679               // abusive storage of scale in the loc pointer :)
1680               td->loc = &ebo->xwidth;
1681               copy_v3_v3(td->iloc, td->loc);
1682               td->val = NULL;
1683             }
1684             copy_v3_v3(td->center, ebo->head);
1685             td->flag = TD_SELECTED;
1686
1687             /* use local bone matrix */
1688             ED_armature_ebone_to_mat3(ebo, bonemat);
1689             mul_m3_m3m3(td->mtx, mtx, bonemat);
1690             invert_m3_m3(td->smtx, td->mtx);
1691
1692             copy_m3_m3(td->axismtx, td->mtx);
1693             normalize_m3(td->axismtx);
1694
1695             td->ext = NULL;
1696             td->ob = tc->obedit;
1697
1698             td++;
1699           }
1700         }
1701         else if (t->mode == TFM_BONE_ROLL) {
1702           if (ebo->flag & BONE_SELECTED) {
1703             td->loc = NULL;
1704             td->val = &(ebo->roll);
1705             td->ival = ebo->roll;
1706
1707             copy_v3_v3(td->center, ebo->head);
1708             td->flag = TD_SELECTED;
1709
1710             td->ext = NULL;
1711             td->ob = tc->obedit;
1712
1713             td++;
1714           }
1715         }
1716         else {
1717           if (ebo->flag & BONE_TIPSEL) {
1718             copy_v3_v3(td->iloc, ebo->tail);
1719
1720             /* Don't allow single selected tips to have a modified center,
1721              * causes problem with snapping (see T45974).
1722              * However, in rotation mode, we want to keep that 'rotate bone around root with
1723              * only its tip selected' behavior (see T46325). */
1724             if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
1725                 ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL))) {
1726               copy_v3_v3(td->center, ebo->head);
1727             }
1728             else {
1729               copy_v3_v3(td->center, td->iloc);
1730             }
1731
1732             td->loc = ebo->tail;
1733             td->flag = TD_SELECTED;
1734             if (ebo->flag & BONE_EDITMODE_LOCKED) {
1735               td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
1736             }
1737
1738             copy_m3_m3(td->smtx, smtx);
1739             copy_m3_m3(td->mtx, mtx);
1740
1741             ED_armature_ebone_to_mat3(ebo, td->axismtx);
1742
1743             if ((ebo->flag & BONE_ROOTSEL) == 0) {
1744               td->extra = ebo;
1745               td->ival = ebo->roll;
1746             }
1747
1748             td->ext = NULL;
1749             td->val = NULL;
1750             td->ob = tc->obedit;
1751
1752             td++;
1753           }
1754           if (ebo->flag & BONE_ROOTSEL) {
1755             copy_v3_v3(td->iloc, ebo->head);
1756             copy_v3_v3(td->center, td->iloc);
1757             td->loc = ebo->head;
1758             td->flag = TD_SELECTED;
1759             if (ebo->flag & BONE_EDITMODE_LOCKED) {
1760               td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
1761             }
1762
1763             copy_m3_m3(td->smtx, smtx);
1764             copy_m3_m3(td->mtx, mtx);
1765
1766             ED_armature_ebone_to_mat3(ebo, td->axismtx);
1767
1768             td->extra = ebo; /* to fix roll */
1769             td->ival = ebo->roll;
1770
1771             td->ext = NULL;
1772             td->val = NULL;
1773             td->ob = tc->obedit;
1774
1775             td++;
1776           }
1777         }
1778       }
1779
1780       if (mirror && (td_old != td)) {
1781         eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
1782         if (eboflip) {
1783           bid[i].bone = eboflip;
1784           bid[i].dist = eboflip->dist;
1785           bid[i].rad_tail = eboflip->rad_tail;
1786           bid[i].roll = eboflip->roll;
1787           bid[i].xwidth = eboflip->xwidth;
1788           bid[i].zwidth = eboflip->zwidth;
1789           copy_v3_v3(bid[i].head, eboflip->head);
1790           copy_v3_v3(bid[i].tail, eboflip->tail);
1791           i++;
1792         }
1793       }
1794     }
1795
1796     if (mirror) {
1797       /* trick to terminate iteration */
1798       BLI_assert(i + 1 == (MEM_allocN_len(bid) / sizeof(*bid)));
1799       bid[i].bone = NULL;
1800     }
1801   }
1802 }
1803
1804 /* ********************* meta elements ********* */
1805
1806 static void createTransMBallVerts(TransInfo *t)
1807 {
1808   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1809     MetaBall *mb = (MetaBall *)tc->obedit->data;
1810     MetaElem *ml;
1811     TransData *td;
1812     TransDataExtension *tx;
1813     float mtx[3][3], smtx[3][3];
1814     int count = 0, countsel = 0;
1815     const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
1816
1817     /* count totals */
1818     for (ml = mb->editelems->first; ml; ml = ml->next) {
1819       if (ml->flag & SELECT) {
1820         countsel++;
1821       }
1822       if (is_prop_edit) {
1823         count++;
1824       }
1825     }
1826
1827     /* note: in prop mode we need at least 1 selected */
1828     if (countsel == 0) {
1829       continue;
1830     }
1831
1832     if (is_prop_edit) {
1833       tc->data_len = count;
1834     }
1835     else {
1836       tc->data_len = countsel;
1837     }
1838
1839     td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(MBall EditMode)");
1840     tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
1841                                     "MetaElement_TransExtension");
1842
1843     copy_m3_m4(mtx, tc->obedit->obmat);
1844     pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
1845
1846     for (ml = mb->editelems->first; ml; ml = ml->next) {
1847       if (is_prop_edit || (ml->flag & SELECT)) {
1848         td->loc = &ml->x;
1849         copy_v3_v3(td->iloc, td->loc);
1850         copy_v3_v3(td->center, td->loc);
1851
1852         quat_to_mat3(td->axismtx, ml->quat);
1853
1854         if (ml->flag & SELECT) {
1855           td->flag = TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1856         }
1857         else {
1858           td->flag = TD_USEQUAT;
1859         }
1860
1861         copy_m3_m3(td->smtx, smtx);
1862         copy_m3_m3(td->mtx, mtx);
1863
1864         td->ext = tx;
1865
1866         /* Radius of MetaElem (mass of MetaElem influence) */
1867         if (ml->flag & MB_SCALE_RAD) {
1868           td->val = &ml->rad;
1869           td->ival = ml->rad;
1870         }
1871         else {
1872           td->val = &ml->s;
1873           td->ival = ml->s;
1874         }
1875
1876         /* expx/expy/expz determine "shape" of some MetaElem types */
1877         tx->size = &ml->expx;
1878         tx->isize[0] = ml->expx;
1879         tx->isize[1] = ml->expy;
1880         tx->isize[2] = ml->expz;
1881
1882         /* quat is used for rotation of MetaElem */
1883         tx->quat = ml->quat;
1884         copy_qt_qt(tx->iquat, ml->quat);
1885
1886         tx->rot = NULL;
1887
1888         td++;
1889         tx++;
1890       }
1891     }
1892   }
1893 }
1894
1895 /* ********************* curve/surface ********* */
1896
1897 static void calc_distanceCurveVerts(TransData *head, TransData *tail)
1898 {
1899   TransData *td, *td_near = NULL;
1900   for (td = head; td <= tail; td++) {
1901     if (td->flag & TD_SELECTED) {
1902       td_near = td;
1903       td->dist = 0.0f;
1904     }
1905     else if (td_near) {
1906       float dist;
1907       float vec[3];
1908
1909       sub_v3_v3v3(vec, td_near->center, td->center);
1910       mul_m3_v3(head->mtx, vec);
1911       dist = len_v3(vec);
1912
1913       if (dist < (td - 1)->dist) {
1914         td->dist = (td - 1)->dist;
1915       }
1916       else {
1917         td->dist = dist;
1918       }
1919     }
1920     else {
1921       td->dist = FLT_MAX;
1922       td->flag |= TD_NOTCONNECTED;
1923     }
1924   }
1925   td_near = NULL;
1926   for (td = tail; td >= head; td--) {
1927     if (td->flag & TD_SELECTED) {
1928       td_near = td;
1929       td->dist = 0.0f;
1930     }
1931     else if (td_near) {
1932       float dist;
1933       float vec[3];
1934
1935       sub_v3_v3v3(vec, td_near->center, td->center);
1936       mul_m3_v3(head->mtx, vec);
1937       dist = len_v3(vec);
1938
1939       if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td + 1)->dist < td->dist) {
1940         td->flag &= ~TD_NOTCONNECTED;
1941         if (dist < (td + 1)->dist) {
1942           td->dist = (td + 1)->dist;
1943         }
1944         else {
1945           td->dist = dist;
1946         }
1947       }
1948     }
1949   }
1950 }
1951
1952 /* Utility function for getting the handle data from bezier's */
1953 static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt)
1954 {
1955   TransDataCurveHandleFlags *hdata;
1956   td->flag |= TD_BEZTRIPLE;
1957   hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1958   hdata->ih1 = bezt->h1;
1959   hdata->h1 = &bezt->h1;
1960   hdata->ih2 = bezt->h2; /* in case the second is not selected */
1961   hdata->h2 = &bezt->h2;
1962   return hdata;
1963 }
1964
1965 /**
1966  * For the purpose of transform code we need to behave as if handles are selected,
1967  * even when they aren't (see special case below).
1968  */
1969 static int bezt_select_to_transform_triple_flag(const BezTriple *bezt, const bool hide_handles)
1970 {
1971   int flag = 0;
1972
1973   if (hide_handles) {
1974     if (bezt->f2 & SELECT) {
1975       flag = (1 << 0) | (1 << 1) | (1 << 2);
1976     }
1977   }
1978   else {
1979     flag = (((bezt->f1 & SELECT) ? (1 << 0) : 0) | ((bezt->f2 & SELECT) ? (1 << 1) : 0) |
1980             ((bezt->f3 & SELECT) ? (1 << 2) : 0));
1981   }
1982
1983   /* Special case for auto & aligned handles:
1984    * When a center point is being moved without the handles,
1985    * leaving the handles stationary makes no sense and only causes strange behavior,
1986    * where one handle is arbitrarily anchored, the other one is aligned and lengthened
1987    * based on where the center point is moved. Also a bug when cancelling, see: T52007.
1988    *
1989    * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'.
1990    * However that doesn't resolve odd behavior, so best transform the handles in this case.
1991    */
1992   if ((flag != ((1 << 0) | (1 << 1) | (1 << 2))) && (flag & (1 << 1))) {
1993     if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) && ELEM(bezt->h2, HD_AUTO, HD_ALIGN)) {
1994       flag = (1 << 0) | (1 << 1) | (1 << 2);
1995     }
1996   }
1997
1998   return flag;
1999 }
2000
2001 static void createTransCurveVerts(TransInfo *t)
2002 {
2003
2004 #define SEL_F1 (1 << 0)
2005 #define SEL_F2 (1 << 1)
2006 #define SEL_F3 (1 << 2)
2007
2008   t->data_len_all = 0;
2009
2010   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2011     Curve *cu = tc->obedit->data;
2012     BLI_assert(cu->editnurb != NULL);
2013     BezTriple *bezt;
2014     BPoint *bp;
2015     int a;
2016     int count = 0, countsel = 0;
2017     const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
2018     View3D *v3d = t->view;
2019     short hide_handles = (v3d != NULL) ?
2020                              ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) :
2021                              false;
2022
2023     /* count total of vertices, check identical as in 2nd loop for making transdata! */
2024     ListBase *nurbs = BKE_curve_editNurbs_get(cu);
2025     for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
2026       if (nu->type == CU_BEZIER) {
2027         for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
2028           if (bezt->hide == 0) {
2029             const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
2030             if (bezt_tx & SEL_F1) {
2031               countsel++;
2032             }
2033             if (bezt_tx & SEL_F2) {
2034               countsel++;
2035             }
2036             if (bezt_tx & SEL_F3) {
2037               countsel++;
2038             }
2039             if (is_prop_edit) {
2040               count += 3;
2041             }
2042           }
2043         }
2044       }
2045       else {
2046         for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
2047           if (bp->hide == 0) {
2048             if (is_prop_edit) {
2049               count++;
2050             }
2051             if (bp->f1 & SELECT) {
2052               countsel++;
2053             }
2054           }
2055         }
2056       }
2057     }
2058     /* note: in prop mode we need at least 1 selected */
2059     if (countsel == 0) {
2060       tc->data_len = 0;
2061       continue;
2062     }
2063
2064     if (is_prop_edit) {
2065       tc->data_len = count;
2066     }
2067     else {
2068       tc->data_len = countsel;
2069     }
2070     tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Curve EditMode)");
2071
2072     t->data_len_all += tc->data_len;
2073   }
2074
2075   transform_around_single_fallback(t);
2076   t->data_len_all = -1;
2077
2078   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2079     if (tc->data_len == 0) {
2080       continue;
2081     }
2082
2083     Curve *cu = tc->obedit->data;
2084     BezTriple *bezt;
2085     BPoint *bp;
2086     int a;
2087     const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
2088     View3D *v3d = t->view;
2089     short hide_handles = (v3d != NULL) ?
2090                              ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) :
2091                              false;
2092
2093     float mtx[3][3], smtx[3][3];
2094
2095     copy_m3_m4(mtx, tc->obedit->obmat);
2096     pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
2097
2098     TransData *td = tc->data;
2099     ListBase *nurbs = BKE_curve_editNurbs_get(cu);
2100     for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
2101       if (nu->type == CU_BEZIER) {
2102         TransData *head, *tail;
2103         head = tail = td;
2104         for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
2105           if (bezt->hide == 0) {
2106             TransDataCurveHandleFlags *hdata = NULL;
2107             float axismtx[3][3];
2108
2109             if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
2110               float normal[3], plane[3];
2111
2112               BKE_nurb_bezt_calc_normal(nu, bezt, normal);
2113               BKE_nurb_bezt_calc_plane(nu, bezt, plane);
2114
2115               if (createSpaceNormalTangent(axismtx, normal, plane)) {
2116                 /* pass */
2117               }
2118               else {
2119                 normalize_v3(normal);
2120                 axis_dominant_v3_to_m3(axismtx, normal);
2121                 invert_m3(axismtx);
2122               }
2123             }
2124
2125             /* Elements that will be transform (not always a match to selection). */
2126             const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
2127
2128             if (is_prop_edit || bezt_tx & SEL_F1) {
2129               copy_v3_v3(td->iloc, bezt->vec[0]);
2130               td->loc = bezt->vec[0];
2131               copy_v3_v3(td->center,
2132                          bezt->vec[(hide_handles || (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
2133                                     (bezt->f2 & SELECT)) ?
2134                                        1 :
2135                                        0]);
2136               if (hide_handles) {
2137                 if (bezt->f2 & SELECT) {
2138                   td->flag = TD_SELECTED;
2139                 }
2140                 else {
2141                   td->flag = 0;
2142                 }
2143               }
2144               else {
2145                 if (bezt->f1 & SELECT) {
2146                   td->flag = TD_SELECTED;
2147                 }
2148                 else {
2149                   td->flag = 0;
2150                 }
2151               }
2152               td->ext = NULL;
2153               td->val = NULL;
2154
2155               hdata = initTransDataCurveHandles(td, bezt);
2156
2157               copy_m3_m3(td->smtx, smtx);
2158               copy_m3_m3(td->mtx, mtx);
2159               if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
2160                 copy_m3_m3(td->axismtx, axismtx);
2161               }
2162
2163               td++;
2164               tail++;
2165             }
2166
2167             /* This is the Curve Point, the other two are handles */
2168             if (is_prop_edit || bezt_tx & SEL_F2) {
2169               copy_v3_v3(td->iloc, bezt->vec[1]);
2170               td->loc = bezt->vec[1];
2171               copy_v3_v3(td->center, td->loc);
2172               if (bezt->f2 & SELECT) {
2173                 td->flag = TD_SELECTED;
2174               }
2175               else {
2176                 td->flag = 0;
2177               }
2178               td->ext = NULL;
2179
2180               /* TODO - make points scale */
2181               if (t->mode == TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/
2182                 td->val = &(bezt->radius);
2183                 td->ival = bezt->radius;
2184               }
2185               else if (t->mode == TFM_TILT) {
2186                 td->val = &(bezt->tilt);
2187                 td->ival = bezt->tilt;
2188               }
2189               else {
2190                 td->val = NULL;
2191               }
2192
2193               copy_m3_m3(td->smtx, smtx);
2194               copy_m3_m3(td->mtx, mtx);
2195               if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
2196                 copy_m3_m3(td->axismtx, axismtx);
2197               }
2198
2199               if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0) {
2200                 /* If the middle is selected but the sides arnt, this is needed */
2201                 if (hdata == NULL) {
2202                   /* if the handle was not saved by the previous handle */
2203                   hdata = initTransDataCurveHandles(td, bezt);
2204                 }
2205               }
2206
2207               td++;
2208               tail++;
2209             }
2210             if (is_prop_edit || bezt_tx & SEL_F3) {
2211               copy_v3_v3(td->iloc, bezt->vec[2]);
2212               td->loc = bezt->vec[2];
2213               copy_v3_v3(td->center,
2214                          bezt->vec[(hide_handles || (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
2215                                     (bezt->f2 & SELECT)) ?
2216                                        1 :
2217                                        2]);
2218               if (hide_handles) {
2219                 if (bezt->f2 & SELECT) {
2220                   td->flag = TD_SELECTED;
2221                 }
2222                 else {
2223                   td->flag = 0;
2224                 }
2225               }
2226               else {
2227                 if (bezt->f3 & SELECT) {
2228                   td->flag = TD_SELECTED;
2229                 }
2230                 else {
2231                   td->flag = 0;
2232                 }
2233               }
2234               td->ext = NULL;
2235               td->val = NULL;
2236
2237               if (hdata == NULL) {
2238                 /* if the handle was not saved by the previous handle */
2239                 hdata = initTransDataCurveHandles(td, bezt);
2240               }
2241
2242               copy_m3_m3(td->smtx, smtx);
2243               copy_m3_m3(td->mtx, mtx);
2244               if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
2245                 copy_m3_m3(td->axismtx, axismtx);
2246               }
2247
2248               td++;
2249               tail++;
2250             }
2251
2252             (void)hdata; /* quiet warning */
2253           }
2254           else if (is_prop_edit && head != tail) {
2255             calc_distanceCurveVerts(head, tail - 1);
2256             head = tail;
2257           }
2258         }
2259         if (is_prop_edit && head != tail) {
2260           calc_distanceCurveVerts(head, tail - 1);
2261         }
2262
2263         /* TODO - in the case of tilt and radius we can also avoid allocating the
2264          * initTransDataCurveHandles but for now just don't change handle types */
2265         if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) {
2266           /* sets the handles based on their selection,
2267            * do this after the data is copied to the TransData */
2268           BKE_nurb_handles_test(nu, !hide_handles);
2269         }
2270       }
2271       else {
2272         TransData *head, *tail;
2273         head = tail = td;
2274         for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
2275           if (bp->hide == 0) {
2276             if (is_prop_edit || (bp->f1 & SELECT)) {
2277               float axismtx[3][3];
2278
2279               if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
2280                 if (nu->pntsv == 1) {
2281                   float normal[3], plane[3];
2282
2283                   BKE_nurb_bpoint_calc_normal(nu, bp, normal);
2284                   BKE_nurb_bpoint_calc_plane(nu, bp, plane);
2285
2286                   if (createSpaceNormalTangent(axismtx, normal, plane)) {
2287                     /* pass */
2288                   }
2289                   else {
2290                     normalize_v3(normal);
2291                     axis_dominant_v3_to_m3(axismtx, normal);
2292                     invert_m3(axismtx);
2293                   }
2294                 }
2295               }
2296
2297               copy_v3_v3(td->iloc, bp->vec);
2298               td->loc = bp->vec;
2299               copy_v3_v3(td->center, td->loc);
2300               if (bp->f1 & SELECT) {
2301                 td->flag = TD_SELECTED;
2302               }
2303               else {
2304                 td->flag = 0;
2305               }
2306               td->ext = NULL;
2307
2308               if (t->mode == TFM_CURVE_SHRINKFATTEN || t->mode == TFM_RESIZE) {
2309                 td->val = &(bp->radius);
2310                 td->ival = bp->radius;
2311               }
2312               else {
2313                 td->val = &(bp->tilt);
2314                 td->ival = bp->tilt;
2315               }
2316
2317               copy_m3_m3(td->smtx, smtx);
2318               copy_m3_m3(td->mtx, mtx);
2319               if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
2320                 if (nu->pntsv == 1) {
2321                   copy_m3_m3(td->axismtx, axismtx);
2322                 }
2323               }
2324
2325               td++;
2326               tail++;
2327             }
2328           }
2329           else if (is_prop_edit && head != tail) {
2330             calc_distanceCurveVerts(head, tail - 1);
2331             head = tail;
2332           }
2333         }
2334         if (is_prop_edit && head != tail) {
2335           calc_distanceCurveVerts(head, tail - 1);
2336         }
2337       }
2338     }
2339   }
2340 #undef SEL_F1
2341 #undef SEL_F2
2342 #undef SEL_F3
2343 }
2344
2345 /* ********************* lattice *************** */
2346
2347 static void createTransLatticeVerts(TransInfo *t)
2348 {
2349   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2350
2351     Lattice *latt = ((Lattice *)tc->obedit->data)->editlatt->latt;
2352     TransData *td = NULL;
2353     BPoint *bp;
2354     float mtx[3][3], smtx[3][3];
2355     int a;
2356     int count = 0, countsel = 0;
2357     const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
2358
2359     bp = latt->def;
2360     a = latt->pntsu * latt->pntsv * latt->pntsw;
2361     while (a--) {
2362       if (bp->hide == 0) {
2363         if (bp->f1 & SELECT) {
2364           countsel++;
2365         }
2366         if (is_prop_edit) {
2367           count++;
2368         }
2369       }
2370       bp++;
2371     }
2372
2373     /* note: in prop mode we need at least 1 selected */
2374     if (countsel == 0) {
2375       return;
2376     }
2377
2378     if (is_prop_edit) {
2379       tc->data_len = count;
2380     }
2381     else {
2382       tc->data_len = countsel;
2383     }
2384     tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Lattice EditMode)");
2385
2386     copy_m3_m4(mtx, tc->obedit->obmat);
2387     pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
2388
2389     td = tc->data;
2390     bp = latt->def;
2391     a = latt->pntsu * latt->pntsv * latt->pntsw;
2392     while (a--) {
2393       if (is_prop_edit || (bp->f1 & SELECT)) {
2394         if (bp->hide == 0) {
2395           copy_v3_v3(td->iloc, bp->vec);
2396           td->loc = bp->vec;
2397           copy_v3_v3(td->center, td->loc);
2398           if (bp->f1 & SELECT) {
2399             td->flag = TD_SELECTED;
2400           }
2401           else {
2402             td->flag = 0;
2403           }
2404           copy_m3_m3(td->smtx, smtx);
2405           copy_m3_m3(td->mtx, mtx);
2406
2407           td->ext = NULL;
2408           td->val = NULL;
2409
2410           td++;
2411         }
2412       }
2413       bp++;
2414     }
2415   }
2416 }
2417
2418 /* ******************* particle edit **************** */
2419 static void createTransParticleVerts(bContext *C, TransInfo *t)
2420 {
2421   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2422
2423     TransData *td = NULL;
2424     TransDataExtension *tx;
2425     Object *ob = CTX_data_active_object(C);
2426     ParticleEditSettings *pset = PE_settings(t->scene);
2427     PTCacheEdit *edit = PE_get_current(t->scene, ob);
2428     ParticleSystem *psys = NULL;
2429     PTCacheEditPoint *point;
2430     PTCacheEditKey *key;
2431     float mat[4][4];
2432     int i, k, transformparticle;
2433     int count = 0, hasselected = 0;
2434     const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
2435
2436     if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) {
2437       return;
2438     }
2439
2440     psys = edit->psys;
2441
2442     for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
2443       point->flag &= ~PEP_TRANSFORM;
2444       transformparticle = 0;
2445
2446       if ((point->flag & PEP_HIDE) == 0) {
2447         for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
2448           if ((key->flag & PEK_HIDE) == 0) {
2449             if (key->flag & PEK_SELECT) {
2450               hasselected = 1;
2451               transformparticle = 1;
2452             }
2453             else if (is_prop_edit) {
2454               transformparticle = 1;
2455             }
2456           }
2457         }
2458       }
2459
2460       if (transformparticle) {
2461         count += point->totkey;
2462         point->flag |= PEP_TRANSFORM;
2463       }
2464     }
2465
2466     /* note: in prop mode we need at least 1 selected */
2467     if (hasselected == 0) {
2468       return;
2469     }
2470
2471     tc->data_len = count;
2472     td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Particle Mode)");
2473
2474     if (t->mode == TFM_BAKE_TIME) {
2475       tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
2476                                       "Particle_TransExtension");
2477     }
2478     else {
2479       tx = tc->data_ext = NULL;
2480     }
2481
2482     unit_m4(mat);
2483
2484     invert_m4_m4(ob->imat, ob->obmat);
2485
2486     for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
2487       TransData *head, *tail;
2488       head = tail = td;
2489
2490       if (!(point->flag & PEP_TRANSFORM)) {
2491         continue;
2492       }
2493
2494       if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
2495         ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
2496         psys_mat_hair_to_global(
2497             ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
2498       }
2499
2500       for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
2501         if (key->flag & PEK_USE_WCO) {
2502           copy_v3_v3(key->world_co, key->co);
2503           mul_m4_v3(mat, key->world_co);
2504           td->loc = key->world_co;
2505         }
2506         else {
2507           td->loc = key->co;
2508         }
2509
2510         copy_v3_v3(td->iloc, td->loc);
2511         copy_v3_v3(td->center, td->loc);
2512
2513         if (key->flag & PEK_SELECT) {
2514           td->flag |= TD_SELECTED;
2515         }
2516         else if (!is_prop_edit) {
2517           td->flag |= TD_SKIP;
2518         }
2519
2520         unit_m3(td->mtx);
2521         unit_m3(td->smtx);
2522
2523         /* don't allow moving roots */
2524         if (k == 0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR))) {
2525           td->protectflag |= OB_LOCK_LOC;
2526         }
2527
2528         td->ob = ob;
2529         td->ext = tx;
2530         if (t->mode == TFM_BAKE_TIME) {
2531           td->val = key->time;
2532           td->ival = *(key->time);
2533           /* abuse size and quat for min/max values */
2534           td->flag |= TD_NO_EXT;
2535           if (k == 0) {
2536             tx->size = NULL;
2537           }
2538           else {
2539             tx->size = (key - 1)->time;
2540           }
2541
2542           if (k == point->totkey - 1) {
2543             tx->quat = NULL;
2544           }
2545           else {
2546             tx->quat = (key + 1)->time;
2547           }
2548         }
2549
2550         td++;
2551         if (tx) {
2552           tx++;
2553         }
2554         tail++;
2555       }
2556       if (is_prop_edit && head != tail) {
2557         calc_distanceCurveVerts(head, tail - 1);
2558       }
2559     }
2560   }
2561 }
2562
2563 void flushTransParticles(TransInfo *t)
2564 {
2565   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2566     Scene *scene = t->scene;
2567     ViewLayer *view_layer = t->view_layer;
2568     Object *ob = OBACT(view_layer);
2569     PTCacheEdit *edit = PE_get_current(scene, ob);
2570     ParticleSystem *psys = edit->psys;
2571     PTCacheEditPoint *point;
2572     PTCacheEditKey *key;
2573     TransData *td;
2574     float mat[4][4], imat[4][4], co[3];
2575     int i, k;
2576     const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
2577
2578     /* we do transform in world space, so flush world space position
2579      * back to particle local space (only for hair particles) */
2580     td = tc->data;
2581     for (i = 0, point = edit->points; i < edit->totpoint; i++, point++, td++) {
2582       if (!(point->flag & PEP_TRANSFORM)) {
2583         continue;
2584       }
2585
2586       if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
2587         ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
2588         psys_mat_hair_to_global(
2589             ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
2590         invert_m4_m4(imat, mat);
2591
2592         for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
2593           copy_v3_v3(co, key->world_co);
2594           mul_m4_v3(imat, co);
2595
2596           /* optimization for proportional edit */
2597           if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
2598             copy_v3_v3(key->co, co);
2599             point->flag |= PEP_EDIT_RECALC;
2600           }
2601         }
2602       }
2603       else {
2604         point->flag |= PEP_EDIT_RECALC;
2605       }
2606     }
2607
2608     PE_update_object(t->depsgraph, scene, OBACT(view_layer), 1);
2609     BKE_particle_batch_cache_dirty_tag(psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
2610     DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO);
2611   }
2612 }
2613
2614 /* ********************* mesh ****************** */
2615
2616 static bool bmesh_test_dist_add(BMVert *v,
2617                                 BMVert *v_other,
2618                                 float *dists,
2619                                 const float *dists_prev,
2620                                 /* optionally track original index */
2621                                 int *index,
2622                                 const int *index_prev,
2623                                 float mtx[3][3])
2624 {
2625   if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) &&
2626       (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) {
2627     const int i = BM_elem_index_get(v);
2628     const int i_other = BM_elem_index_get(v_other);
2629     float vec[3];
2630     float dist_other;
2631     sub_v3_v3v3(vec, v->co, v_other->co);
2632     mul_m3_v3(mtx, vec);
2633
2634     dist_other = dists_prev[i] + len_v3(vec);
2635     if (dist_other < dists[i_other]) {
2636       dists[i_other] = dist_other;
2637       if (index != NULL) {
2638         index[i_other] = index_prev[i];
2639       }
2640       return true;
2641     }
2642   }
2643
2644   return false;
2645 }
2646
2647 /**
2648  * \param mtx: Measure distance in this space.
2649  * \param dists: Store the closest connected distance to selected vertices.
2650  * \param index: Optionally store the original index we're measuring the distance to (can be NULL).
2651  */
2652 static void editmesh_set_connectivity_distance(BMesh *bm,
2653                                                float mtx[3][3],
2654                                                float *dists,
2655                                                int *index)
2656 {
2657   BLI_LINKSTACK_DECLARE(queue, BMVert *);
2658
2659   /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */
2660   BLI_LINKSTACK_DECLARE(queue_next, BMVert *);
2661
2662   BLI_LINKSTACK_INIT(queue);
2663   BLI_LINKSTACK_INIT(queue_next);
2664
2665   {
2666     BMIter viter;
2667     BMVert *v;
2668     int i;
2669
2670     BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
2671       float dist;
2672       BM_elem_index_set(v, i); /* set_inline */
2673       BM_elem_flag_disable(v, BM_ELEM_TAG);
2674
2675       if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
2676         dist = FLT_MAX;
2677         if (index != NULL) {
2678           index[i] = i;
2679         }
2680       }
2681       else {
2682         BLI_LINKSTACK_PUSH(queue, v);
2683         dist = 0.0f;
2684         if (index != NULL) {
2685           index[i] = i;
2686         }
2687       }
2688
2689       dists[i] = dist;
2690     }
2691     bm->elem_index_dirty &= ~BM_VERT;
2692   }
2693
2694   /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
2695   float *dists_prev = MEM_dupallocN(dists);
2696   int *index_prev = MEM_dupallocN(index); /* may be NULL */
2697
2698   do {
2699     BMVert *v;
2700     LinkNode *lnk;
2701
2702     /* this is correct but slow to do each iteration,
2703      * instead sync the dist's while clearing BM_ELEM_TAG (below) */
2704 #if 0
2705     memcpy(dists_prev, dists, sizeof(float) * bm->totvert);
2706 #endif
2707
2708     while ((v = BLI_LINKSTACK_POP(queue))) {
2709       BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX);
2710
2711       /* connected edge-verts */
2712       if (v->e != NULL) {
2713         BMEdge *e_iter, *e_first;
2714
2715         e_iter = e_first = v->e;
2716
2717         /* would normally use BM_EDGES_OF_VERT, but this runs so often,
2718          * its faster to iterate on the data directly */
2719         do {
2720
2721           if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == 0) {
2722
2723             /* edge distance */
2724             {
2725               BMVert *v_other = BM_edge_other_vert(e_iter, v);
2726               if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
2727                 if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
2728                   BM_elem_flag_enable(v_other, BM_ELEM_TAG);
2729                   BLI_LINKSTACK_PUSH(queue_next, v_other);
2730                 }
2731               }
2732             }
2733
2734             /* face distance */
2735             if (e_iter->l) {
2736               BMLoop *l_iter_radial, *l_first_radial;
2737               /**
2738                * imaginary edge diagonally across quad,
2739                * \note, this takes advantage of the rules of winding that we
2740                * know 2 or more of a verts edges wont reference the same face twice.
2741                * Also, if the edge is hidden, the face will be hidden too.
2742                */
2743               l_iter_radial = l_first_radial = e_iter->l;
2744
2745               do {
2746                 if ((l_iter_radial->v == v) && (l_iter_radial->f->len == 4) &&
2747                     (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0)) {
2748                   BMVert *v_other = l_iter_radial->next->next->v;
2749                   if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
2750                     if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
2751                       BM_elem_flag_enable(v_other, BM_ELEM_TAG);
2752                       BLI_LINKSTACK_PUSH(queue_next, v_other);
2753                     }
2754                   }
2755                 }
2756               } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial);
2757             }
2758           }
2759         } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
2760       }
2761     }
2762
2763     /* clear for the next loop */
2764     for (lnk = queue_next; lnk; lnk = lnk->next) {
2765       BMVert *v_link = lnk->link;
2766       const int i = BM_elem_index_get(v_link);
2767
2768       BM_elem_flag_disable(v_link, BM_ELEM_TAG);
2769
2770       /* keep in sync, avoid having to do full memcpy each iteration */
2771       dists_prev[i] = dists[i];
2772       if (index != NULL) {
2773         index_prev[i] = index[i];
2774       }
2775     }
2776
2777     BLI_LINKSTACK_SWAP(queue, queue_next);
2778
2779     /* none should be tagged now since 'queue_next' is empty */
2780     BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0);
2781
2782   } while (BLI_LINKSTACK_SIZE(queue));
2783
2784   BLI_LINKSTACK_FREE(queue);
2785   BLI_LINKSTACK_FREE(queue_next);
2786
2787   MEM_freeN(dists_prev);
2788   if (index_prev != NULL) {
2789     MEM_freeN(index_prev);
2790   }
2791 }
2792
2793 static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em,
2794                                                           int *r_island_tot,
2795                                                           int **r_island_vert_map,
2796                                                           bool calc_single_islands)
2797 {
2798   BMesh *bm = em->bm;
2799   struct TransIslandData *trans_islands;
2800   char htype;
2801   char itype;
2802   int i;
2803
2804   /* group vars */
2805   int *groups_array;
2806   int(*group_index)[2];
2807   int group_tot;
2808   void **ele_array;
2809
2810   int *vert_map;
2811
2812   if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
2813     groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__);
2814     group_tot = BM_mesh_calc_edge_groups(
2815         bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT);
2816
2817     htype = BM_EDGE;
2818     itype = BM_VERTS_OF_EDGE;
2819   }
2820   else { /* (bm->selectmode & SCE_SELECT_FACE) */
2821     groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
2822     group_tot = BM_mesh_calc_face_groups(
2823         bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT, BM_VERT);
2824
2825     htype = BM_FACE;
2826     itype = BM_VERTS_OF_FACE;
2827   }
2828
2829   trans_islands = MEM_mallocN(sizeof(*trans_islands) * group_tot, __func__);
2830
2831   vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__);
2832   /* we shouldn't need this, but with incorrect selection flushing
2833    * its possible we have a selected vertex that's not in a face,
2834    * for now best not crash in that case. */
2835   copy_vn_i(vert_map, bm->totvert, -1);
2836
2837   BM_mesh_elem_table_ensure(bm, htype);
2838   ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable;
2839
2840   BM_mesh_elem_index_ensure(bm, BM_VERT);
2841
2842   /* may be an edge OR a face array */
2843   for (i = 0; i < group_tot; i++) {
2844     BMEditSelection ese = {NULL};
2845
2846     const int fg_sta = group_index[i][0];
2847     const int fg_len = group_index[i][1];
2848     float co[3], no[3], tangent[3];
2849     int j;
2850
2851     zero_v3(co);
2852     zero_v3(no);
2853     zero_v3(tangent);
2854
2855     ese.htype = htype;
2856
2857     /* loop on each face in this group:
2858      * - assign r_vert_map
2859      * - calculate (co, no)
2860      */
2861     for (j = 0; j < fg_len; j++) {
2862       float tmp_co[3], tmp_no[3], tmp_tangent[3];
2863
2864       ese.ele = ele_array[groups_array[fg_sta + j]];
2865
2866       BM_editselection_center(&ese, tmp_co);
2867       BM_editselection_normal(&ese, tmp_no);
2868       BM_editselection_plane(&ese, tmp_tangent);
2869
2870       add_v3_v3(co, tmp_co);
2871       add_v3_v3(no, tmp_no);
2872       add_v3_v3(tangent, tmp_tangent);
2873
2874       {
2875         /* setup vertex map */
2876         BMIter iter;
2877         BMVert *v;
2878
2879         /* connected edge-verts */
2880         BM_ITER_ELEM (v, &iter, ese.ele, itype) {
2881           vert_map[BM_elem_index_get(v)] = i;
2882         }
2883       }
2884     }
2885
2886     mul_v3_v3fl(trans_islands[i].co, co, 1.0f / (float)fg_len);
2887
2888     if (createSpaceNormalTangent(trans_islands[i].axismtx, no, tangent)) {
2889       /* pass */
2890     }
2891     else {
2892       if (normalize_v3(no) != 0.0f) {
2893         axis_dominant_v3_to_m3(trans_islands[i].axismtx, no);
2894         invert_m3(trans_islands[i].axismtx);
2895       }
2896       else {
2897         unit_m3(trans_islands[i].axismtx);
2898       }
2899     }
2900   }
2901
2902   MEM_freeN(groups_array);
2903   MEM_freeN(group_index);
2904
2905   /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */
2906   if (calc_single_islands) {
2907     BMIter viter;
2908     BMVert *v;
2909     int group_tot_single = 0;
2910
2911     BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
2912       if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
2913         group_tot_single += 1;
2914       }
2915     }
2916
2917     if (group_tot_single != 0) {
2918       trans_islands = MEM_reallocN(trans_islands,
2919                                    sizeof(*trans_islands) * (group_tot + group_tot_single));
2920
2921       BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
2922         if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
2923           struct TransIslandData *v_island = &trans_islands[group_tot];
2924           vert_map[i] = group_tot;
2925
2926           copy_v3_v3(v_island->co, v->co);
2927
2928           if (is_zero_v3(v->no) != 0.0f) {
2929             axis_dominant_v3_to_m3(v_island->axismtx, v->no);
2930             invert_m3(v_island->axismtx);
2931           }
2932           else {
2933             unit_m3(v_island->axismtx);
2934           }
2935
2936           group_tot += 1;
2937         }
2938       }
2939     }
2940   }
2941
2942   *r_island_tot = group_tot;
2943   *r_island_vert_map = vert_map;
2944
2945   return trans_islands;
2946 }
2947
2948 /* way to overwrite what data is edited with transform */
2949 static void VertsToTransData(TransInfo *t,
2950                              TransData *td,
2951                              TransDataExtension *tx,
2952                              BMEditMesh *em,
2953                              BMVert *eve,
2954                              float *bweight,
2955                              struct TransIslandData *v_island,
2956                              const bool no_island_center)
2957 {
2958   float *no, _no[3];
2959   BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
2960
2961   td->flag = 0;
2962   // if (key)
2963   //  td->loc = key->co;
2964   // else
2965   td->loc = eve->co;
2966   copy_v3_v3(td->iloc, td->loc);
2967
2968   if ((t->mode == TFM_SHRINKFATTEN) && (em->selectmode & SCE_SELECT_FACE) &&
2969       BM_elem_flag_test(eve, BM_ELEM_SELECT) &&
2970       (BM_vert_calc_normal_ex(eve, BM_ELEM_SELECT, _no))) {
2971     no = _no;
2972   }
2973   else {
2974     no = eve->no;
2975   }
2976
2977   if (v_island) {
2978     if (no_island_center) {
2979       copy_v3_v3(td->center, td->loc);
2980     }
2981     else {
2982       copy_v3_v3(td->center, v_island->co);
2983     }
2984     copy_m3_m3(td->axismtx, v_island->axismtx);
2985   }
2986   else if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
2987     copy_v3_v3(td->center, td->loc);
2988     createSpaceNormal(td->axismtx, no);
2989   }
2990   else {
2991     copy_v3_v3(td->center, td->loc);
2992
2993     /* Setting normals */
2994     copy_v3_v3(td->axismtx[2], no);
2995     td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] =
2996         td->axismtx[1][1] = td->axismtx[1][2] = 0.0f;
2997   }
2998
2999   td->ext = NULL;
3000   td->val = NULL;
3001   td->extra = NULL;
3002   if (t->mode == TFM_BWEIGHT) {
3003     td->val = bweight;
3004     td->ival = *bweight;
3005   }
3006   else if (t->mode == TFM_SKIN_RESIZE) {
3007     MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MVERT_SKIN);
3008     if (vs) {
3009       /* skin node size */
3010       td->ext = tx;
3011       copy_v3_v3(tx->isize, vs->radius);
3012       tx->size = vs->radius;
3013       td->val = vs->radius;
3014     }
3015     else {
3016       td->flag |= TD_SKIP;
3017     }
3018   }
3019   else if (t->mode == TFM_SHRINKFATTEN) {
3020     td->ext = tx;
3021     tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, no, BM_ELEM_SELECT);
3022   }
3023 }
3024
3025 static void createTransEditVerts(TransInfo *t)
3026 {
3027   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
3028     TransData *tob = NULL;
3029     TransDataExtension *tx = NULL;
3030     BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
3031     Mesh *me = tc->obedit->data;
3032     BMesh *bm = em->bm;
3033     BMVert *eve;
3034     BMIter iter;
3035     float(*mappedcos)[3] = NULL, (*quats)[4] = NULL;
3036     float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
3037     float *dists = NULL;
3038     int a;
3039     const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
3040     int mirror = 0;
3041     int cd_vert_bweight_offset = -1;
3042     bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
3043
3044     struct TransIslandData *island_info = NULL;
3045     int island_info_tot;
3046     int *island_vert_map = NULL;
3047
3048     /* Snap rotation along normal needs a common axis for whole islands,
3049      * otherwise one get random crazy results, see T59104.
3050      * However, we do not want to use the island center for the pivot/translation reference. */
3051     const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) &&
3052                                  /* There is not guarantee that snapping
3053                                   * is initialized yet at this point... */
3054                                  (usingSnappingNormal(t) ||
3055                                   (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) &&
3056                                  (t->around != V3D_AROUND_LOCAL_ORIGINS));
3057     /* Even for translation this is needed because of island-orientation, see: T51651. */
3058     const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate;
3059     /* Original index of our connected vertex when connected distances are calculated.
3060      * Optional, allocate if needed. */
3061     int *dists_index = NULL;
3062
3063     if (tc->mirror.axis_flag) {
3064       EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
3065       mirror = 1;
3066     }
3067
3068     /**
3069      * Quick check if we can transform.
3070      *
3071      * \note ignore modes here, even in edge/face modes,
3072      * transform data is created by selected vertices.
3073      * \note in prop mode we need at least 1 selected.
3074      */
3075     if (bm->totvertsel == 0) {
3076       goto cleanup;
3077     }
3078
3079     if (t->mode == TFM_BWEIGHT) {
3080       BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT);
3081       cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
3082     }
3083
3084     if (prop_mode) {
3085       unsigned int count = 0;
3086       BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
3087         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
3088           count++;
3089         }
3090       }
3091
3092       tc->data_len = count;
3093
3094       /* allocating scratch arrays */
3095       if (prop_mode & T_PROP_CONNECTED) {
3096         dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__);
3097         if (is_island_center) {
3098           dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__);
3099         }
3100       }
3101     }
3102     else {
3103       tc->data_len = bm->totvertsel;
3104     }
3105
3106     tob = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
3107     if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
3108       /* warning, this is overkill, we only need 2 extra floats,
3109        * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
3110        * since we may not use the 'alt' transform mode to maintain shell thickness,
3111        * but with generic transform code its hard to lazy init vars */
3112       tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
3113                                       "TransObData ext");
3114     }
3115
3116     copy_m3_m4(mtx, tc->obedit->obmat);
3117     /* we use a pseudo-inverse so that when one of the axes is scaled to 0,
3118      * matrix inversion still works and we can still moving along the other */
3119     pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
3120
3121     if (prop_mode & T_PROP_CONNECTED) {
3122       editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
3123     }
3124
3125     if (is_island_center) {
3126       /* In this specific case, near-by vertices will need to know
3127        * the island of the nearest connected vertex. */
3128       const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) &&
3129                                         (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
3130                                         (em->selectmode & SCE_SELECT_VERTEX));
3131
3132       island_info = editmesh_islands_info_calc(
3133           em, &island_info_tot, &island_vert_map, calc_single_islands);
3134     }
3135
3136     /* detect CrazySpace [tm] */
3137     if (modifiers_getCageIndex(t->scene, tc->obedit, NULL, 1) != -1) {
3138       int totleft = -1;
3139       if (modifiers_isCorrectableDeformed(t->scene, tc->obedit)) {
3140         BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context));
3141
3142         /* Use evaluated state because we need b-bone cache. */
3143         Scene *scene_eval = (Scene *)DEG_get_evaluated_id(t->depsgraph, &t->scene->id);
3144         Object *obedit_eval = (Object *)DEG_get_evaluated_id(t->depsgraph, &tc->obedit->id);
3145         BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
3146         /* check if we can use deform matrices for modifier from the
3147          * start up to stack, they are more accurate than quats */
3148         totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(
3149             t->depsgraph, scene_eval, obedit_eval, em_eval, &defmats, &defcos);
3150       }
3151
3152       /* if we still have more modifiers, also do crazyspace
3153        * correction with quats, relative to the coordinates after
3154        * the modifiers that support deform matrices (defcos) */
3155
3156 #if 0 /* TODO, fix crazyspace+extrude so it can be enabled for general use - campbell */
3157       if ((totleft > 0) || (totleft == -1))
3158 #else
3159       if (totleft > 0)
3160 #endif
3161       {
3162         mappedcos = BKE_crazyspace_get_mapped_editverts(t->depsgraph, tc->obedit);
3163         quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
3164         BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
3165         if (mappedcos) {
3166           MEM_freeN(mappedcos);
3167         }
3168       }
3169
3170       if (defcos) {
3171         MEM_freeN(defcos);
3172       }
3173     }
3174
3175     /* find out which half we do */
3176     if (mirror) {
3177       BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
3178         if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve->co[0] != 0.0f) {
3179           if (eve->co[0] < 0.0f) {
3180             tc->mirror.sign = -1.0f;
3181             mirror = -1;
3182           }
3183           break;
3184         }
3185       }
3186     }
3187
3188     BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
3189       if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
3190         if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
3191           struct TransIslandData *v_island = NULL;
3192           float *bweight = (cd_vert_bweight_offset != -1) ?
3193                                BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) :
3194                                NULL;
3195
3196           if (island_info) {
3197             const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
3198             v_island = (island_vert_map[connected_index] != -1) ?
3199                            &island_info[island_vert_map[connected_index]] :
3200                            NULL;
3201           }
3202
3203           /* Do not use the island center in case we are using islands
3204            * only to get axis for snap/rotate to normal... */
3205           VertsToTransData(t, tob, tx, em, eve, bweight, v_island, is_snap_rotate);
3206           if (tx) {
3207             tx++;
3208           }
3209
3210           /* selected */
3211           if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
3212             tob->flag |= TD_SELECTED;
3213           }
3214
3215           if (prop_mode) {
3216             if (prop_mode & T_PROP_CONNECTED) {
3217               tob->dist = dists[a];
3218             }
3219             else {
3220               tob->flag |= TD_NOTCONNECTED;
3221               tob->dist = FLT_MAX;
3222             }
3223           }
3224
3225           /* CrazySpace */
3226           const bool use_quats = quats && BM_elem_flag_test(eve, BM_ELEM_TAG);
3227           if (use_quats || defmats) {
3228             float mat[3][3], qmat[3][3], imat[3][3];
3229
3230             /* Use both or either quat and defmat correction. */
3231             if (use_quats) {
3232               quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
3233
3234               if (defmats) {
3235                 mul_m3_series(mat, defmats[a], qmat, mtx);
3236               }
3237               else {
3238                 mul_m3_m3m3(mat, mtx, qmat);
3239               }
3240             }
3241             else {
3242               mul_m3_m3m3(mat, mtx, defmats[a]);
3243             }
3244
3245             invert_m3_m3(imat, mat);
3246
3247             copy_m3_m3(tob->smtx, imat);
3248             copy_m3_m3(tob->mtx, mat);
3249           }
3250           else {
3251             copy_m3_m3(tob->smtx, smtx);
3252             copy_m3_m3(tob->mtx, mtx);
3253           }
3254
3255           /* Mirror? */
3256           if ((mirror > 0 && tob->iloc[0] > 0.0f) || (mirror < 0 && tob->iloc[0] < 0.0f)) {
3257             BMVert *vmir = EDBM_verts_mirror_get(em, eve);  // t->obedit, em, eve, tob->iloc, a);
3258             if (vmir && vmir != eve) {
3259               tob->extra = vmir;
3260             }
3261           }
3262           tob++;
3263         }
3264       }
3265     }
3266
3267     if (island_info) {
3268       MEM_freeN(island_info);
3269       MEM_freeN(island_vert_map);
3270     }
3271
3272     if (mirror != 0) {
3273       tob = tc->data;
3274       for (a = 0; a < tc->data_len; a++, tob++) {
3275         if (ABS(tob->loc[0]) <= 0.00001f) {
3276           tob->flag |= TD_MIRROR_EDGE;
3277         }
3278       }
3279     }
3280
3281   cleanup:
3282     /* crazy space free */
3283     if (quats) {
3284       MEM_freeN(quats);
3285     }
3286     if (defmats) {
3287       MEM_freeN(defmats);
3288     }
3289     if (dists) {
3290       MEM_freeN(dists);
3291     }
3292     if (dists_index) {
3293       MEM_freeN(dists_index);
3294     }
3295
3296     if (tc->mirror.axis_flag) {
3297       EDBM_verts_mirror_cache_end(em);
3298     }
3299   }
3300 }
3301
3302 /* *** NODE EDITOR *** */
3303 void flushTransNodes(TransInfo *t)
3304 {
3305   const float dpi_fac = UI_DPI_FAC;
3306
3307   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
3308     int a;
3309     TransData *td;
3310     TransData2D *td2d;
3311
3312     applyGridAbsolute(t);
3313
3314     /* flush to 2d vector from internally used 3d vector */
3315     for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
3316       bNode *node = td->extra;
3317       float locx, locy;
3318
3319       /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
3320 #ifdef USE_NODE_CENTER
3321       locx = (td2d->loc[0] - (BLI_rctf_size_x(&node->totr)) * +0.5f) / dpi_fac;
3322       locy = (td2d->loc[1] - (BLI_rctf_size_y(&node->totr)) * -0.5f) / dpi_fac;
3323 #else
3324       locx = td2d->loc[0] / dpi_fac;
3325       locy = td2d->loc[1] / dpi_fac;
3326 #endif
3327
3328       /* account for parents (nested nodes) */
3329       if (node->parent) {
3330         nodeFromView(node->parent, locx, locy, &node->locx, &node->locy);
3331       }
3332       else {
3333         node->locx = locx;
3334         node->locy = locy;
3335       }
3336     }
3337
3338     /* handle intersection with noodles */
3339     if (tc->data_len == 1) {
3340       ED_node_link_intersect_test(t->sa, 1);
3341     }
3342   }
3343 }
3344
3345 /* *** SEQUENCE EDITOR *** */
3346
3347 /* commented _only_ because the meta may have animation data which
3348  * needs moving too [#28158] */
3349
3350 #define SEQ_TX_NESTED_METAS
3351
3352 BLI_INLINE void trans_update_seq(Scene *sce, Sequence *seq, int old_start, int sel_flag)
3353 {
3354   if (seq->depth == 0) {
3355     /* Calculate this strip and all nested strips.
3356      * Children are ALWAYS transformed first so we don't need to do this in another loop.
3357      */
3358     BKE_sequence_calc(sce, seq);
3359   }
3360   else {
3361     BKE_sequence_calc_disp(sce, seq);
3362   }
3363
3364   if (sel_flag == SELECT) {
3365     BKE_sequencer_offset_animdata(sce, seq, seq->start - old_start);
3366   }
3367 }
3368
3369 void flushTransSeq(TransInfo *t)
3370 {
3371   /* Editing null check already done */
3372   ListBase *seqbasep = BKE_sequencer_editing_get(t->scene, false)->seqbasep;
3373
3374   int a, new_frame;
3375   TransData *td = NULL;
3376   TransData2D *td2d = NULL;
3377   TransDataSeq *tdsq = NULL;
3378   Sequence *seq;
3379
3380   TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
3381
3382   /* prevent updating the same seq twice
3383    * if the transdata order is changed this will mess up
3384    * but so will TransDataSeq */
3385   Sequence *seq_prev = NULL;
3386   int old_start_prev = 0, sel_flag_prev = 0;
3387
3388   /* flush to 2d vector from internally used 3d vector */
3389   for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
3390     int old_start;
3391     tdsq = (TransDataSeq *)td->extra;
3392     seq = tdsq->seq;
3393     old_start = seq->start;
3394     new_frame = round_fl_to_int(td2d->loc[0]);
3395
3396     switch (tdsq->sel_flag) {
3397       case SELECT:
3398 #ifdef SEQ_TX_NESTED_METAS
3399         if ((seq->depth != 0 || BKE_sequence_tx_test(seq))) {
3400           /* for meta's, their children move */
3401           seq->start = new_frame - tdsq->start_offset;
3402         }
3403 #else
3404         if (seq->type != SEQ_TYPE_META && (seq->depth != 0 || seq_tx_test(seq))) {
3405           /* for meta's, their children move */
3406           seq->start = new_frame - tdsq->start_offset;
3407         }
3408 #endif
3409         if (seq->depth == 0) {
3410           seq->machine = round_fl_to_int(td2d->loc[1]);
3411           CLAMP(seq->machine, 1, MAXSEQ);
3412         }
3413         break;
3414       case SEQ_LEFTSEL: /* no vertical transform  */
3415         BKE_sequence_tx_set_final_left(seq, new_frame);
3416         BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
3417
3418         /* todo - move this into aftertrans update? - old seq tx needed it anyway */
3419         BKE_sequence_single_fix(seq);
3420         break;
3421       case SEQ_RIGHTSEL: /* no vertical transform  */
3422         BKE_sequence_tx_set_final_right(seq, new_frame);
3423         BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
3424
3425         /* todo - move this into aftertrans update? - old seq tx needed it anyway */
3426         BKE_sequence_single_fix(seq);
3427         break;
3428     }
3429
3430     /* Update *previous* seq! Else, we would update a seq after its first transform,
3431      * and if it has more than one (like e.g. SEQ_LEFTSEL and SEQ_RIGHTSEL),
3432      * the others are not updated! See T38469.
3433      */
3434     if (seq != seq_prev) {
3435       if (seq_prev) {
3436         trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
3437       }
3438
3439       seq_prev = seq;
3440       old_start_prev = old_start;
3441       sel_flag_prev = tdsq->sel_flag;
3442     }
3443     else {
3444       /* We want to accumulate *all* sel_flags for this seq! */
3445       sel_flag_prev |= tdsq->sel_flag;
3446     }
3447   }
3448
3449   /* Don't forget to update the last seq! */
3450   if (seq_prev) {
3451     trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
3452   }
3453
3454   /* originally TFM_TIME_EXTEND, transform changes */
3455   if (ELEM(t->mode, TFM_SEQ_SLIDE, TFM_TIME_TRANSLATE)) {
3456     /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
3457
3458     /* calc all meta's then effects [#27953] */
3459     for (seq = seqbasep->first; seq; seq = seq->next) {
3460       if (seq->type == SEQ_TYPE_META && seq->flag & SELECT) {
3461         BKE_sequence_calc(t->scene, seq);
3462       }
3463     }
3464     for (seq = seqbasep->first; seq; seq = seq->next) {
3465       if (seq->seq1 || seq->seq2 || seq->seq3) {
3466         BKE_sequence_calc(t->scene, seq);
3467       }
3468     }
3469
3470     /* update effects inside meta's */
3471     for (a = 0, seq_prev = NULL, td = tc->data, td2d = tc->data_2d; a < tc->data_len;
3472          a++, td++, td2d++, seq_prev = seq) {
3473       tdsq = (TransDataSeq *)td->extra;
3474       seq = tdsq->seq;
3475       if ((seq != seq_prev) && (seq->depth != 0)) {
3476         if (seq->seq1 || seq->seq2 || seq->seq3) {
3477           BKE_sequence_calc(t->scene, seq);
3478         }
3479       }
3480     }
3481   }
3482
3483   /* need to do the overlap check in a new loop otherwise adjacent strips
3484    * will not be updated and we'll get false positives */
3485   seq_prev = NULL;
3486   for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
3487
3488     tdsq = (TransDataSeq *)td->extra;
3489     seq = tdsq->seq;
3490
3491     if (seq != seq_prev) {
3492       if (seq->depth == 0) {
3493         /* test overlap, displays red outline */
3494         seq->flag &= ~SEQ_OVERLAP;
3495         if (BKE_sequence_test_overlap(seqbasep, seq)) {
3496           seq->flag |= SEQ_OVERLAP;
3497         }
3498       }
3499     }
3500     seq_prev = seq;
3501   }
3502 }
3503
3504 /* ********************* UV ****************** */
3505
3506 static void UVsToTransData(const float aspect[2],
3507                            TransData *td,
3508                            TransData2D *td2d,
3509                            float *uv,
3510                            const float *center,
3511                            bool selected)
3512 {
3513   /* uv coords are scaled by aspects. this is needed for rotations and
3514    * proportional editing to be consistent with the stretched uv coords
3515    * that are displayed. this also means that for display and numinput,
3516    * and when the uv coords are flushed, these are converted each time */
3517   td2d->loc[0] = uv[0] * aspect[0];
3518   td2d->loc[1] = uv[1] * aspect[1];
3519   td2d->loc[2] = 0.0f;
3520   td2d->loc2d = uv;
3521
3522   td->flag = 0;
3523   td->loc = td2d->loc;
3524   copy_v2_v2(td->center, center ? center : td->loc);
3525   td->center[2] = 0.0f;
3526   copy_v3_v3(td->iloc, td->loc);
3527
3528   memset(td->axismtx, 0, sizeof(td->axismtx));
3529   td->axismtx[2][2] = 1.0f;
3530
3531   td->ext = NULL;
3532   td->val = NULL;
3533
3534   if (selected) {
3535     td->flag |= TD_SELECTED;
3536     td->dist = 0.0;
3537   }
3538   else {
3539     td->dist = FLT_MAX;
3540   }
3541   unit_m3(td->mtx);
3542   unit_m3(td->smtx);
3543 }
3544
3545 static void createTransUVs(bContext *C, TransInfo *t)
3546 {
3547   SpaceImage *sima = CTX_wm_space_image(C);
3548   Image *ima = CTX_data_edit_image(C);
3549   Scene *scene = t->scene;
3550   ToolSettings *ts = CTX_data_tool_settings(C);
3551
3552   const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
3553   const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0;
3554   const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
3555
3556   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
3557
3558     TransData *td = NULL;
3559     TransData2D *td2d = NULL;
3560     BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
3561     BMFace *efa;
3562     BMIter iter, liter;
3563     UvElementMap *elementmap = NULL;
3564     BLI_bitmap *island_enabled = NULL;
3565     struct {
3566       float co[2];
3567       int co_num;
3568     } *island_center = NULL;
3569     int count = 0, countsel = 0, count_rejected = 0;
3570     const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
3571
3572     if (!ED_space_image_show_uvedit(sima, tc->obedit)) {
3573       continue;
3574     }
3575
3576     /* count */
3577     if (is_prop_connected || is_island_center) {
3578       /* create element map with island information */
3579       const bool use_facesel = (ts->uv_flag & UV_SYNC_SELECTION) == 0;
3580       elementmap = BM_uv_element_map_create(em->bm, use_facesel, false, true);
3581       if (elementmap == NULL) {
3582         return;
3583       }
3584
3585       if (is_prop_connected) {
3586         island_enabled = BLI_BITMAP_NEW(elementmap->totalIslands, "TransIslandData(UV Editing)");
3587       }
3588
3589       if (is_island_center) {
3590         island_center = MEM_callocN(sizeof(*island_center) * elementmap->totalIslands, __func__);
3591       }
3592     }
3593
3594     BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
3595       BMLoop *l;
3596
3597       if (!uvedit_face_visible_test(scene, tc->obedit, ima, efa)) {
3598         BM_elem_flag_disable(efa, BM_ELEM_TAG);
3599         continue;
3600       }
3601
3602       BM_elem_flag_enable(efa, BM_ELEM_TAG);
3603       BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
3604         if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
3605           countsel++;
3606
3607           if (is_prop_connected || island_center) {
3608             UvElement *element = BM_uv_element_get(elementmap, efa, l);
3609
3610             if (is_prop_connected) {
3611               BLI_BITMAP_ENABLE(island_enabled, element->island);
3612             }
3613
3614             if (is_island_center) {
3615               if (element->flag == false) {
3616                 MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
3617                 add_v2_v2(island_center[element->island].co, luv->uv);
3618                 island_center[element->island].co_num++;
3619                 element->flag = true;
3620               }
3621             }
3622           }
3623         }
3624
3625         if (is_prop_edit) {
3626           count++;
3627         }
3628       }
3629     }
3630
3631     /* note: in prop mode we need at least 1 selected */
3632     if (countsel == 0) {
3633       goto finally;
3634     }
3635
3636     if (is_island_center) {
3637       int i;
3638
3639       for (i = 0; i < elementmap->totalIslands; i++) {
3640         mul_v2_fl(island_center[i].co, 1.0f / island_center[i].co_num);
3641         mul_v2_v2(island_center[i].co, t->aspect);
3642       }
3643     }
3644
3645     tc->data_len = (is_prop_edit) ? count : countsel;
3646     tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(UV Editing)");
3647     /* for each 2d uv coord a 3d vector is allocated, so that they can be
3648      * treated just as if they were 3d verts */
3649     tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransObData2D(UV Editing)");
3650
3651     if (sima->flag & SI_CLIP_UV) {
3652       t->flag |= T_CLIP_UV;
3653     }
3654
3655     td = tc->data;
3656     td2d = tc->data_2d;
3657
3658     BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
3659       BMLoop *l;
3660
3661       if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) {
3662         continue;
3663       }
3664
3665       BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
3666         const bool selected = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
3667         MLoopUV *luv;
3668         const float *center = NULL;
3669
3670         if (!is_prop_edit && !selected) {
3671           continue;
3672         }
3673
3674         if (is_prop_connected || is_island_center) {
3675           UvElement *element = BM_uv_element_get(elementmap, efa, l);
3676
3677           if (is_prop_connected) {
3678             if (!BLI_BITMAP_TEST(island_enabled, element->island)) {
3679               count_rejected++;
3680               continue;
3681             }
3682           }
3683
3684           if (is_island_center) {
3685             center = island_center[element->island].co;
3686           }
3687         }
3688
3689         BM_elem_flag_enable(l, BM_ELEM_TAG);
3690         luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
3691         UVsToTransData(t->aspect, td++, td2d++, luv->uv, center, selected);
3692       }
3693     }
3694
3695     if (is_prop_connected) {
3696       tc->data_len -= count_rejected;
3697     }
3698
3699     if (sima->flag & SI_LIVE_UNWRAP) {
3700       ED_uvedit_live_unwrap_begin(t->scene, tc->obedit);
3701     }
3702
3703   finally:
3704     if (is_prop_connected || is_island_center) {
3705       BM_uv_element_map_free(elementmap);
3706
3707       if (is_prop_connected) {
3708         MEM_freeN(island_enabled);
3709       }
3710
3711       if (island_center) {
3712         MEM_freeN(island_center);
3713       }
3714     }
3715   }
3716 }
3717
3718 void flushTransUVs(TransInfo *t)
3719 {
3720   SpaceImage *sima = t->sa->spacedata.first;
3721   const bool use_pixel_snap = ((sima->pixel_snap_mode != SI_PIXEL_SNAP_DISABLED) &&
3722                                (t->state != TRANS_CANCEL));
3723
3724   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
3725     TransData2D *td;
3726     int a;
3727     float aspect_inv[2], size[2];
3728
3729     aspect_inv[0] = 1.0f / t->aspect[0];
3730     aspect_inv[1] = 1.0f / t->aspect[1];
3731
3732     if (use_pixel_snap) {
3733       int size_i[2];
3734       ED_space_image_get_size(sima, &size_i[0], &size_i[1]);
3735       size[0] = size_i[0];
3736       size[1] = size_i[1];
3737     }
3738
3739     /* flush to 2d vector from internally used 3d vector */
3740     for (a = 0, td = tc->data_2d; a < tc->data_len; a++, td++) {
3741       td->loc2d[0] = td->loc[0] * aspect_inv[0];
3742       td->loc2d[1] = td->loc[1] * aspect_inv[1];
3743
3744       if (use_pixel_snap) {
3745         td->loc2d[0] *= size[0];
3746         td->loc2d[1] *= size[1];
3747
3748         switch (sima->pixel_snap_mode) {
3749           case SI_PIXEL_SNAP_CENTER:
3750             td->loc2d[0] = roundf(td->loc2d[0] - 0.5f) + 0.5f;
3751             td->loc2d[1] = roundf(td->loc2d[1] - 0.5f) + 0.5f;
3752             break;
3753           case SI_PIXEL_SNAP_CORNER:
3754             td->loc2d[0] = roundf(td->loc2d[0]);
3755             td->loc2d[1] = roundf(td->loc2d[1]);
3756             break;
3757         }
3758
3759         td->loc2d[0] /= size[0];
3760         td->loc2d[1] /= size[1];
3761       }
3762     }
3763   }
3764 }
3765
3766 bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
3767 {
3768   bool clipx = true, clipy = true;
3769   float min[2], max[2];
3770
3771   min[0] = min[1] = 0.0f;
3772   max[0] = t->aspect[0];
3773   max[1] = t->aspect[1];
3774
3775   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
3776
3777     TransData *td;
3778     int a;
3779
3780     for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
3781       minmax_v2v2_v2(min, max, td->loc);
3782     }
3783   }
3784
3785   if (resize) {
3786     if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f) {
3787       vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
3788     }
3789     else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0]) {
3790       vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
3791     }
3792     else {
3793       clipx = 0;
3794     }
3795
3796     if (min[1] < 0.0f && t->center_global[1] > 0.0f && t->center_global[1] < t->aspect[1] * 0.5f) {
3797       vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
3798     }
3799     else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1]) {
3800       vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
3801     }
3802     else {
3803       clipy = 0;
3804     }
3805   }
3806   else {
3807     if (min[0] < 0.0f) {
3808       vec[0] -= min[0];
3809     }
3810     else if (max[0] > t->aspect[0]) {
3811       vec[0] -= max[0] - t->aspect[0];
3812     }
3813     else {
3814       clipx = 0;
3815     }
3816
3817     if (min[1] < 0.0f) {
3818       vec[1] -= min[1];
3819     }
3820     else if (max[1] > t->aspect[1]) {
3821       vec[1] -= max[1] - t->aspect[1];
3822     }
3823     else {
3824       clipy = 0;
3825     }
3826   }
3827
3828   return (clipx || clipy);
3829 }
3830
3831 void clipUVData(TransInfo *t)
3832 {
3833   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
3834     TransData *td = tc->data;
3835     for (int a = 0; a < tc->data_len; a++, td++) {
3836       if (td->flag & TD_NOACTION) {
3837         break;
3838       }
3839
3840       if ((td->flag & TD_SKIP) || (!td->loc)) {
3841         continue;
3842       }
3843
3844       td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), t->aspect[0]);
3845       td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), t->aspect[1]);
3846     }
3847   }
3848 }
3849
3850 /* ********************* ANIMATION EDITORS (GENERAL) ************************* */
3851
3852 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
3853 static bool FrameOnMouseSide(char side, float frame, float cframe)
3854 {
3855   /* both sides, so it doesn't matter */
3856   if (side == 'B') {
3857     return true;
3858   }
3859
3860   /* only on the named side */
3861   if (side == 'R') {
3862     return (frame >= cframe);
3863   }
3864   else {
3865     return (frame <= cframe);
3866   }
3867 }
3868
3869 /* ********************* NLA EDITOR ************************* */
3870
3871 static void createTransNlaData(bContext *C, TransInfo *t)
3872 {
3873   Scene *scene = t->scene;
3874   SpaceNla *snla = NULL;
3875   TransData *td = NULL;
3876   TransDataNla *tdn = NULL;
3877
3878   bAnimContext ac;
3879   ListBase anim_data = {NULL, NULL};
3880   bAnimListElem *ale;
3881   int filter;
3882
3883   int count = 0;
3884
3885   TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
3886
3887   /* determine what type of data we are operating on */
3888   if (ANIM_animdata_get_context(C, &ac) == 0) {
3889     return;
3890   }
3891   snla = (SpaceNla *)ac.sl;
3892
3893   /* filter data */
3894   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
3895   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
3896
3897   /* which side of the current frame should be allowed */
3898   if (t->mode == TFM_TIME_EXTEND) {
3899     /* only side on which mouse is gets transformed */
3900     float xmouse, ymouse;
3901
3902     UI_view2d_region_to_view(&ac.ar->v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
3903     t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
3904   }
3905   else {
3906     /* normal transform - both sides of current frame are considered */
3907     t->frame_side = 'B';
3908   }
3909
3910   /* loop 1: count how many strips are selected (consider each strip as 2 points) */
3911   for (ale = anim_data.first; ale; ale = ale->next) {
3912     NlaTrack *nlt = (NlaTrack *)ale->data;
3913     NlaStrip *strip;
3914
3915     /* make some meta-strips for chains of selected strips */
3916     BKE_nlastrips_make_metas(&nlt->strips, 1);
3917
3918     /* only consider selected strips */
3919     for (strip = nlt->strips.first; strip; strip = strip->next) {
3920       // TODO: we can make strips have handles later on...
3921       /* transition strips can't get directly transformed */
3922       if (strip->type != NLASTRIP_TYPE_TRANSITION) {
3923         if (strip->flag & NLASTRIP_FLAG_SELECT) {
3924           if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) {
3925             count++;
3926           }
3927           if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) {
3928             count++;
3929           }
3930         }
3931       }
3932     }
3933   }
3934
3935   /* stop if trying to build list if nothing selected */
3936   if (count == 0) {
3937     /* clear temp metas that may have been created but aren't needed now
3938      * because they fell on the wrong side of CFRA
3939      */
3940     for (ale = anim_data.first; ale; ale = ale->next) {
3941       NlaTrack *nlt = (NlaTrack *)ale->dat