Merge branch 'blender-v2.81-release'
[blender.git] / source / blender / editors / transform / transform_convert.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 "DNA_anim_types.h"
25 #include "DNA_armature_types.h"
26 #include "DNA_space_types.h"
27 #include "DNA_constraint_types.h"
28 #include "DNA_gpencil_types.h"
29 #include "DNA_mask_types.h"
30
31 #include "MEM_guardedalloc.h"
32
33 #include "BLI_math.h"
34 #include "BLI_listbase.h"
35 #include "BLI_string.h"
36 #include "BLI_kdtree.h"
37
38 #include "BKE_animsys.h"
39 #include "BKE_armature.h"
40 #include "BKE_context.h"
41 #include "BKE_fcurve.h"
42 #include "BKE_global.h"
43 #include "BKE_gpencil.h"
44 #include "BKE_layer.h"
45 #include "BKE_key.h"
46 #include "BKE_main.h"
47 #include "BKE_modifier.h"
48 #include "BKE_nla.h"
49 #include "BKE_node.h"
50 #include "BKE_pointcache.h"
51 #include "BKE_rigidbody.h"
52 #include "BKE_scene.h"
53 #include "BKE_editmesh.h"
54 #include "BKE_tracking.h"
55 #include "BKE_mask.h"
56
57 #include "BIK_api.h"
58
59 #include "ED_anim_api.h"
60 #include "ED_armature.h"
61 #include "ED_particle.h"
62 #include "ED_image.h"
63 #include "ED_keyframing.h"
64 #include "ED_keyframes_edit.h"
65 #include "ED_object.h"
66 #include "ED_markers.h"
67 #include "ED_mesh.h"
68 #include "ED_node.h"
69 #include "ED_clip.h"
70 #include "ED_mask.h"
71
72 #include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
73 #include "WM_types.h"
74
75 #include "RNA_access.h"
76
77 #include "DEG_depsgraph.h"
78 #include "DEG_depsgraph_build.h"
79
80 #include "transform.h"
81 #include "transform_convert.h"
82
83 /**
84  * Transforming around ourselves is no use, fallback to individual origins,
85  * useful for curve/armatures.
86  */
87 void transform_around_single_fallback(TransInfo *t)
88 {
89   if ((t->data_len_all == 1) &&
90       (ELEM(t->around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEDIAN, V3D_AROUND_ACTIVE)) &&
91       (ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL))) {
92     t->around = V3D_AROUND_LOCAL_ORIGINS;
93   }
94 }
95
96 /* ************************** Functions *************************** */
97
98 static int trans_data_compare_dist(const void *a, const void *b)
99 {
100   const TransData *td_a = (const TransData *)a;
101   const TransData *td_b = (const TransData *)b;
102
103   if (td_a->dist < td_b->dist) {
104     return -1;
105   }
106   else if (td_a->dist > td_b->dist) {
107     return 1;
108   }
109   else {
110     return 0;
111   }
112 }
113
114 static int trans_data_compare_rdist(const void *a, const void *b)
115 {
116   const TransData *td_a = (const TransData *)a;
117   const TransData *td_b = (const TransData *)b;
118
119   if (td_a->rdist < td_b->rdist) {
120     return -1;
121   }
122   else if (td_a->rdist > td_b->rdist) {
123     return 1;
124   }
125   else {
126     return 0;
127   }
128 }
129
130 static void sort_trans_data_dist_container(const TransInfo *t, TransDataContainer *tc)
131 {
132   TransData *start = tc->data;
133   int i;
134
135   for (i = 0; i < tc->data_len && start->flag & TD_SELECTED; i++) {
136     start++;
137   }
138
139   if (i < tc->data_len) {
140     if (t->flag & T_PROP_CONNECTED) {
141       qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_dist);
142     }
143     else {
144       qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_rdist);
145     }
146   }
147 }
148 void sort_trans_data_dist(TransInfo *t)
149 {
150   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
151     sort_trans_data_dist_container(t, tc);
152   }
153 }
154
155 /**
156  * Make #TD_SELECTED first in the array.
157  */
158 static void sort_trans_data_selected_first_container(TransDataContainer *tc)
159 {
160   TransData *sel, *unsel;
161   TransData temp;
162   unsel = tc->data;
163   sel = tc->data;
164   sel += tc->data_len - 1;
165   while (sel > unsel) {
166     while (unsel->flag & TD_SELECTED) {
167       unsel++;
168       if (unsel == sel) {
169         return;
170       }
171     }
172     while (!(sel->flag & TD_SELECTED)) {
173       sel--;
174       if (unsel == sel) {
175         return;
176       }
177     }
178     temp = *unsel;
179     *unsel = *sel;
180     *sel = temp;
181     sel--;
182     unsel++;
183   }
184 }
185 static void sort_trans_data_selected_first(TransInfo *t)
186 {
187   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
188     sort_trans_data_selected_first_container(tc);
189   }
190 }
191
192 /**
193  * Distance calculated from not-selected vertex to nearest selected vertex.
194  */
195 static void set_prop_dist(TransInfo *t, const bool with_dist)
196 {
197   int a;
198
199   float _proj_vec[3];
200   const float *proj_vec = NULL;
201
202   /* support for face-islands */
203   const bool use_island = transdata_check_local_islands(t, t->around);
204
205   if (t->flag & T_PROP_PROJECTED) {
206     if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
207       RegionView3D *rv3d = t->ar->regiondata;
208       normalize_v3_v3(_proj_vec, rv3d->viewinv[2]);
209       proj_vec = _proj_vec;
210     }
211   }
212
213   /* Count number of selected. */
214   int td_table_len = 0;
215   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
216     TransData *td = tc->data;
217     for (a = 0; a < tc->data_len; a++, td++) {
218       if (td->flag & TD_SELECTED) {
219         td_table_len++;
220       }
221       else {
222         /* By definition transform-data has selected items in beginning. */
223         break;
224       }
225     }
226   }
227
228   /* Pointers to selected's #TransData.
229    * Used to find #TransData from the index returned by #BLI_kdtree_find_nearest. */
230   TransData **td_table = MEM_mallocN(sizeof(*td_table) * td_table_len, __func__);
231
232   /* Create and fill kd-tree of selected's positions - in global or proj_vec space. */
233   KDTree_3d *td_tree = BLI_kdtree_3d_new(td_table_len);
234
235   int td_table_index = 0;
236   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
237     TransData *td = tc->data;
238     for (a = 0; a < tc->data_len; a++, td++) {
239       if (td->flag & TD_SELECTED) {
240         /* Initialize, it was mallocced. */
241         float vec[3];
242         td->rdist = 0.0f;
243
244         if (use_island) {
245           if (tc->use_local_mat) {
246             mul_v3_m4v3(vec, tc->mat, td->iloc);
247           }
248           else {
249             mul_v3_m3v3(vec, td->mtx, td->iloc);
250           }
251         }
252         else {
253           if (tc->use_local_mat) {
254             mul_v3_m4v3(vec, tc->mat, td->center);
255           }
256           else {
257             mul_v3_m3v3(vec, td->mtx, td->center);
258           }
259         }
260
261         if (proj_vec) {
262           float vec_p[3];
263           project_v3_v3v3(vec_p, vec, proj_vec);
264           sub_v3_v3(vec, vec_p);
265         }
266
267         BLI_kdtree_3d_insert(td_tree, td_table_index, vec);
268         td_table[td_table_index++] = td;
269       }
270       else {
271         /* By definition transform-data has selected items in beginning. */
272         break;
273       }
274     }
275   }
276   BLI_assert(td_table_index == td_table_len);
277
278   BLI_kdtree_3d_balance(td_tree);
279
280   /* For each non-selected vertex, find distance to the nearest selected vertex. */
281   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
282     TransData *td = tc->data;
283     for (a = 0; a < tc->data_len; a++, td++) {
284       if ((td->flag & TD_SELECTED) == 0) {
285         float vec[3];
286
287         if (use_island) {
288           if (tc->use_local_mat) {
289             mul_v3_m4v3(vec, tc->mat, td->iloc);
290           }
291           else {
292             mul_v3_m3v3(vec, td->mtx, td->iloc);
293           }
294         }
295         else {
296           if (tc->use_local_mat) {
297             mul_v3_m4v3(vec, tc->mat, td->center);
298           }
299           else {
300             mul_v3_m3v3(vec, td->mtx, td->center);
301           }
302         }
303
304         if (proj_vec) {
305           float vec_p[3];
306           project_v3_v3v3(vec_p, vec, proj_vec);
307           sub_v3_v3(vec, vec_p);
308         }
309
310         KDTreeNearest_3d nearest;
311         const int td_index = BLI_kdtree_3d_find_nearest(td_tree, vec, &nearest);
312
313         td->rdist = -1.0f;
314         if (td_index != -1) {
315           td->rdist = nearest.dist;
316           if (use_island) {
317             copy_v3_v3(td->center, td_table[td_index]->center);
318             copy_m3_m3(td->axismtx, td_table[td_index]->axismtx);
319           }
320         }
321
322         if (with_dist) {
323           td->dist = td->rdist;
324         }
325       }
326     }
327   }
328
329   BLI_kdtree_3d_free(td_tree);
330   MEM_freeN(td_table);
331 }
332
333 /* ********************* pose mode ************* */
334
335 static short apply_targetless_ik(Object *ob)
336 {
337   bPoseChannel *pchan, *parchan, *chanlist[256];
338   bKinematicConstraint *data;
339   int segcount, apply = 0;
340
341   /* now we got a difficult situation... we have to find the
342    * target-less IK pchans, and apply transformation to the all
343    * pchans that were in the chain */
344
345   for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
346     data = has_targetless_ik(pchan);
347     if (data && (data->flag & CONSTRAINT_IK_AUTO)) {
348
349       /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
350       segcount = 0;
351
352       /* exclude tip from chain? */
353       if (!(data->flag & CONSTRAINT_IK_TIP)) {
354         parchan = pchan->parent;
355       }
356       else {
357         parchan = pchan;
358       }
359
360       /* Find the chain's root & count the segments needed */
361       for (; parchan; parchan = parchan->parent) {
362         chanlist[segcount] = parchan;
363         segcount++;
364
365         if (segcount == data->rootbone || segcount > 255) {
366           break;  // 255 is weak
367         }
368       }
369       for (; segcount; segcount--) {
370         Bone *bone;
371         float rmat[4][4] /*, tmat[4][4], imat[4][4]*/;
372
373         /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK  */
374         /* we put in channel the entire result of rmat = (channel * constraint * IK) */
375         /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat  */
376         /* rmat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone ) */
377
378         parchan = chanlist[segcount - 1];
379         bone = parchan->bone;
380         bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
381
382         BKE_armature_mat_pose_to_bone(parchan, parchan->pose_mat, rmat);
383
384         /* apply and decompose, doesn't work for constraints or non-uniform scale well */
385         {
386           float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3];
387           copy_m3_m4(rmat3, rmat);
388
389           /* rotation */
390           /* [#22409] is partially caused by this, as slight numeric error introduced during
391            * the solving process leads to locked-axis values changing. However, we cannot modify
392            * the values here, or else there are huge discrepancies between IK-solver (interactive)
393            * and applied poses. */
394           BKE_pchan_mat3_to_rot(parchan, rmat3, false);
395
396           /* for size, remove rotation */
397           /* causes problems with some constraints (so apply only if needed) */
398           if (data->flag & CONSTRAINT_IK_STRETCH) {
399             BKE_pchan_rot_to_mat3(parchan, qrmat);
400             invert_m3_m3(imat3, qrmat);
401             mul_m3_m3m3(smat, rmat3, imat3);
402             mat3_to_size(parchan->size, smat);
403           }
404
405           /* causes problems with some constraints (e.g. childof), so disable this */
406           /* as it is IK shouldn't affect location directly */
407           /* copy_v3_v3(parchan->loc, rmat[3]); */
408         }
409       }
410
411       apply = 1;
412       data->flag &= ~CONSTRAINT_IK_AUTO;
413     }
414   }
415
416   return apply;
417 }
418
419 static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
420 {
421   Bone *bone = lb->first;
422
423   for (; bone; bone = bone->next) {
424     if ((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED)) {
425       bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
426     }
427     else if ((bone->flag & BONE_TRANSFORM) && (mode == TFM_ROTATION || mode == TFM_TRACKBALL) &&
428              (around == V3D_AROUND_LOCAL_ORIGINS)) {
429       bone->flag |= BONE_TRANSFORM_CHILD;
430     }
431     else {
432       bone->flag &= ~BONE_TRANSFORM;
433     }
434
435     bone_children_clear_transflag(mode, around, &bone->childbase);
436   }
437 }
438
439 /* sets transform flags in the bones
440  * returns total number of bones with BONE_TRANSFORM */
441 int count_set_pose_transflags(Object *ob,
442                               const int mode,
443                               const short around,
444                               bool has_translate_rotate[2])
445 {
446   bArmature *arm = ob->data;
447   bPoseChannel *pchan;
448   Bone *bone;
449   int total = 0;
450
451   for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
452     bone = pchan->bone;
453     if (PBONE_VISIBLE(arm, bone)) {
454       if ((bone->flag & BONE_SELECTED)) {
455         bone->flag |= BONE_TRANSFORM;
456       }
457       else {
458         bone->flag &= ~BONE_TRANSFORM;
459       }
460
461       bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
462       bone->flag &= ~BONE_TRANSFORM_CHILD;
463     }
464     else {
465       bone->flag &= ~BONE_TRANSFORM;
466     }
467   }
468
469   /* make sure no bone can be transformed when a parent is transformed */
470   /* since pchans are depsgraph sorted, the parents are in beginning of list */
471   if (!ELEM(mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
472     for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
473       bone = pchan->bone;
474       if (bone->flag & BONE_TRANSFORM) {
475         bone_children_clear_transflag(mode, around, &bone->childbase);
476       }
477     }
478   }
479   /* now count, and check if we have autoIK or have to switch from translate to rotate */
480   for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
481     bone = pchan->bone;
482     if (bone->flag & BONE_TRANSFORM) {
483       total++;
484
485       if (has_translate_rotate != NULL) {
486         if (has_targetless_ik(pchan) == NULL) {
487           if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
488             if (pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
489               has_translate_rotate[0] = true;
490             }
491           }
492           else {
493             if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC) {
494               has_translate_rotate[0] = true;
495             }
496           }
497           if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT) {
498             has_translate_rotate[1] = true;
499           }
500         }
501         else {
502           has_translate_rotate[0] = true;
503         }
504       }
505     }
506   }
507
508   return total;
509 }
510
511 /* -------- Auto-IK ---------- */
512
513 /* adjust pose-channel's auto-ik chainlen */
514 static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
515 {
516   bConstraint *con;
517   bool changed = false;
518
519   /* don't bother to search if no valid constraints */
520   if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) {
521     return changed;
522   }
523
524   /* check if pchan has ik-constraint */
525   for (con = pchan->constraints.first; con; con = con->next) {
526     if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
527       bKinematicConstraint *data = con->data;
528
529       /* only accept if a temporary one (for auto-ik) */
530       if (data->flag & CONSTRAINT_IK_TEMP) {
531         /* chainlen is new chainlen, but is limited by maximum chainlen */
532         const int old_rootbone = data->rootbone;
533         if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
534           data->rootbone = data->max_rootbone;
535         }
536         else {
537           data->rootbone = chainlen;
538         }
539         changed |= (data->rootbone != old_rootbone);
540       }
541     }
542   }
543
544   return changed;
545 }
546
547 /* change the chain-length of auto-ik */
548 void transform_autoik_update(TransInfo *t, short mode)
549 {
550   Main *bmain = CTX_data_main(t->context);
551
552   short *chainlen = &t->settings->autoik_chainlen;
553   bPoseChannel *pchan;
554
555   /* mode determines what change to apply to chainlen */
556   if (mode == 1) {
557     /* mode=1 is from WHEELMOUSEDOWN... increases len */
558     (*chainlen)++;
559   }
560   else if (mode == -1) {
561     /* mode==-1 is from WHEELMOUSEUP... decreases len */
562     if (*chainlen > 0) {
563       (*chainlen)--;
564     }
565     else {
566       /* IK length did not change, skip updates. */
567       return;
568     }
569   }
570
571   /* apply to all pose-channels */
572   bool changed = false;
573
574   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
575
576     /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
577     if (ELEM(NULL, tc->poseobj, tc->poseobj->pose)) {
578       continue;
579     }
580
581     for (pchan = tc->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
582       changed |= pchan_autoik_adjust(pchan, *chainlen);
583     }
584   }
585
586   if (changed) {
587     /* TODO(sergey): Consider doing partial update only. */
588     DEG_relations_tag_update(bmain);
589   }
590 }
591
592 /* frees temporal IKs */
593 static void pose_grab_with_ik_clear(Main *bmain, Object *ob)
594 {
595   bKinematicConstraint *data;
596   bPoseChannel *pchan;
597   bConstraint *con, *next;
598   bool relations_changed = false;
599
600   for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
601     /* clear all temporary lock flags */
602     pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP | BONE_IK_NO_YDOF_TEMP | BONE_IK_NO_ZDOF_TEMP);
603
604     pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
605
606     /* remove all temporary IK-constraints added */
607     for (con = pchan->constraints.first; con; con = next) {
608       next = con->next;
609       if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
610         data = con->data;
611         if (data->flag & CONSTRAINT_IK_TEMP) {
612           relations_changed = true;
613
614           /* iTaSC needs clear for removed constraints */
615           BIK_clear_data(ob->pose);
616
617           BLI_remlink(&pchan->constraints, con);
618           MEM_freeN(con->data);
619           MEM_freeN(con);
620           continue;
621         }
622         pchan->constflag |= PCHAN_HAS_IK;
623         if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0)) {
624           pchan->constflag |= PCHAN_HAS_TARGET;
625         }
626       }
627     }
628   }
629
630   if (relations_changed) {
631     /* TODO(sergey): Consider doing partial update only. */
632     DEG_relations_tag_update(bmain);
633   }
634 }
635
636 /* ********************* curve/surface ********* */
637
638 void calc_distanceCurveVerts(TransData *head, TransData *tail)
639 {
640   TransData *td, *td_near = NULL;
641   for (td = head; td <= tail; td++) {
642     if (td->flag & TD_SELECTED) {
643       td_near = td;
644       td->dist = 0.0f;
645     }
646     else if (td_near) {
647       float dist;
648       float vec[3];
649
650       sub_v3_v3v3(vec, td_near->center, td->center);
651       mul_m3_v3(head->mtx, vec);
652       dist = len_v3(vec);
653
654       if (dist < (td - 1)->dist) {
655         td->dist = (td - 1)->dist;
656       }
657       else {
658         td->dist = dist;
659       }
660     }
661     else {
662       td->dist = FLT_MAX;
663       td->flag |= TD_NOTCONNECTED;
664     }
665   }
666   td_near = NULL;
667   for (td = tail; td >= head; td--) {
668     if (td->flag & TD_SELECTED) {
669       td_near = td;
670       td->dist = 0.0f;
671     }
672     else if (td_near) {
673       float dist;
674       float vec[3];
675
676       sub_v3_v3v3(vec, td_near->center, td->center);
677       mul_m3_v3(head->mtx, vec);
678       dist = len_v3(vec);
679
680       if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td + 1)->dist < td->dist) {
681         td->flag &= ~TD_NOTCONNECTED;
682         if (dist < (td + 1)->dist) {
683           td->dist = (td + 1)->dist;
684         }
685         else {
686           td->dist = dist;
687         }
688       }
689     }
690   }
691 }
692
693 /* Utility function for getting the handle data from bezier's */
694 TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt)
695 {
696   TransDataCurveHandleFlags *hdata;
697   td->flag |= TD_BEZTRIPLE;
698   hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
699   hdata->ih1 = bezt->h1;
700   hdata->h1 = &bezt->h1;
701   hdata->ih2 = bezt->h2; /* in case the second is not selected */
702   hdata->h2 = &bezt->h2;
703   return hdata;
704 }
705
706 /* ********************* UV ****************** */
707
708 bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
709 {
710   bool clipx = true, clipy = true;
711   float min[2], max[2];
712
713   min[0] = min[1] = 0.0f;
714   max[0] = t->aspect[0];
715   max[1] = t->aspect[1];
716
717   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
718
719     TransData *td;
720     int a;
721
722     for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
723       minmax_v2v2_v2(min, max, td->loc);
724     }
725   }
726
727   if (resize) {
728     if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f) {
729       vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
730     }
731     else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0]) {
732       vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
733     }
734     else {
735       clipx = 0;
736     }
737
738     if (min[1] < 0.0f && t->center_global[1] > 0.0f && t->center_global[1] < t->aspect[1] * 0.5f) {
739       vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
740     }
741     else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1]) {
742       vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
743     }
744     else {
745       clipy = 0;
746     }
747   }
748   else {
749     if (min[0] < 0.0f) {
750       vec[0] -= min[0];
751     }
752     else if (max[0] > t->aspect[0]) {
753       vec[0] -= max[0] - t->aspect[0];
754     }
755     else {
756       clipx = 0;
757     }
758
759     if (min[1] < 0.0f) {
760       vec[1] -= min[1];
761     }
762     else if (max[1] > t->aspect[1]) {
763       vec[1] -= max[1] - t->aspect[1];
764     }
765     else {
766       clipy = 0;
767     }
768   }
769
770   return (clipx || clipy);
771 }
772
773 void clipUVData(TransInfo *t)
774 {
775   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
776     TransData *td = tc->data;
777     for (int a = 0; a < tc->data_len; a++, td++) {
778       if (td->flag & TD_NOACTION) {
779         break;
780       }
781
782       if ((td->flag & TD_SKIP) || (!td->loc)) {
783         continue;
784       }
785
786       td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), t->aspect[0]);
787       td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), t->aspect[1]);
788     }
789   }
790 }
791
792 /* ********************* ANIMATION EDITORS (GENERAL) ************************* */
793
794 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
795 bool FrameOnMouseSide(char side, float frame, float cframe)
796 {
797   /* both sides, so it doesn't matter */
798   if (side == 'B') {
799     return true;
800   }
801
802   /* only on the named side */
803   if (side == 'R') {
804     return (frame >= cframe);
805   }
806   else {
807     return (frame <= cframe);
808   }
809 }
810
811 /* ********************* ACTION EDITOR ****************** */
812
813 static int gpf_cmp_frame(void *thunk, const void *a, const void *b)
814 {
815   const bGPDframe *frame_a = a;
816   const bGPDframe *frame_b = b;
817
818   if (frame_a->framenum < frame_b->framenum) {
819     return -1;
820   }
821   if (frame_a->framenum > frame_b->framenum) {
822     return 1;
823   }
824   *((bool *)thunk) = true;
825   /* selected last */
826   if ((frame_a->flag & GP_FRAME_SELECT) && ((frame_b->flag & GP_FRAME_SELECT) == 0)) {
827     return 1;
828   }
829   return 0;
830 }
831
832 static int masklay_shape_cmp_frame(void *thunk, const void *a, const void *b)
833 {
834   const MaskLayerShape *frame_a = a;
835   const MaskLayerShape *frame_b = b;
836
837   if (frame_a->frame < frame_b->frame) {
838     return -1;
839   }
840   if (frame_a->frame > frame_b->frame) {
841     return 1;
842   }
843   *((bool *)thunk) = true;
844   /* selected last */
845   if ((frame_a->flag & MASK_SHAPE_SELECT) && ((frame_b->flag & MASK_SHAPE_SELECT) == 0)) {
846     return 1;
847   }
848   return 0;
849 }
850
851 /* Called by special_aftertrans_update to make sure selected gp-frames replace
852  * any other gp-frames which may reside on that frame (that are not selected).
853  * It also makes sure gp-frames are still stored in chronological order after
854  * transform.
855  */
856 static void posttrans_gpd_clean(bGPdata *gpd)
857 {
858   bGPDlayer *gpl;
859
860   for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
861     bGPDframe *gpf, *gpfn;
862     bool is_double = false;
863
864     BLI_listbase_sort_r(&gpl->frames, gpf_cmp_frame, &is_double);
865
866     if (is_double) {
867       for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
868         gpfn = gpf->next;
869         if (gpfn && gpf->framenum == gpfn->framenum) {
870           BKE_gpencil_layer_delframe(gpl, gpf);
871         }
872       }
873     }
874
875 #ifdef DEBUG
876     for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
877       BLI_assert(!gpf->next || gpf->framenum < gpf->next->framenum);
878     }
879 #endif
880   }
881   /* set cache flag to dirty */
882   DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
883 }
884
885 static void posttrans_mask_clean(Mask *mask)
886 {
887   MaskLayer *masklay;
888
889   for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
890     MaskLayerShape *masklay_shape, *masklay_shape_next;
891     bool is_double = false;
892
893     BLI_listbase_sort_r(&masklay->splines_shapes, masklay_shape_cmp_frame, &is_double);
894
895     if (is_double) {
896       for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
897            masklay_shape = masklay_shape_next) {
898         masklay_shape_next = masklay_shape->next;
899         if (masklay_shape_next && masklay_shape->frame == masklay_shape_next->frame) {
900           BKE_mask_layer_shape_unlink(masklay, masklay_shape);
901         }
902       }
903     }
904
905 #ifdef DEBUG
906     for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
907          masklay_shape = masklay_shape->next) {
908       BLI_assert(!masklay_shape->next || masklay_shape->frame < masklay_shape->next->frame);
909     }
910 #endif
911   }
912 }
913
914 /* Time + Average value */
915 typedef struct tRetainedKeyframe {
916   struct tRetainedKeyframe *next, *prev;
917   float frame; /* frame to cluster around */
918   float val;   /* average value */
919
920   size_t tot_count; /* number of keyframes that have been averaged */
921   size_t del_count; /* number of keyframes of this sort that have been deleted so far */
922 } tRetainedKeyframe;
923
924 /* Called during special_aftertrans_update to make sure selected keyframes replace
925  * any other keyframes which may reside on that frame (that is not selected).
926  */
927 static void posttrans_fcurve_clean(FCurve *fcu, const bool use_handle)
928 {
929   /* NOTE: We assume that all keys are sorted */
930   ListBase retained_keys = {NULL, NULL};
931   const bool can_average_points = ((fcu->flag & (FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES)) ==
932                                    0);
933
934   /* sanity checks */
935   if ((fcu->totvert == 0) || (fcu->bezt == NULL)) {
936     return;
937   }
938
939   /* 1) Identify selected keyframes, and average the values on those
940    * in case there are collisions due to multiple keys getting scaled
941    * to all end up on the same frame
942    */
943   for (int i = 0; i < fcu->totvert; i++) {
944     BezTriple *bezt = &fcu->bezt[i];
945
946     if (BEZT_ISSEL_ANY(bezt)) {
947       bool found = false;
948
949       /* If there's another selected frame here, merge it */
950       for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
951         if (IS_EQT(rk->frame, bezt->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
952           rk->val += bezt->vec[1][1];
953           rk->tot_count++;
954
955           found = true;
956           break;
957         }
958         else if (rk->frame < bezt->vec[1][0]) {
959           /* Terminate early if have passed the supposed insertion point? */
960           break;
961         }
962       }
963
964       /* If nothing found yet, create a new one */
965       if (found == false) {
966         tRetainedKeyframe *rk = MEM_callocN(sizeof(tRetainedKeyframe), "tRetainedKeyframe");
967
968         rk->frame = bezt->vec[1][0];
969         rk->val = bezt->vec[1][1];
970         rk->tot_count = 1;
971
972         BLI_addtail(&retained_keys, rk);
973       }
974     }
975   }
976
977   if (BLI_listbase_is_empty(&retained_keys)) {
978     /* This may happen if none of the points were selected... */
979     if (G.debug & G_DEBUG) {
980       printf("%s: nothing to do for FCurve %p (rna_path = '%s')\n", __func__, fcu, fcu->rna_path);
981     }
982     return;
983   }
984   else {
985     /* Compute the average values for each retained keyframe */
986     for (tRetainedKeyframe *rk = retained_keys.first; rk; rk = rk->next) {
987       rk->val = rk->val / (float)rk->tot_count;
988     }
989   }
990
991   /* 2) Delete all keyframes duplicating the "retained keys" found above
992    *   - Most of these will be unselected keyframes
993    *   - Some will be selected keyframes though. For those, we only keep the last one
994    *     (or else everything is gone), and replace its value with the averaged value.
995    */
996   for (int i = fcu->totvert - 1; i >= 0; i--) {
997     BezTriple *bezt = &fcu->bezt[i];
998
999     /* Is this keyframe a candidate for deletion? */
1000     /* TODO: Replace loop with an O(1) lookup instead */
1001     for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
1002       if (IS_EQT(bezt->vec[1][0], rk->frame, BEZT_BINARYSEARCH_THRESH)) {
1003         /* Selected keys are treated with greater care than unselected ones... */
1004         if (BEZT_ISSEL_ANY(bezt)) {
1005           /* - If this is the last selected key left (based on rk->del_count) ==> UPDATE IT
1006            *   (or else we wouldn't have any keyframe left here)
1007            * - Otherwise, there are still other selected keyframes on this frame
1008            *   to be merged down still ==> DELETE IT
1009            */
1010           if (rk->del_count == rk->tot_count - 1) {
1011             /* Update keyframe... */
1012             if (can_average_points) {
1013               /* TODO: update handles too? */
1014               bezt->vec[1][1] = rk->val;
1015             }
1016           }
1017           else {
1018             /* Delete Keyframe */
1019             delete_fcurve_key(fcu, i, 0);
1020           }
1021
1022           /* Update count of how many we've deleted
1023            * - It should only matter that we're doing this for all but the last one
1024            */
1025           rk->del_count++;
1026         }
1027         else {
1028           /* Always delete - Unselected keys don't matter */
1029           delete_fcurve_key(fcu, i, 0);
1030         }
1031
1032         /* Stop the RK search... we've found our match now */
1033         break;
1034       }
1035     }
1036   }
1037
1038   /* 3) Recalculate handles */
1039   testhandles_fcurve(fcu, use_handle);
1040
1041   /* cleanup */
1042   BLI_freelistN(&retained_keys);
1043 }
1044
1045 /* Called by special_aftertrans_update to make sure selected keyframes replace
1046  * any other keyframes which may reside on that frame (that is not selected).
1047  * remake_action_ipos should have already been called
1048  */
1049 static void posttrans_action_clean(bAnimContext *ac, bAction *act)
1050 {
1051   ListBase anim_data = {NULL, NULL};
1052   bAnimListElem *ale;
1053   int filter;
1054
1055   /* filter data */
1056   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
1057   ANIM_animdata_filter(ac, &anim_data, filter, act, ANIMCONT_ACTION);
1058
1059   /* loop through relevant data, removing keyframes as appropriate
1060    *      - all keyframes are converted in/out of global time
1061    */
1062   for (ale = anim_data.first; ale; ale = ale->next) {
1063     AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1064
1065     if (adt) {
1066       ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
1067       posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
1068       ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
1069     }
1070     else {
1071       posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
1072     }
1073   }
1074
1075   /* free temp data */
1076   ANIM_animdata_freelist(&anim_data);
1077 }
1078
1079 /* ********************* GRAPH EDITOR ************************* */
1080
1081 /* struct for use in re-sorting BezTriples during Graph Editor transform */
1082 typedef struct BeztMap {
1083   BezTriple *bezt;
1084   unsigned int oldIndex; /* index of bezt in fcu->bezt array before sorting */
1085   unsigned int newIndex; /* index of bezt in fcu->bezt array after sorting */
1086   short swapHs;          /* swap order of handles (-1=clear; 0=not checked, 1=swap) */
1087   char pipo, cipo;       /* interpolation of current and next segments */
1088 } BeztMap;
1089
1090 /* This function converts an FCurve's BezTriple array to a BeztMap array
1091  * NOTE: this allocates memory that will need to get freed later
1092  */
1093 static BeztMap *bezt_to_beztmaps(BezTriple *bezts, int totvert, const short UNUSED(use_handle))
1094 {
1095   BezTriple *bezt = bezts;
1096   BezTriple *prevbezt = NULL;
1097   BeztMap *bezm, *bezms;
1098   int i;
1099
1100   /* allocate memory for this array */
1101   if (totvert == 0 || bezts == NULL) {
1102     return NULL;
1103   }
1104   bezm = bezms = MEM_callocN(sizeof(BeztMap) * totvert, "BeztMaps");
1105
1106   /* assign beztriples to beztmaps */
1107   for (i = 0; i < totvert; i++, bezm++, prevbezt = bezt, bezt++) {
1108     bezm->bezt = bezt;
1109
1110     bezm->oldIndex = i;
1111     bezm->newIndex = i;
1112
1113     bezm->pipo = (prevbezt) ? prevbezt->ipo : bezt->ipo;
1114     bezm->cipo = bezt->ipo;
1115   }
1116
1117   return bezms;
1118 }
1119
1120 /* This function copies the code of sort_time_ipocurve, but acts on BeztMap structs instead */
1121 static void sort_time_beztmaps(BeztMap *bezms, int totvert, const short UNUSED(use_handle))
1122 {
1123   BeztMap *bezm;
1124   int i, ok = 1;
1125
1126   /* keep repeating the process until nothing is out of place anymore */
1127   while (ok) {
1128     ok = 0;
1129
1130     bezm = bezms;
1131     i = totvert;
1132     while (i--) {
1133       /* is current bezm out of order (i.e. occurs later than next)? */
1134       if (i > 0) {
1135         if (bezm->bezt->vec[1][0] > (bezm + 1)->bezt->vec[1][0]) {
1136           bezm->newIndex++;
1137           (bezm + 1)->newIndex--;
1138
1139           SWAP(BeztMap, *bezm, *(bezm + 1));
1140
1141           ok = 1;
1142         }
1143       }
1144
1145       /* do we need to check if the handles need to be swapped?
1146        * optimization: this only needs to be performed in the first loop
1147        */
1148       if (bezm->swapHs == 0) {
1149         if ((bezm->bezt->vec[0][0] > bezm->bezt->vec[1][0]) &&
1150             (bezm->bezt->vec[2][0] < bezm->bezt->vec[1][0])) {
1151           /* handles need to be swapped */
1152           bezm->swapHs = 1;
1153         }
1154         else {
1155           /* handles need to be cleared */
1156           bezm->swapHs = -1;
1157         }
1158       }
1159
1160       bezm++;
1161     }
1162   }
1163 }
1164
1165 /* This function firstly adjusts the pointers that the transdata has to each BezTriple */
1166 static void beztmap_to_data(
1167     TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert, const short UNUSED(use_handle))
1168 {
1169   BezTriple *bezts = fcu->bezt;
1170   BeztMap *bezm;
1171   TransData2D *td2d;
1172   TransData *td;
1173   int i, j;
1174   char *adjusted;
1175
1176   TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
1177
1178   /* dynamically allocate an array of chars to mark whether an TransData's
1179    * pointers have been fixed already, so that we don't override ones that are
1180    * already done
1181    */
1182   adjusted = MEM_callocN(tc->data_len, "beztmap_adjusted_map");
1183
1184   /* for each beztmap item, find if it is used anywhere */
1185   bezm = bezms;
1186   for (i = 0; i < totvert; i++, bezm++) {
1187     /* loop through transdata, testing if we have a hit
1188      * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped...
1189      */
1190     td2d = tc->data_2d;
1191     td = tc->data;
1192     for (j = 0; j < tc->data_len; j++, td2d++, td++) {
1193       /* skip item if already marked */
1194       if (adjusted[j] != 0) {
1195         continue;
1196       }
1197
1198       /* update all transdata pointers, no need to check for selections etc,
1199        * since only points that are really needed were created as transdata
1200        */
1201       if (td2d->loc2d == bezm->bezt->vec[0]) {
1202         if (bezm->swapHs == 1) {
1203           td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
1204         }
1205         else {
1206           td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
1207         }
1208         adjusted[j] = 1;
1209       }
1210       else if (td2d->loc2d == bezm->bezt->vec[2]) {
1211         if (bezm->swapHs == 1) {
1212           td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
1213         }
1214         else {
1215           td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
1216         }
1217         adjusted[j] = 1;
1218       }
1219       else if (td2d->loc2d == bezm->bezt->vec[1]) {
1220         td2d->loc2d = (bezts + bezm->newIndex)->vec[1];
1221
1222         /* if only control point is selected, the handle pointers need to be updated as well */
1223         if (td2d->h1) {
1224           td2d->h1 = (bezts + bezm->newIndex)->vec[0];
1225         }
1226         if (td2d->h2) {
1227           td2d->h2 = (bezts + bezm->newIndex)->vec[2];
1228         }
1229
1230         adjusted[j] = 1;
1231       }
1232
1233       /* the handle type pointer has to be updated too */
1234       if (adjusted[j] && td->flag & TD_BEZTRIPLE && td->hdata) {
1235         if (bezm->swapHs == 1) {
1236           td->hdata->h1 = &(bezts + bezm->newIndex)->h2;
1237           td->hdata->h2 = &(bezts + bezm->newIndex)->h1;
1238         }
1239         else {
1240           td->hdata->h1 = &(bezts + bezm->newIndex)->h1;
1241           td->hdata->h2 = &(bezts + bezm->newIndex)->h2;
1242         }
1243       }
1244     }
1245   }
1246
1247   /* free temp memory used for 'adjusted' array */
1248   MEM_freeN(adjusted);
1249 }
1250
1251 /* This function is called by recalcData during the Transform loop to recalculate
1252  * the handles of curves and sort the keyframes so that the curves draw correctly.
1253  * It is only called if some keyframes have moved out of order.
1254  *
1255  * anim_data is the list of channels (F-Curves) retrieved already containing the
1256  * channels to work on. It should not be freed here as it may still need to be used.
1257  */
1258 void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
1259 {
1260   SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
1261   bAnimListElem *ale;
1262   const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
1263
1264   /* sort and reassign verts */
1265   for (ale = anim_data->first; ale; ale = ale->next) {
1266     FCurve *fcu = (FCurve *)ale->key_data;
1267
1268     if (fcu->bezt) {
1269       BeztMap *bezm;
1270
1271       /* adjust transform-data pointers */
1272       /* note, none of these functions use 'use_handle', it could be removed */
1273       bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert, use_handle);
1274       sort_time_beztmaps(bezm, fcu->totvert, use_handle);
1275       beztmap_to_data(t, fcu, bezm, fcu->totvert, use_handle);
1276
1277       /* free mapping stuff */
1278       MEM_freeN(bezm);
1279
1280       /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */
1281       sort_time_fcurve(fcu);
1282
1283       /* make sure handles are all set correctly */
1284       testhandles_fcurve(fcu, use_handle);
1285     }
1286   }
1287 }
1288
1289 /* *********************** Transform data ******************* */
1290
1291 /* Little helper function for ObjectToTransData used to give certain
1292  * constraints (ChildOf, FollowPath, and others that may be added)
1293  * inverse corrections for transform, so that they aren't in CrazySpace.
1294  * These particular constraints benefit from this, but others don't, hence
1295  * this semi-hack ;-)    - Aligorith
1296  */
1297 bool constraints_list_needinv(TransInfo *t, ListBase *list)
1298 {
1299   bConstraint *con;
1300
1301   /* loop through constraints, checking if there's one of the mentioned
1302    * constraints needing special crazyspace corrections
1303    */
1304   if (list) {
1305     for (con = list->first; con; con = con->next) {
1306       /* only consider constraint if it is enabled, and has influence on result */
1307       if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) {
1308         /* (affirmative) returns for specific constraints here... */
1309         /* constraints that require this regardless  */
1310         if (ELEM(con->type,
1311                  CONSTRAINT_TYPE_FOLLOWPATH,
1312                  CONSTRAINT_TYPE_CLAMPTO,
1313                  CONSTRAINT_TYPE_ARMATURE,
1314                  CONSTRAINT_TYPE_OBJECTSOLVER,
1315                  CONSTRAINT_TYPE_FOLLOWTRACK)) {
1316           return true;
1317         }
1318
1319         /* constraints that require this only under special conditions */
1320         if (con->type == CONSTRAINT_TYPE_CHILDOF) {
1321           /* ChildOf constraint only works when using all location components, see T42256. */
1322           bChildOfConstraint *data = (bChildOfConstraint *)con->data;
1323
1324           if ((data->flag & CHILDOF_LOCX) && (data->flag & CHILDOF_LOCY) &&
1325               (data->flag & CHILDOF_LOCZ)) {
1326             return true;
1327           }
1328         }
1329         else if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
1330           /* CopyRot constraint only does this when rotating, and offset is on */
1331           bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
1332
1333           if (ELEM(data->mix_mode, ROTLIKE_MIX_OFFSET, ROTLIKE_MIX_BEFORE) &&
1334               ELEM(t->mode, TFM_ROTATION)) {
1335             return true;
1336           }
1337         }
1338         else if (con->type == CONSTRAINT_TYPE_TRANSLIKE) {
1339           /* Copy Transforms constraint only does this in the Before mode. */
1340           bTransLikeConstraint *data = (bTransLikeConstraint *)con->data;
1341
1342           if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE) &&
1343               ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) {
1344             return true;
1345           }
1346         }
1347         else if (con->type == CONSTRAINT_TYPE_TRANSFORM) {
1348           /* Transform constraint needs it for rotation at least (r.57309),
1349            * but doing so when translating may also mess things up [#36203]
1350            */
1351           bTransformConstraint *data = (bTransformConstraint *)con->data;
1352
1353           if (data->to == TRANS_ROTATION) {
1354             if (t->mode == TFM_ROTATION && data->mix_mode_rot == TRANS_MIXROT_BEFORE) {
1355               return true;
1356             }
1357           }
1358         }
1359       }
1360     }
1361   }
1362
1363   /* no appropriate candidates found */
1364   return false;
1365 }
1366
1367 /**
1368  * Auto-keyframing feature - for objects
1369  *
1370  * \param tmode: A transform mode.
1371  *
1372  * \note Context may not always be available,
1373  * so must check before using it as it's a luxury for a few cases.
1374  */
1375 void autokeyframe_object(bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, int tmode)
1376 {
1377   Main *bmain = CTX_data_main(C);
1378   ID *id = &ob->id;
1379   FCurve *fcu;
1380
1381   // TODO: this should probably be done per channel instead...
1382   if (autokeyframe_cfra_can_key(scene, id)) {
1383     ReportList *reports = CTX_wm_reports(C);
1384     ToolSettings *ts = scene->toolsettings;
1385     KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
1386     ListBase dsources = {NULL, NULL};
1387     float cfra = (float)CFRA;  // xxx this will do for now
1388     short flag = 0;
1389
1390     /* get flags used for inserting keyframes */
1391     flag = ANIM_get_keyframing_flags(scene, 1);
1392
1393     /* add datasource override for the object */
1394     ANIM_relative_keyingset_add_source(&dsources, id, NULL, NULL);
1395
1396     if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
1397       /* Only insert into active keyingset
1398        * NOTE: we assume here that the active Keying Set
1399        * does not need to have its iterator overridden.
1400        */
1401       ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
1402     }
1403     else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
1404       AnimData *adt = ob->adt;
1405
1406       /* only key on available channels */
1407       if (adt && adt->action) {
1408         ListBase nla_cache = {NULL, NULL};
1409         for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
1410           fcu->flag &= ~FCURVE_SELECTED;
1411           insert_keyframe(bmain,
1412                           reports,
1413                           id,
1414                           adt->action,
1415                           (fcu->grp ? fcu->grp->name : NULL),
1416                           fcu->rna_path,
1417                           fcu->array_index,
1418                           cfra,
1419                           ts->keyframe_type,
1420                           &nla_cache,
1421                           flag);
1422         }
1423
1424         BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
1425       }
1426     }
1427     else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) {
1428       bool do_loc = false, do_rot = false, do_scale = false;
1429
1430       /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
1431       if (tmode == TFM_TRANSLATION) {
1432         do_loc = true;
1433       }
1434       else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
1435         if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
1436           if (ob != OBACT(view_layer)) {
1437             do_loc = true;
1438           }
1439         }
1440         else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
1441           do_loc = true;
1442         }
1443
1444         if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
1445           do_rot = true;
1446         }
1447       }
1448       else if (tmode == TFM_RESIZE) {
1449         if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
1450           if (ob != OBACT(view_layer)) {
1451             do_loc = true;
1452           }
1453         }
1454         else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
1455           do_loc = true;
1456         }
1457
1458         if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
1459           do_scale = true;
1460         }
1461       }
1462
1463       /* insert keyframes for the affected sets of channels using the builtin KeyingSets found */
1464       if (do_loc) {
1465         KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
1466         ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
1467       }
1468       if (do_rot) {
1469         KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
1470         ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
1471       }
1472       if (do_scale) {
1473         KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
1474         ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
1475       }
1476     }
1477     /* insert keyframe in all (transform) channels */
1478     else {
1479       KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
1480       ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
1481     }
1482
1483     /* free temp info */
1484     BLI_freelistN(&dsources);
1485   }
1486 }
1487
1488 /* Return if we need to update motion paths, only if they already exist,
1489  * and we will insert a keyframe at the end of transform. */
1490 bool motionpath_need_update_object(Scene *scene, Object *ob)
1491 {
1492   /* XXX: there's potential here for problems with unkeyed rotations/scale,
1493    *      but for now (until proper data-locality for baking operations),
1494    *      this should be a better fix for T24451 and T37755
1495    */
1496
1497   if (autokeyframe_cfra_can_key(scene, &ob->id)) {
1498     return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
1499   }
1500
1501   return false;
1502 }
1503
1504 /**
1505  * Auto-keyframing feature - for poses/pose-channels
1506  *
1507  * \param tmode: A transform mode.
1508  *
1509  * targetless_ik: has targetless ik been done on any channels?
1510  *
1511  * \note Context may not always be available,
1512  * so must check before using it as it's a luxury for a few cases.
1513  */
1514 void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short targetless_ik)
1515 {
1516   Main *bmain = CTX_data_main(C);
1517   ID *id = &ob->id;
1518   AnimData *adt = ob->adt;
1519   bAction *act = (adt) ? adt->action : NULL;
1520   bPose *pose = ob->pose;
1521   bPoseChannel *pchan;
1522   FCurve *fcu;
1523
1524   // TODO: this should probably be done per channel instead...
1525   if (autokeyframe_cfra_can_key(scene, id)) {
1526     ReportList *reports = CTX_wm_reports(C);
1527     ToolSettings *ts = scene->toolsettings;
1528     KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
1529     ListBase nla_cache = {NULL, NULL};
1530     float cfra = (float)CFRA;
1531     short flag = 0;
1532
1533     /* flag is initialized from UserPref keyframing settings
1534      * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
1535      *   visual keyframes even if flag not set, as it's not that useful otherwise
1536      *   (for quick animation recording)
1537      */
1538     flag = ANIM_get_keyframing_flags(scene, 1);
1539
1540     if (targetless_ik) {
1541       flag |= INSERTKEY_MATRIX;
1542     }
1543
1544     for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
1545       if ((pchan->bone->flag & BONE_TRANSFORM) ||
1546           ((pose->flag & POSE_MIRROR_EDIT) && (pchan->bone->flag & BONE_TRANSFORM_MIRROR))) {
1547         ListBase dsources = {NULL, NULL};
1548
1549         /* clear any 'unkeyed' flag it may have */
1550         pchan->bone->flag &= ~BONE_UNKEYED;
1551
1552         /* add datasource override for the camera object */
1553         ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan);
1554
1555         /* only insert into active keyingset? */
1556         if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
1557           /* run the active Keying Set on the current datasource */
1558           ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
1559         }
1560         /* only insert into available channels? */
1561         else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
1562           if (act) {
1563             for (fcu = act->curves.first; fcu; fcu = fcu->next) {
1564               /* only insert keyframes for this F-Curve if it affects the current bone */
1565               if (strstr(fcu->rna_path, "bones")) {
1566                 char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
1567
1568                 /* only if bone name matches too...
1569                  * NOTE: this will do constraints too, but those are ok to do here too?
1570                  */
1571                 if (pchanName && STREQ(pchanName, pchan->name)) {
1572                   insert_keyframe(bmain,
1573                                   reports,
1574                                   id,
1575                                   act,
1576                                   ((fcu->grp) ? (fcu->grp->name) : (NULL)),
1577                                   fcu->rna_path,
1578                                   fcu->array_index,
1579                                   cfra,
1580                                   ts->keyframe_type,
1581                                   &nla_cache,
1582                                   flag);
1583                 }
1584
1585                 if (pchanName) {
1586                   MEM_freeN(pchanName);
1587                 }
1588               }
1589             }
1590           }
1591         }
1592         /* only insert keyframe if needed? */
1593         else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) {
1594           bool do_loc = false, do_rot = false, do_scale = false;
1595
1596           /* Filter the conditions when this happens
1597            * (assume that 'curarea->spacetype == SPACE_VIEW3D'). */
1598           if (tmode == TFM_TRANSLATION) {
1599             if (targetless_ik) {
1600               do_rot = true;
1601             }
1602             else {
1603               do_loc = true;
1604             }
1605           }
1606           else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
1607             if (ELEM(scene->toolsettings->transform_pivot_point,
1608                      V3D_AROUND_CURSOR,
1609                      V3D_AROUND_ACTIVE)) {
1610               do_loc = true;
1611             }
1612
1613             if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
1614               do_rot = true;
1615             }
1616           }
1617           else if (tmode == TFM_RESIZE) {
1618             if (ELEM(scene->toolsettings->transform_pivot_point,
1619                      V3D_AROUND_CURSOR,
1620                      V3D_AROUND_ACTIVE)) {
1621               do_loc = true;
1622             }
1623
1624             if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
1625               do_scale = true;
1626             }
1627           }
1628
1629           if (do_loc) {
1630             KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
1631             ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
1632           }
1633           if (do_rot) {
1634             KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
1635             ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
1636           }
1637           if (do_scale) {
1638             KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
1639             ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
1640           }
1641         }
1642         /* insert keyframe in all (transform) channels */
1643         else {
1644           KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
1645           ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
1646         }
1647
1648         /* free temp info */
1649         BLI_freelistN(&dsources);
1650       }
1651     }
1652
1653     BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
1654   }
1655   else {
1656     /* tag channels that should have unkeyed data */
1657     for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
1658       if (pchan->bone->flag & BONE_TRANSFORM) {
1659         /* tag this channel */
1660         pchan->bone->flag |= BONE_UNKEYED;
1661       }
1662     }
1663   }
1664 }
1665
1666 /* Return if we need to update motion paths, only if they already exist,
1667  * and we will insert a keyframe at the end of transform. */
1668 bool motionpath_need_update_pose(Scene *scene, Object *ob)
1669 {
1670   if (autokeyframe_cfra_can_key(scene, &ob->id)) {
1671     return (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
1672   }
1673
1674   return false;
1675 }
1676
1677 static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t)
1678 {
1679   SpaceClip *sc = t->sa->spacedata.first;
1680   MovieClip *clip = ED_space_clip_get_clip(sc);
1681   ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
1682   const int framenr = ED_space_clip_get_clip_frame_number(sc);
1683   /* Update coordinates of modified plane tracks. */
1684   for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; plane_track;
1685        plane_track = plane_track->next) {
1686     bool do_update = false;
1687     if (plane_track->flag & PLANE_TRACK_HIDDEN) {
1688       continue;
1689     }
1690     do_update |= PLANE_TRACK_VIEW_SELECTED(plane_track) != 0;
1691     if (do_update == false) {
1692       if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
1693         int i;
1694         for (i = 0; i < plane_track->point_tracksnr; i++) {
1695           MovieTrackingTrack *track = plane_track->point_tracks[i];
1696           if (TRACK_VIEW_SELECTED(sc, track)) {
1697             do_update = true;
1698             break;
1699           }
1700         }
1701       }
1702     }
1703     if (do_update) {
1704       BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
1705     }
1706   }
1707   if (t->scene->nodetree != NULL) {
1708     /* Tracks can be used for stabilization nodes,
1709      * flush update for such nodes.
1710      */
1711     nodeUpdateID(t->scene->nodetree, &clip->id);
1712     WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
1713   }
1714 }
1715
1716 static void special_aftertrans_update__mask(bContext *C, TransInfo *t)
1717 {
1718   Mask *mask = NULL;
1719
1720   if (t->spacetype == SPACE_CLIP) {
1721     SpaceClip *sc = t->sa->spacedata.first;
1722     mask = ED_space_clip_get_mask(sc);
1723   }
1724   else if (t->spacetype == SPACE_IMAGE) {
1725     SpaceImage *sima = t->sa->spacedata.first;
1726     mask = ED_space_image_get_mask(sima);
1727   }
1728   else {
1729     BLI_assert(0);
1730   }
1731
1732   if (t->scene->nodetree) {
1733     /* tracks can be used for stabilization nodes,
1734      * flush update for such nodes */
1735     // if (nodeUpdateID(t->scene->nodetree, &mask->id))
1736     {
1737       WM_event_add_notifier(C, NC_MASK | ND_DATA, &mask->id);
1738     }
1739   }
1740
1741   /* TODO - dont key all masks... */
1742   if (IS_AUTOKEY_ON(t->scene)) {
1743     Scene *scene = t->scene;
1744
1745     ED_mask_layer_shape_auto_key_select(mask, CFRA);
1746   }
1747 }
1748
1749 static void special_aftertrans_update__node(bContext *C, TransInfo *t)
1750 {
1751   Main *bmain = CTX_data_main(C);
1752   const bool canceled = (t->state == TRANS_CANCEL);
1753
1754   if (canceled && t->remove_on_cancel) {
1755     /* remove selected nodes on cancel */
1756     SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
1757     bNodeTree *ntree = snode->edittree;
1758     if (ntree) {
1759       bNode *node, *node_next;
1760       for (node = ntree->nodes.first; node; node = node_next) {
1761         node_next = node->next;
1762         if (node->flag & NODE_SELECT) {
1763           nodeRemoveNode(bmain, ntree, node, true);
1764         }
1765       }
1766     }
1767   }
1768 }
1769
1770 static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
1771 {
1772   /* so automerge supports mirror */
1773   if ((t->scene->toolsettings->automerge) && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) {
1774     FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1775
1776       BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
1777       BMesh *bm = em->bm;
1778       char hflag;
1779       bool has_face_sel = (bm->totfacesel != 0);
1780
1781       if (tc->mirror.use_mirror_any) {
1782         TransDataMirror *tdm;
1783         int i;
1784
1785         /* Rather then adjusting the selection (which the user would notice)
1786          * tag all mirrored verts, then auto-merge those. */
1787         BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
1788
1789         for (i = tc->mirror.data_len, tdm = tc->mirror.data; i--; tdm++) {
1790           BM_elem_flag_enable((BMVert *)tdm->extra, BM_ELEM_TAG);
1791         }
1792
1793         hflag = BM_ELEM_SELECT | BM_ELEM_TAG;
1794       }
1795       else {
1796         hflag = BM_ELEM_SELECT;
1797       }
1798
1799       if (t->scene->toolsettings->automerge & AUTO_MERGE) {
1800         if (t->scene->toolsettings->automerge & AUTO_MERGE_AND_SPLIT) {
1801           EDBM_automerge_and_split(
1802               tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit);
1803         }
1804         else {
1805           EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit);
1806         }
1807       }
1808
1809       /* Special case, this is needed or faces won't re-select.
1810        * Flush selected edges to faces. */
1811       if (has_face_sel && (em->selectmode == SCE_SELECT_FACE)) {
1812         EDBM_selectmode_flush_ex(em, SCE_SELECT_EDGE);
1813       }
1814     }
1815   }
1816 }
1817
1818 /* inserting keys, pointcache, redraw events... */
1819 /**
1820  * \note Sequencer freeing has its own function now because of a conflict
1821  * with transform's order of freeing (campbell).
1822  * Order changed, the sequencer stuff should go back in here
1823  */
1824 void special_aftertrans_update(bContext *C, TransInfo *t)
1825 {
1826   Main *bmain = CTX_data_main(t->context);
1827   BLI_assert(bmain == CTX_data_main(C));
1828
1829   Object *ob;
1830   //  short redrawipo=0, resetslowpar=1;
1831   const bool canceled = (t->state == TRANS_CANCEL);
1832   const bool duplicate = (t->mode == TFM_TIME_DUPLICATE);
1833
1834   /* early out when nothing happened */
1835   if (t->data_len_all == 0 || t->mode == TFM_DUMMY) {
1836     return;
1837   }
1838
1839   if (t->spacetype == SPACE_VIEW3D) {
1840     if (t->flag & T_EDIT) {
1841       /* Special Exception:
1842        * We don't normally access 't->custom.mode' here, but its needed in this case. */
1843
1844       if (canceled == 0) {
1845         /* we need to delete the temporary faces before automerging */
1846         if (t->mode == TFM_EDGE_SLIDE) {
1847           /* handle multires re-projection, done
1848            * on transform completion since it's
1849            * really slow -joeedh */
1850           projectEdgeSlideData(t, true);
1851         }
1852         else if (t->mode == TFM_VERT_SLIDE) {
1853           /* as above */
1854           projectVertSlideData(t, true);
1855         }
1856
1857         if (t->obedit_type == OB_MESH) {
1858           special_aftertrans_update__mesh(C, t);
1859         }
1860       }
1861       else {
1862         if (t->mode == TFM_EDGE_SLIDE) {
1863           EdgeSlideParams *slp = t->custom.mode.data;
1864           slp->perc = 0.0;
1865           projectEdgeSlideData(t, false);
1866         }
1867         else if (t->mode == TFM_VERT_SLIDE) {
1868           EdgeSlideParams *slp = t->custom.mode.data;
1869           slp->perc = 0.0;
1870           projectVertSlideData(t, false);
1871         }
1872       }
1873     }
1874   }
1875
1876   if (t->options & CTX_GPENCIL_STROKES) {
1877     /* pass */
1878   }
1879   else if (t->spacetype == SPACE_SEQ) {
1880     /* freeSeqData in transform_conversions.c does this
1881      * keep here so the else at the end wont run... */
1882
1883     SpaceSeq *sseq = (SpaceSeq *)t->sa->spacedata.first;
1884
1885     /* marker transform, not especially nice but we may want to move markers
1886      * at the same time as keyframes in the dope sheet. */
1887     if ((sseq->flag & SEQ_MARKER_TRANS) && (canceled == 0)) {
1888       /* cant use TFM_TIME_EXTEND
1889        * for some reason EXTEND is changed into TRANSLATE, so use frame_side instead */
1890
1891       if (t->mode == TFM_SEQ_SLIDE) {
1892         if (t->frame_side == 'B') {
1893           ED_markers_post_apply_transform(
1894               &t->scene->markers, t->scene, TFM_TIME_TRANSLATE, t->values[0], t->frame_side);
1895         }
1896       }
1897       else if (ELEM(t->frame_side, 'L', 'R')) {
1898         ED_markers_post_apply_transform(
1899             &t->scene->markers, t->scene, TFM_TIME_EXTEND, t->values[0], t->frame_side);
1900       }
1901     }
1902   }
1903   else if (t->spacetype == SPACE_IMAGE) {
1904     if (t->options & CTX_MASK) {
1905       special_aftertrans_update__mask(C, t);
1906     }
1907   }
1908   else if (t->spacetype == SPACE_NODE) {
1909     SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
1910     special_aftertrans_update__node(C, t);
1911     if (canceled == 0) {
1912       ED_node_post_apply_transform(C, snode->edittree);
1913
1914       ED_node_link_insert(bmain, t->sa);
1915     }
1916
1917     /* clear link line */
1918     ED_node_link_intersect_test(t->sa, 0);
1919   }
1920   else if (t->spacetype == SPACE_CLIP) {
1921     if (t->options & CTX_MOVIECLIP) {
1922       special_aftertrans_update__movieclip(C, t);
1923     }
1924     else if (t->options & CTX_MASK) {
1925       special_aftertrans_update__mask(C, t);
1926     }
1927   }
1928   else if (t->spacetype == SPACE_ACTION) {
1929     SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
1930     bAnimContext ac;
1931
1932     /* initialize relevant anim-context 'context' data */
1933     if (ANIM_animdata_get_context(C, &ac) == 0) {
1934       return;
1935     }
1936
1937     ob = ac.obact;
1938
1939     if (ELEM(ac.datatype, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY, ANIMCONT_TIMELINE)) {
1940       ListBase anim_data = {NULL, NULL};
1941       bAnimListElem *ale;
1942       short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
1943
1944       /* get channels to work on */
1945       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1946
1947       /* these should all be F-Curves */
1948       for (ale = anim_data.first; ale; ale = ale->next) {
1949         AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
1950         FCurve *fcu = (FCurve *)ale->key_data;
1951
1952         /* 3 cases here for curve cleanups:
1953          * 1) NOTRANSKEYCULL on    -> cleanup of duplicates shouldn't be done
1954          * 2) canceled == 0        -> user confirmed the transform,
1955          *                            so duplicates should be removed
1956          * 3) canceled + duplicate -> user canceled the transform,
1957          *                            but we made duplicates, so get rid of these
1958          */
1959         if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
1960           if (adt) {
1961             ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
1962             posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
1963             ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
1964           }
1965           else {
1966             posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
1967           }
1968         }
1969       }
1970
1971       /* free temp memory */
1972       ANIM_animdata_freelist(&anim_data);
1973     }
1974     else if (ac.datatype == ANIMCONT_ACTION) {  // TODO: just integrate into the above...
1975       /* Depending on the lock status, draw necessary views */
1976       // fixme... some of this stuff is not good
1977       if (ob) {
1978         if (ob->pose || BKE_key_from_object(ob)) {
1979           DEG_id_tag_update(&ob->id,
1980                             ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
1981         }
1982         else {
1983           DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
1984         }
1985       }
1986
1987       /* 3 cases here for curve cleanups:
1988        * 1) NOTRANSKEYCULL on    -> cleanup of duplicates shouldn't be done
1989        * 2) canceled == 0        -> user confirmed the transform,
1990        *                            so duplicates should be removed.
1991        * 3) canceled + duplicate -> user canceled the transform,
1992        *                            but we made duplicates, so get rid of these.
1993        */
1994       if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
1995         posttrans_action_clean(&ac, (bAction *)ac.data);
1996       }
1997     }
1998     else if (ac.datatype == ANIMCONT_GPENCIL) {
1999       /* remove duplicate frames and also make sure points are in order! */
2000       /* 3 cases here for curve cleanups:
2001        * 1) NOTRANSKEYCULL on    -> cleanup of duplicates shouldn't be done
2002        * 2) canceled == 0        -> user confirmed the transform,
2003        *                            so duplicates should be removed
2004        * 3) canceled + duplicate -> user canceled the transform,
2005        *                            but we made duplicates, so get rid of these
2006        */
2007       if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
2008         bGPdata *gpd;
2009
2010         // XXX: BAD! this get gpencil datablocks directly from main db...
2011         // but that's how this currently works :/
2012         for (gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
2013           if (ID_REAL_USERS(gpd)) {
2014             posttrans_gpd_clean(gpd);
2015           }
2016         }
2017       }
2018     }
2019     else if (ac.datatype == ANIMCONT_MASK) {
2020       /* remove duplicate frames and also make sure points are in order! */
2021       /* 3 cases here for curve cleanups:
2022        * 1) NOTRANSKEYCULL on:
2023        *    Cleanup of duplicates shouldn't be done.
2024        * 2) canceled == 0:
2025        *    User confirmed the transform, so duplicates should be removed.
2026        * 3) Canceled + duplicate:
2027        *    User canceled the transform, but we made duplicates, so get rid of these.
2028        */
2029       if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
2030         Mask *mask;
2031
2032         // XXX: BAD! this get gpencil datablocks directly from main db...
2033         // but that's how this currently works :/
2034         for (mask = bmain->masks.first; mask; mask = mask->id.next) {
2035           if (ID_REAL_USERS(mask)) {
2036             posttrans_mask_clean(mask);
2037           }
2038         }
2039       }
2040     }
2041
2042     /* marker transform, not especially nice but we may want to move markers
2043      * at the same time as keyframes in the dope sheet.
2044      */
2045     if ((saction->flag & SACTION_MARKERS_MOVE) && (canceled == 0)) {
2046       if (t->mode == TFM_TIME_TRANSLATE) {
2047 #if 0
2048         if (ELEM(t->frame_side, 'L', 'R')) { /* TFM_TIME_EXTEND */
2049           /* same as below */
2050           ED_markers_post_apply_transform(
2051               ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
2052         }
2053         else /* TFM_TIME_TRANSLATE */
2054 #endif
2055         {
2056           ED_markers_post_apply_transform(
2057               ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
2058         }
2059       }
2060       else if (t->mode == TFM_TIME_SCALE) {
2061         ED_markers_post_apply_transform(
2062             ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
2063       }
2064     }
2065
2066     /* make sure all F-Curves are set correctly */
2067     if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
2068       ANIM_editkeyframes_refresh(&ac);
2069     }
2070
2071     /* clear flag that was set for time-slide drawing */
2072     saction->flag &= ~SACTION_MOVING;
2073   }
2074   else if (t->spacetype == SPACE_GRAPH) {
2075     SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
2076     bAnimContext ac;
2077     const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
2078
2079     /* initialize relevant anim-context 'context' data */
2080     if (ANIM_animdata_get_context(C, &ac) == 0) {
2081       return;
2082     }
2083
2084     if (ac.datatype) {
2085       ListBase anim_data = {NULL, NULL};
2086       bAnimListElem *ale;
2087       short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
2088
2089       /* get channels to work on */
2090       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2091
2092       for (ale = anim_data.first; ale; ale = ale->next) {
2093         AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
2094         FCurve *fcu = (FCurve *)ale->key_data;
2095
2096         /* 3 cases here for curve cleanups:
2097          * 1) NOTRANSKEYCULL on    -> cleanup of duplicates shouldn't be done
2098          * 2) canceled == 0        -> user confirmed the transform,
2099          *                            so duplicates should be removed
2100          * 3) canceled + duplicate -> user canceled the transform,
2101          *                            but we made duplicates, so get rid of these
2102          */
2103         if ((sipo->flag & SIPO_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
2104           if (adt) {
2105             ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
2106             posttrans_fcurve_clean(fcu, use_handle);
2107             ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
2108           }
2109           else {
2110             posttrans_fcurve_clean(fcu, use_handle);
2111           }
2112         }
2113       }
2114
2115       /* free temp memory */
2116       ANIM_animdata_freelist(&anim_data);
2117     }
2118
2119     /* Make sure all F-Curves are set correctly, but not if transform was
2120      * canceled, since then curves were already restored to initial state.
2121      * Note: if the refresh is really needed after cancel then some way
2122      *       has to be added to not update handle types (see bug 22289).
2123      */
2124     if (!canceled) {
2125       ANIM_editkeyframes_refresh(&ac);
2126     }
2127   }
2128   else if (t->spacetype == SPACE_NLA) {
2129     bAnimContext ac;
2130
2131     /* initialize relevant anim-context 'context' data */
2132     if (ANIM_animdata_get_context(C, &ac) == 0) {
2133       return;
2134     }
2135
2136     if (ac.datatype) {
2137       ListBase anim_data = {NULL, NULL};
2138       bAnimListElem *ale;
2139       short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
2140
2141       /* get channels to work on */
2142       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2143
2144       for (ale = anim_data.first; ale; ale = ale->next) {
2145         NlaTrack *nlt = (NlaTrack *)ale->data;
2146
2147         /* make sure strips are in order again */
2148         BKE_nlatrack_sort_strips(nlt);
2149
2150         /* remove the temp metas */
2151         BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
2152       }
2153
2154       /* free temp memory */
2155       ANIM_animdata_freelist(&anim_data);
2156
2157       /* perform after-transfrom validation */
2158       ED_nla_postop_refresh(&ac);
2159     }
2160   }
2161   else if (t->flag & T_EDIT) {
2162     if (t->obedit_type == OB_MESH) {
2163       FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2164         BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
2165         /* table needs to be created for each edit command, since vertices can move etc */
2166         ED_mesh_mirror_spatial_table(tc->obedit, em, NULL, NULL, 'e');
2167         /* TODO(campbell): xform: We need support for many mirror objects at once! */
2168         break;
2169       }
2170     }
2171   }
2172   else if (t->flag & T_POSE && (t->mode == TFM_BONESIZE)) {
2173     /* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be
2174      * in pose mode (to use bone orientation matrix),
2175      * in that case we don't do operations like auto-keyframing. */
2176     FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2177       ob = tc->poseobj;
2178       DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
2179     }
2180   }
2181   else if (t->flag & T_POSE) {
2182     GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
2183
2184     FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2185
2186       bPoseChannel *pchan;
2187       short targetless_ik = 0;
2188
2189       ob = tc->poseobj;
2190
2191       if ((t->flag & T_AUTOIK) && (t->options & CTX_AUTOCONFIRM)) {
2192         /* when running transform non-interactively (operator exec),
2193          * we need to update the pose otherwise no updates get called during
2194          * transform and the auto-ik is not applied. see [#26164] */
2195         struct Object *pose_ob = tc->poseobj;
2196         BKE_pose_where_is(t->depsgraph, t->scene, pose_ob);
2197       }
2198
2199       /* set BONE_TRANSFORM flags for autokey, gizmo draw might have changed them */
2200       if (!canceled && (t->mode != TFM_DUMMY)) {
2201         count_set_pose_transflags(ob, t->mode, t->around, NULL);
2202       }
2203
2204       /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
2205       if (!canceled && t->mode == TFM_TRANSLATION) {
2206         targetless_ik = apply_targetless_ik(ob);
2207       }
2208       else {
2209         /* not forget to clear the auto flag */
2210         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
2211           bKinematicConstraint *data = has_targetless_ik(pchan);
2212           if (data) {
2213             data->flag &= ~CONSTRAINT_IK_AUTO;
2214           }
2215         }
2216       }
2217
2218       if (t->mode == TFM_TRANSLATION) {
2219         pose_grab_with_ik_clear(bmain, ob);
2220       }
2221
2222       /* automatic inserting of keys and unkeyed tagging -
2223        * only if transform wasn't canceled (or TFM_DUMMY) */
2224       if (!canceled && (t->mode != TFM_DUMMY)) {
2225         autokeyframe_pose(C, t->scene, ob, t->mode, targetless_ik);
2226         DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
2227       }
2228       else {
2229         DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
2230       }
2231
2232       if (t->mode != TFM_DUMMY && motionpath_need_update_pose(t->scene, ob)) {
2233         BLI_gset_insert(motionpath_updates, ob);
2234       }
2235     }
2236
2237     /* Update motion paths once for all transformed bones in an object. */
2238     GSetIterator gs_iter;
2239     GSET_ITER (gs_iter, motionpath_updates) {
2240       const ePosePathCalcRange range = canceled ? POSE_PATH_CALC_RANGE_CURRENT_FRAME :
2241                                                   POSE_PATH_CALC_RANGE_CHANGED;
2242       ob = BLI_gsetIterator_getKey(&gs_iter);
2243       ED_pose_recalculate_paths(C, t->scene, ob, range);
2244     }
2245     BLI_gset_free(motionpath_updates, NULL);
2246   }
2247   else if (t->options & CTX_PAINT_CURVE) {
2248     /* pass */
2249   }
2250   else if (t->options & CTX_SCULPT) {
2251     /* pass */
2252   }
2253   else if ((t->view_layer->basact) && (ob = t->view_layer->basact->object) &&
2254            (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->depsgraph, t->scene, ob)) {
2255     /* do nothing */
2256   }
2257   else if (t->flag & T_CURSOR) {
2258     /* do nothing */
2259   }
2260   else { /* Objects */
2261     BLI_assert(t->flag & (T_OBJECT | T_TEXTURE));
2262
2263     TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
2264     bool motionpath_update = false;
2265
2266     for (int i = 0; i < tc->data_len; i++) {
2267       TransData *td = tc->data + i;
2268       ListBase pidlist;
2269       PTCacheID *pid;
2270       ob = td->ob;
2271
2272       if (td->flag & TD_NOACTION) {
2273         break;
2274       }
2275
2276       if (td->flag & TD_SKIP) {
2277         continue;
2278       }
2279
2280       /* flag object caches as outdated */
2281       BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR);
2282       for (pid = pidlist.first; pid; pid = pid->next) {
2283         if (pid->type != PTCACHE_TYPE_PARTICLES) {
2284           /* particles don't need reset on geometry change */
2285           pid->cache->flag |= PTCACHE_OUTDATED;
2286         }
2287       }
2288       BLI_freelistN(&pidlist);
2289
2290       /* pointcache refresh */
2291       if (BKE_ptcache_object_reset(t->scene, ob, PTCACHE_RESET_OUTDATED)) {
2292         DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
2293       }
2294
2295       /* Needed for proper updating of "quick cached" dynamics. */
2296       /* Creates troubles for moving animated objects without */
2297       /* autokey though, probably needed is an anim sys override? */
2298       /* Please remove if some other solution is found. -jahka */
2299       DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
2300
2301       /* Set autokey if necessary */
2302       if (!canceled) {
2303         autokeyframe_object(C, t->scene, t->view_layer, ob, t->mode);
2304       }
2305
2306       motionpath_update |= motionpath_need_update_object(t->scene, ob);
2307
2308       /* restore rigid body transform */
2309       if (ob->rigidbody_object && canceled) {
2310         float ctime = BKE_scene_frame_get(t->scene);
2311         if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime)) {
2312           BKE_rigidbody_aftertrans_update(ob,
2313                                           td->ext->oloc,
2314                                           td->ext->orot,
2315                                           td->ext->oquat,
2316                                           td->ext->orotAxis,
2317                                           td->ext->orotAngle);
2318         }
2319       }
2320     }
2321
2322     if (motionpath_update) {
2323       /* Update motion paths once for all transformed objects. */
2324       const eObjectPathCalcRange range = canceled ? OBJECT_PATH_CALC_RANGE_CURRENT_FRAME :
2325                                                     OBJECT_PATH_CALC_RANGE_CHANGED;
2326       ED_objects_recalculate_paths(C, t->scene, range);
2327     }
2328   }
2329
2330   clear_trans_object_base_flags(t);
2331 }
2332
2333 int special_transform_moving(TransInfo *t)
2334 {
2335   if (t->spacetype == SPACE_SEQ) {
2336     return G_TRANSFORM_SEQ;
2337   }
2338   else if (t->spacetype == SPACE_GRAPH) {
2339     return G_TRANSFORM_FCURVES;
2340   }
2341   else if ((t->flag & T_EDIT) || (t->flag & T_POSE)) {
2342     return G_TRANSFORM_EDIT;
2343   }
2344   else if (t->flag & (T_OBJECT | T_TEXTURE)) {
2345     return G_TRANSFORM_OBJ;
2346   }
2347
2348   return 0;
2349 }
2350
2351 /** \} */
2352
2353 static int countAndCleanTransDataContainer(TransInfo *t)
2354 {
2355   BLI_assert(ELEM(t->data_len_all, 0, -1));
2356   t->data_len_all = 0;
2357   uint data_container_len_orig = t->data_container_len;
2358   for (TransDataContainer *th_end = t->data_container - 1,
2359                           *tc = t->data_container + (t->data_container_len - 1);
2360        tc != th_end;
2361        tc--) {
2362     if (tc->data_len == 0) {
2363       uint index = tc - t->data_container;
2364       if (index + 1 != t->data_container_len) {
2365         SWAP(TransDataContainer,
2366              t->data_container[index],
2367              t->data_container[t->data_container_len - 1]);
2368       }
2369       t->data_container_len -= 1;
2370     }
2371     else {
2372       t->data_len_all += tc->data_len;
2373     }
2374   }
2375   if (data_container_len_orig != t->data_container_len) {
2376     t->data_container = MEM_reallocN(t->data_container,
2377                                      sizeof(*t->data_container) * t->data_container_len);
2378   }
2379   return t->data_len_all;
2380 }
2381
2382 void createTransData(bContext *C, TransInfo *t)
2383 {
2384   Scene *scene = t->scene;
2385   ViewLayer *view_layer = t->view_layer;
2386   Object *ob = OBACT(view_layer);
2387
2388   bool has_transform_context = true;
2389   t->data_len_all = -1;
2390
2391   /* if tests must match recalcData for correct updates */
2392   if (t->options & CTX_CURSOR) {
2393     t->flag |= T_CURSOR;
2394     t->obedit_type = -1;
2395
2396     if (t->spacetype == SPACE_IMAGE) {
2397       createTransCursor_image(t);
2398     }
2399     else {
2400       createTransCursor_view3d(t);
2401     }
2402     countAndCleanTransDataContainer(t);
2403   }
2404   else if ((t->options & CTX_SCULPT) && !(t->options & CTX_PAINT_CURVE)) {
2405     createTransSculpt(t);
2406     countAndCleanTransDataContainer(t);
2407   }
2408   else if (t->options & CTX_TEXTURE) {
2409     t->flag |= T_TEXTURE;
2410     t->obedit_type = -1;
2411
2412     createTransTexspace(t);
2413     countAndCleanTransDataContainer(t);
2414   }
2415   else if (t->options & CTX_EDGE) {
2416     /* Multi object editing. */
2417     initTransDataContainers_FromObjectData(t, ob, NULL, 0);
2418     FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2419       tc->data_ext = NULL;
2420     }
2421     t->flag |= T_EDIT;
2422
2423     createTransEdge(t);
2424     countAndCleanTransDataContainer(t);
2425
2426     if (t->data_len_all && t->flag & T_PROP_EDIT) {
2427       sort_trans_data_selected_first(t);
2428       set_prop_dist(t, 1);
2429       sort_trans_data_dist(t);
2430     }
2431   }
2432   else if (t->options & CTX_GPENCIL_STROKES) {
2433     t->options |= CTX_GPENCIL_STROKES;
2434     t->flag |= T_POINTS | T_EDIT;
2435
2436     initTransDataContainers_FromObjectData(t, ob, NULL, 0);
2437     createTransGPencil(C, t);
2438     countAndCleanTransDataContainer(t);
2439
2440     if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
2441       sort_trans_data_selected_first(t);
2442       set_prop_dist(t, 1);
2443       sort_trans_data_dist(t);
2444     }
2445   }
2446   else if (t->spacetype == SPACE_IMAGE) {
2447     t->flag |= T_POINTS | T_2D_EDIT;
2448     if (t->options & CTX_MASK) {
2449
2450       /* copied from below */
2451       createTransMaskingData(C, t);
2452       countAndCleanTransDataContainer(t);
2453
2454       if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
2455         sort_trans_data_selected_first(t);
2456         set_prop_dist(t, true);
2457         sort_trans_data_dist(t);
2458       }
2459     }
2460     else if (t->options & CTX_PAINT_CURVE) {
2461       if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
2462         createTransPaintCurveVerts(C, t);
2463         countAndCleanTransDataContainer(t);
2464       }
2465       else {
2466         has_transform_context = false;
2467       }
2468     }
2469     else if (t->obedit_type == OB_MESH) {
2470
2471       initTransDataContainers_FromObjectData(t, ob, NULL, 0);
2472       createTransUVs(C, t);
2473       countAndCleanTransDataContainer(t);
2474
2475       t->flag |= T_EDIT;
2476
2477       if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
2478         sort_trans_data_selected_first(t);
2479         set_prop_dist(t, 1);
2480         sort_trans_data_dist(t);
2481       }
2482     }
2483     else {
2484       has_transform_context = false;
2485     }
2486   }
2487   else if (t->spacetype == SPACE_ACTION) {
2488     t->flag |= T_POINTS | T_2D_EDIT;
2489     t->obedit_type = -1;
2490
2491     createTransActionData(C, t);
2492     countAndCleanTransDataContainer(t);
2493
2494     if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
2495       sort_trans_data_selected_first(t);
2496       /* don't do that, distance has been set in createTransActionData already */
2497       // set_prop_dist(t, false);
2498       sort_trans_data_dist(t);
2499     }
2500   }
2501   else if (t->spacetype == SPACE_NLA) {
2502     t->flag |= T_POINTS | T_2D_EDIT;
2503     t->obedit_type = -1;
2504
2505     createTransNlaData(C, t);
2506     countAndCleanTransDataContainer(t);
2507   }
2508   else if (t->spacetype == SPACE_SEQ) {
2509     t->flag |= T_POINTS | T_2D_EDIT;
2510     t->obedit_type = -1;
2511
2512     t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point trasnform */
2513     createTransSeqData(C, t);
2514     countAndCleanTransDataContainer(t);
2515   }
2516   else if (t->spacetype == SPACE_GRAPH) {
2517     t->flag |= T_POINTS | T_2D_EDIT;
2518     t->obedit_type = -1;
2519
2520     createTransGraphEditData(C, t);
2521     countAndCleanTransDataContainer(t);
2522
2523     if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
2524       /* makes selected become first in array */
2525       sort_trans_data_selected_first(t);
2526
2527       /* don't do that, distance has been set in createTransGraphEditData already */
2528       set_prop_dist(t, false);
2529
2530       sort_trans_data_dist(t);
2531     }
2532   }
2533   else if (t->spacetype == SPACE_NODE) {
2534     t->flag |= T_POINTS | T_2D_EDIT;
2535     t->obedit_type = -1;
2536
2537     createTransNodeData(C, t);
2538     countAndCleanTransDataContainer(t);
2539
2540     if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
2541       sort_trans_data_selected_first(t);
2542       set_prop_dist(t, 1);
2543       sort_trans_data_dist(t);
2544     }
2545   }
2546   else if (t->spacetype == SPACE_CLIP) {
2547     t->flag |= T_POINTS | T_2D_EDIT;
2548     t->obedit_type = -1;
2549
2550     if (t->options & CTX_MOVIECLIP) {
2551       createTransTrackingData(C, t);
2552       countAndCleanTransDataContainer(t);
2553     }
2554     else if (t->options & CTX_MASK) {
2555       /* copied from above */
2556       createTransMaskingData(C, t);
2557       countAndCleanTransDataContainer(t);
2558
2559       if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
2560         sort_trans_data_selected_first(t);
2561         set_prop_dist(t, true);
2562         sort_trans_data_dist(t);
2563       }
2564     }
2565     else {
2566       has_transform_context = false;
2567     }
2568   }
2569   else if (t->obedit_type != -1) {
2570     /* Multi object editing. */
2571     initTransDataContainers_FromObjectData(t, ob, NULL, 0);
2572
2573     FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2574       tc->data_ext = NULL;
2575     }
2576     if (t->obedit_type == OB_MESH) {
2577       createTransEditVerts(t);
2578     }
2579     else if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) {
2580       createTransCurveVerts(t);
2581     }
2582     else if (t->obedit_type == OB_LATTICE) {
2583       createTransLatticeVerts(t);
2584     }
2585     else if (t->obedit_type == OB_MBALL) {
2586       createTransMBallVerts(t);
2587     }
2588     else if (t->obedit_type == OB_ARMATURE) {
2589       t->flag &= ~T_PROP_EDIT;
2590       createTransArmatureVerts(t);
2591     }
2592     else {
2593       printf("edit type not implemented!\n");
2594     }
2595
2596     countAndCleanTransDataContainer(t);
2597
2598     t->flag |= T_EDIT | T_POINTS;
2599
2600     if (t->data_len_all) {
2601       if (t->flag & T_PROP_EDIT) {
2602         if (ELEM(t->obedit_type, OB_CURVE, OB_MESH)) {
2603           sort_trans_data_selected_first(t);
2604           if ((t->obedit_type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) {
2605             /* already calculated by editmesh_set_connectivity_distance */
2606           }
2607           else {
2608             set_prop_dist(t, 0);
2609           }
2610           sort_trans_data_dist(t);
2611         }
2612         else {
2613           sort_trans_data_selected_first(t);
2614           set_prop_dist(t, 1);
2615           sort_trans_data_dist(t);
2616         }
2617       }
2618       else {
2619         if (ELEM(t->obedit_type, OB_CURVE)) {
2620           /* Needed because bezier handles can be partially selected
2621            * and are still added into transform data. */
2622           sort_trans_data_selected_first(t);
2623         }
2624       }
2625     }
2626
2627     /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
2628     if (t->mode == TFM_BONESIZE) {
2629       t->flag &= ~(T_EDIT | T_POINTS);
2630       t->flag |= T_POSE;
2631       t->obedit_type = -1;
2632
2633       FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2634         tc->poseobj = tc->obedit;
2635         tc->obedit = NULL;
2636       }
2637     }
2638   }
2639   else if (ob && (ob->mode & OB_MODE_POSE)) {
2640     /* XXX this is currently limited to active armature only... */
2641
2642     /* XXX active-layer checking isn't done
2643      * as that should probably be checked through context instead. */
2644
2645     /* Multi object editing. */
2646     initTransDataContainers_FromObjectData(t, ob, NULL, 0);
2647     createTransPose(t);
2648     countAndCleanTransDataContainer(t);
2649   }
2650   else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) {
2651     /* important that ob_armature can be set even when its not selected [#23412]
2652      * lines below just check is also visible */
2653     has_transform_context = false;
2654     Object *ob_armature = modifiers_isDeformedByArmature(ob);
2655     if (ob_armature && ob_armature->mode & OB_MODE_POSE) {
2656       Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature);
2657       if (base_arm) {
2658         View3D *v3d = t->view;
2659         if (BASE_VISIBLE(v3d, base_arm)) {
2660           Object *objects[1];
2661           objects[0] = ob_armature;
2662           uint objects_len = 1;
2663           initTransDataContainers_FromObjectData(t, ob_armature, objects, objects_len);
2664           createTransPose(t);
2665           countAndCleanTransDataContainer(t);
2666           has_transform_context = true;
2667         }
2668       }
2669     }
2670   }
2671   else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) &&
2672            PE_start_edit(PE_get_current(t->depsgraph, scene, ob))) {
2673     createTransParticleVerts(C, t);
2674     countAndCleanTransDataContainer(t);
2675     t->flag |= T_POINTS;
2676
2677     if (t->data_len_all && t->flag & T_PROP_EDIT) {
2678       sort_trans_data_selected_first(t);
2679       set_prop_dist(t, 1);
2680       sort_trans_data_dist(t);
2681     }
2682   }
2683   else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
2684     if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
2685       t->flag |= T_POINTS | T_2D_EDIT;
2686       createTransPaintCurveVerts(C, t);
2687       countAndCleanTransDataContainer(t);
2688     }
2689     else {
2690       has_transform_context = false;
2691     }
2692   }
2693   else if ((ob) &&
2694            (ELEM(
2695                ob->mode, OB_MODE_PAINT_GPENCIL, OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL))) {
2696     /* In grease pencil all transformations must be canceled if not Object or Edit. */
2697     has_transform_context = false;
2698   }
2699   else {
2700     /* Needed for correct Object.obmat after duplication, see: T62135. */
2701     BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context));
2702
2703     if ((scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) {
2704       t->options |= CTX_OBMODE_XFORM_OBDATA;
2705     }
2706     if ((scene->toolsettings->transform_flag & SCE_XFORM_SKIP_CHILDREN) != 0) {
2707       t->options |= CTX_OBMODE_XFORM_SKIP_CHILDREN;
2708     }
2709
2710     createTransObject(C, t);
2711     countAndCleanTransDataContainer(t);
2712     t->flag |= T_OBJECT;
2713
2714     if (t->data_len_all && t->flag & T_PROP_EDIT) {
2715       // selected objects are already first, no need to presort
2716       set_prop_dist(t, 1);
2717       sort_trans_data_dist(t);
2718     }
2719
2720     /* Check if we're transforming the camera from the camera */
2721     if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
2722       View3D *v3d = t->view;
2723       RegionView3D *rv3d = t->ar->regiondata;
2724       if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) {
2725         /* we could have a flag to easily check an object is being transformed */
2726         if (v3d->camera->id.tag & LIB_TAG_DOIT) {
2727           t->flag |= T_CAMERA;
2728         }
2729       }
2730     }
2731   }
2732
2733   /* Check that 'countAndCleanTransDataContainer' ran. */
2734   if (has_transform_context) {
2735     BLI_assert(t->data_len_all != -1);
2736   }
2737   else {
2738     BLI_assert(t->data_len_all == -1);
2739     t->data_len_all = 0;
2740   }
2741
2742   BLI_assert((!(t->flag & T_EDIT)) == (!(t->obedit_type != -1)));
2743 }