Merge branch 'blender2.7'
[blender.git] / source / blender / editors / transform / transform_generics.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 \ingroup edtransform
21  */
22
23 #include <string.h>
24 #include <math.h>
25
26 #include "MEM_guardedalloc.h"
27
28 #include "BLI_sys_types.h" /* for intptr_t support */
29
30 #include "DNA_anim_types.h"
31 #include "DNA_armature_types.h"
32 #include "DNA_brush_types.h"
33 #include "DNA_gpencil_types.h"
34 #include "DNA_lattice_types.h"
35 #include "DNA_screen_types.h"
36 #include "DNA_sequence_types.h"
37 #include "DNA_space_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_mesh_types.h"
41 #include "DNA_view3d_types.h"
42 #include "DNA_modifier_types.h"
43 #include "DNA_movieclip_types.h"
44 #include "DNA_mask_types.h"
45 #include "DNA_meta_types.h"
46
47 #include "BLI_math.h"
48 #include "BLI_blenlib.h"
49 #include "BLI_rand.h"
50 #include "BLI_utildefines.h"
51
52 #include "PIL_time.h"
53
54 #include "BLT_translation.h"
55
56 #include "RNA_access.h"
57
58 #include "GPU_immediate.h"
59 #include "GPU_matrix.h"
60
61 #include "BIK_api.h"
62
63 #include "BKE_action.h"
64 #include "BKE_animsys.h"
65 #include "BKE_armature.h"
66 #include "BKE_context.h"
67 #include "BKE_curve.h"
68 #include "BKE_editmesh.h"
69 #include "BKE_fcurve.h"
70 #include "BKE_gpencil.h"
71 #include "BKE_lattice.h"
72 #include "BKE_layer.h"
73 #include "BKE_library.h"
74 #include "BKE_mask.h"
75 #include "BKE_nla.h"
76 #include "BKE_paint.h"
77 #include "BKE_scene.h"
78 #include "BKE_sequencer.h"
79 #include "BKE_tracking.h"
80 #include "BKE_workspace.h"
81
82 #include "DEG_depsgraph.h"
83
84 #include "ED_anim_api.h"
85 #include "ED_armature.h"
86 #include "ED_image.h"
87 #include "ED_keyframing.h"
88 #include "ED_markers.h"
89 #include "ED_mesh.h"
90 #include "ED_object.h"
91 #include "ED_particle.h"
92 #include "ED_screen_types.h"
93 #include "ED_space_api.h"
94 #include "ED_uvedit.h"
95 #include "ED_view3d.h"
96 #include "ED_curve.h" /* for curve_editnurbs */
97 #include "ED_clip.h"
98 #include "ED_screen.h"
99 #include "ED_gpencil.h"
100
101 #include "WM_types.h"
102 #include "WM_api.h"
103
104 #include "RE_engine.h"
105
106 #include "UI_resources.h"
107 #include "UI_view2d.h"
108
109 #include "transform.h"
110
111 /* ************************** Functions *************************** */
112
113 void getViewVector(const TransInfo *t, const float coord[3], float vec[3])
114 {
115         if (t->persp != RV3D_ORTHO) {
116                 sub_v3_v3v3(vec, coord, t->viewinv[3]);
117         }
118         else {
119                 copy_v3_v3(vec, t->viewinv[2]);
120         }
121         normalize_v3(vec);
122 }
123
124 /* ************************** GENERICS **************************** */
125
126
127 static void clipMirrorModifier(TransInfo *t)
128 {
129         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
130                 Object *ob = tc->obedit;
131                 ModifierData *md = ob->modifiers.first;
132                 float tolerance[3] = {0.0f, 0.0f, 0.0f};
133                 int axis = 0;
134
135                 for (; md; md = md->next) {
136                         if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
137                                 MirrorModifierData *mmd = (MirrorModifierData *) md;
138
139                                 if (mmd->flag & MOD_MIR_CLIPPING) {
140                                         axis = 0;
141                                         if (mmd->flag & MOD_MIR_AXIS_X) {
142                                                 axis |= 1;
143                                                 tolerance[0] = mmd->tolerance;
144                                         }
145                                         if (mmd->flag & MOD_MIR_AXIS_Y) {
146                                                 axis |= 2;
147                                                 tolerance[1] = mmd->tolerance;
148                                         }
149                                         if (mmd->flag & MOD_MIR_AXIS_Z) {
150                                                 axis |= 4;
151                                                 tolerance[2] = mmd->tolerance;
152                                         }
153                                         if (axis) {
154                                                 float mtx[4][4], imtx[4][4];
155                                                 int i;
156
157                                                 if (mmd->mirror_ob) {
158                                                         float obinv[4][4];
159
160                                                         invert_m4_m4(obinv, mmd->mirror_ob->obmat);
161                                                         mul_m4_m4m4(mtx, obinv, ob->obmat);
162                                                         invert_m4_m4(imtx, mtx);
163                                                 }
164
165                                                 TransData *td = tc->data;
166                                                 for (i = 0; i < tc->data_len; i++, td++) {
167                                                         int clip;
168                                                         float loc[3], iloc[3];
169
170                                                         if (td->flag & TD_NOACTION)
171                                                                 break;
172                                                         if (td->loc == NULL)
173                                                                 break;
174
175                                                         if (td->flag & TD_SKIP)
176                                                                 continue;
177
178                                                         copy_v3_v3(loc,  td->loc);
179                                                         copy_v3_v3(iloc, td->iloc);
180
181                                                         if (mmd->mirror_ob) {
182                                                                 mul_m4_v3(mtx, loc);
183                                                                 mul_m4_v3(mtx, iloc);
184                                                         }
185
186                                                         clip = 0;
187                                                         if (axis & 1) {
188                                                                 if (fabsf(iloc[0]) <= tolerance[0] ||
189                                                                     loc[0] * iloc[0] < 0.0f)
190                                                                 {
191                                                                         loc[0] = 0.0f;
192                                                                         clip = 1;
193                                                                 }
194                                                         }
195
196                                                         if (axis & 2) {
197                                                                 if (fabsf(iloc[1]) <= tolerance[1] ||
198                                                                     loc[1] * iloc[1] < 0.0f)
199                                                                 {
200                                                                         loc[1] = 0.0f;
201                                                                         clip = 1;
202                                                                 }
203                                                         }
204                                                         if (axis & 4) {
205                                                                 if (fabsf(iloc[2]) <= tolerance[2] ||
206                                                                     loc[2] * iloc[2] < 0.0f)
207                                                                 {
208                                                                         loc[2] = 0.0f;
209                                                                         clip = 1;
210                                                                 }
211                                                         }
212                                                         if (clip) {
213                                                                 if (mmd->mirror_ob) {
214                                                                         mul_m4_v3(imtx, loc);
215                                                                 }
216                                                                 copy_v3_v3(td->loc, loc);
217                                                         }
218                                                 }
219                                         }
220
221                                 }
222                         }
223                 }
224         }
225 }
226
227 /* assumes obedit set to mesh object */
228 static void editbmesh_apply_to_mirror(TransInfo *t)
229 {
230         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
231                 if (tc->mirror.axis_flag) {
232                         TransData *td = tc->data;
233                         BMVert *eve;
234                         int i;
235
236                         for (i = 0; i < tc->data_len; i++, td++) {
237                                 if (td->flag & TD_NOACTION)
238                                         break;
239                                 if (td->loc == NULL)
240                                         break;
241                                 if (td->flag & TD_SKIP)
242                                         continue;
243
244                                 eve = td->extra;
245                                 if (eve) {
246                                         eve->co[0] = -td->loc[0];
247                                         eve->co[1] = td->loc[1];
248                                         eve->co[2] = td->loc[2];
249                                 }
250
251                                 if (td->flag & TD_MIRROR_EDGE) {
252                                         td->loc[0] = 0;
253                                 }
254                         }
255                 }
256         }
257 }
258
259 /* for the realtime animation recording feature, handle overlapping data */
260 static void animrecord_check_state(Scene *scene, ID *id, wmTimer *animtimer)
261 {
262         ScreenAnimData *sad = (animtimer) ? animtimer->customdata : NULL;
263
264         /* sanity checks */
265         if (ELEM(NULL, scene, id, sad))
266                 return;
267
268         /* check if we need a new strip if:
269          * - if animtimer is running
270          * - we're not only keying for available channels
271          * - the option to add new actions for each round is not enabled
272          */
273         if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL) == 0 && (scene->toolsettings->autokey_flag & ANIMRECORD_FLAG_WITHNLA)) {
274                 /* if playback has just looped around,
275                  * we need to add a new NLA track+strip to allow a clean pass to occur */
276                 if ((sad) && (sad->flag & ANIMPLAY_FLAG_JUMPED)) {
277                         AnimData *adt = BKE_animdata_from_id(id);
278                         const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
279
280                         /* perform push-down manually with some differences
281                          * NOTE: BKE_nla_action_pushdown() sync warning...
282                          */
283                         if ((adt->action) && !(adt->flag & ADT_NLA_EDIT_ON)) {
284                                 float astart, aend;
285
286                                 /* only push down if action is more than 1-2 frames long */
287                                 calc_action_range(adt->action, &astart, &aend, 1);
288                                 if (aend > astart + 2.0f) {
289                                         NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action);
290
291                                         /* clear reference to action now that we've pushed it onto the stack */
292                                         id_us_min(&adt->action->id);
293                                         adt->action = NULL;
294
295                                         /* adjust blending + extend so that they will behave correctly */
296                                         strip->extendmode = NLASTRIP_EXTEND_NOTHING;
297                                         strip->flag &= ~(NLASTRIP_FLAG_AUTO_BLENDS | NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
298
299                                         /* copy current "action blending" settings from adt to the strip,
300                                          * as it was keyframed with these settings, so omitting them will
301                                          * change the effect  [T54766]
302                                          */
303                                         if (is_first == false) {
304                                                 strip->blendmode = adt->act_blendmode;
305                                                 strip->influence = adt->act_influence;
306
307                                                 if (adt->act_influence < 1.0f) {
308                                                         /* enable "user-controlled" influence (which will insert a default keyframe)
309                                                          * so that the influence doesn't get lost on the new update
310                                                          *
311                                                          * NOTE: An alternative way would have been to instead hack the influence
312                                                          * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
313                                                          * is disabled but auto-blending isn't being used. However, that approach
314                                                          * is a bit hacky/hard to discover, and may cause backwards compatibility issues,
315                                                          * so it's better to just do it this way.
316                                                          */
317                                                         strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
318                                                         BKE_nlastrip_validate_fcurves(strip);
319                                                 }
320                                         }
321
322                                         /* also, adjust the AnimData's action extend mode to be on
323                                          * 'nothing' so that previous result still play
324                                          */
325                                         adt->act_extendmode = NLASTRIP_EXTEND_NOTHING;
326                                 }
327                         }
328                 }
329         }
330 }
331
332 static bool fcu_test_selected(FCurve *fcu)
333 {
334         BezTriple *bezt = fcu->bezt;
335         unsigned int i;
336
337         if (bezt == NULL) /* ignore baked */
338                 return 0;
339
340         for (i = 0; i < fcu->totvert; i++, bezt++) {
341                 if (BEZT_ISSEL_ANY(bezt)) return 1;
342         }
343
344         return 0;
345 }
346
347 /* helper for recalcData() - for Action Editor transforms */
348 static void recalcData_actedit(TransInfo *t)
349 {
350         ViewLayer *view_layer = t->view_layer;
351         SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
352
353         bAnimContext ac = {NULL};
354         ListBase anim_data = {NULL, NULL};
355         bAnimListElem *ale;
356         int filter;
357
358         /* initialize relevant anim-context 'context' data from TransInfo data */
359         /* NOTE: sync this with the code in ANIM_animdata_get_context() */
360         ac.bmain = CTX_data_main(t->context);
361         ac.scene = t->scene;
362         ac.view_layer = t->view_layer;
363         ac.obact = OBACT(view_layer);
364         ac.sa = t->sa;
365         ac.ar = t->ar;
366         ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
367         ac.spacetype = (t->sa) ? t->sa->spacetype : 0;
368         ac.regiontype = (t->ar) ? t->ar->regiontype : 0;
369
370         ANIM_animdata_context_getdata(&ac);
371
372         /* perform flush */
373         if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
374                 /* flush transform values back to actual coordinates */
375                 flushTransIntFrameActionData(t);
376         }
377
378         if (ac.datatype != ANIMCONT_MASK) {
379                 /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
380                 filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
381                 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
382
383                 /* just tag these animdata-blocks to recalc, assuming that some data there changed
384                  * BUT only do this if realtime updates are enabled
385                  */
386                 if ((saction->flag & SACTION_NOREALTIMEUPDATES) == 0) {
387                         for (ale = anim_data.first; ale; ale = ale->next) {
388                                 /* set refresh tags for objects using this animation */
389                                 ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
390                         }
391                 }
392
393                 /* now free temp channels */
394                 ANIM_animdata_freelist(&anim_data);
395         }
396 }
397 /* helper for recalcData() - for Graph Editor transforms */
398 static void recalcData_graphedit(TransInfo *t)
399 {
400         SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
401         ViewLayer *view_layer = t->view_layer;
402
403         ListBase anim_data = {NULL, NULL};
404         bAnimContext ac = {NULL};
405         int filter;
406
407         bAnimListElem *ale;
408         int dosort = 0;
409
410         /* initialize relevant anim-context 'context' data from TransInfo data */
411         /* NOTE: sync this with the code in ANIM_animdata_get_context() */
412         ac.bmain = CTX_data_main(t->context);
413         ac.scene = t->scene;
414         ac.view_layer = t->view_layer;
415         ac.obact = OBACT(view_layer);
416         ac.sa = t->sa;
417         ac.ar = t->ar;
418         ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
419         ac.spacetype = (t->sa) ? t->sa->spacetype : 0;
420         ac.regiontype = (t->ar) ? t->ar->regiontype : 0;
421
422         ANIM_animdata_context_getdata(&ac);
423
424         /* do the flush first */
425         flushTransGraphData(t);
426
427         /* get curves to check if a re-sort is needed */
428         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
429         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
430
431         /* now test if there is a need to re-sort */
432         for (ale = anim_data.first; ale; ale = ale->next) {
433                 FCurve *fcu = (FCurve *)ale->key_data;
434
435                 /* ignore FC-Curves without any selected verts */
436                 if (!fcu_test_selected(fcu))
437                         continue;
438
439                 /* watch it: if the time is wrong: do not correct handles yet */
440                 if (test_time_fcurve(fcu))
441                         dosort++;
442                 else
443                         calchandles_fcurve(fcu);
444
445                 /* set refresh tags for objects using this animation,
446                  * BUT only if realtime updates are enabled
447                  */
448                 if ((sipo->flag & SIPO_NOREALTIMEUPDATES) == 0)
449                         ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
450         }
451
452         /* do resort and other updates? */
453         if (dosort) remake_graph_transdata(t, &anim_data);
454
455         /* now free temp channels */
456         ANIM_animdata_freelist(&anim_data);
457 }
458
459 /* helper for recalcData() - for NLA Editor transforms */
460 static void recalcData_nla(TransInfo *t)
461 {
462         SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
463         Scene *scene = t->scene;
464         double secf = FPS;
465         int i;
466
467         TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
468         TransDataNla *tdn = tc->custom.type.data;
469
470         /* for each strip we've got, perform some additional validation of the values that got set before
471          * using RNA to set the value (which does some special operations when setting these values to make
472          * sure that everything works ok)
473          */
474         for (i = 0; i < tc->data_len; i++, tdn++) {
475                 NlaStrip *strip = tdn->strip;
476                 PointerRNA strip_ptr;
477                 short pExceeded, nExceeded, iter;
478                 int delta_y1, delta_y2;
479
480                 /* if this tdn has no handles, that means it is just a dummy that should be skipped */
481                 if (tdn->handle == 0)
482                         continue;
483
484                 /* set refresh tags for objects using this animation,
485                  * BUT only if realtime updates are enabled
486                  */
487                 if ((snla->flag & SNLA_NOREALTIMEUPDATES) == 0)
488                         ANIM_id_update(CTX_data_main(t->context), tdn->id);
489
490                 /* if canceling transform, just write the values without validating, then move on */
491                 if (t->state == TRANS_CANCEL) {
492                         /* clear the values by directly overwriting the originals, but also need to restore
493                          * endpoints of neighboring transition-strips
494                          */
495
496                         /* start */
497                         strip->start = tdn->h1[0];
498
499                         if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
500                                 strip->prev->end = tdn->h1[0];
501
502                         /* end */
503                         strip->end = tdn->h2[0];
504
505                         if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION))
506                                 strip->next->start = tdn->h2[0];
507
508                         /* flush transforms to child strips (since this should be a meta) */
509                         BKE_nlameta_flush_transforms(strip);
510
511                         /* restore to original track (if needed) */
512                         if (tdn->oldTrack != tdn->nlt) {
513                                 /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */
514                                 BLI_remlink(&tdn->nlt->strips, strip);
515                                 BLI_addtail(&tdn->oldTrack->strips, strip);
516                         }
517
518                         continue;
519                 }
520
521                 /* firstly, check if the proposed transform locations would overlap with any neighboring strips
522                  * (barring transitions) which are absolute barriers since they are not being moved
523                  *
524                  * this is done as a iterative procedure (done 5 times max for now)
525                  */
526                 for (iter = 0; iter < 5; iter++) {
527                         pExceeded = ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h1[0] < strip->prev->end));
528                         nExceeded = ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h2[0] > strip->next->start));
529
530                         if ((pExceeded && nExceeded) || (iter == 4)) {
531                                 /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise)
532                                  * - simply crop strip to fit within the bounds of the strips bounding it
533                                  * - if there were no neighbors, clear the transforms (make it default to the strip's current values)
534                                  */
535                                 if (strip->prev && strip->next) {
536                                         tdn->h1[0] = strip->prev->end;
537                                         tdn->h2[0] = strip->next->start;
538                                 }
539                                 else {
540                                         tdn->h1[0] = strip->start;
541                                         tdn->h2[0] = strip->end;
542                                 }
543                         }
544                         else if (nExceeded) {
545                                 /* move backwards */
546                                 float offset = tdn->h2[0] - strip->next->start;
547
548                                 tdn->h1[0] -= offset;
549                                 tdn->h2[0] -= offset;
550                         }
551                         else if (pExceeded) {
552                                 /* more forwards */
553                                 float offset = strip->prev->end - tdn->h1[0];
554
555                                 tdn->h1[0] += offset;
556                                 tdn->h2[0] += offset;
557                         }
558                         else /* all is fine and well */
559                                 break;
560                 }
561
562                 /* handle auto-snapping
563                  * NOTE: only do this when transform is still running, or we can't restore
564                  */
565                 if (t->state != TRANS_CANCEL) {
566                         switch (snla->autosnap) {
567                                 case SACTSNAP_FRAME: /* snap to nearest frame */
568                                 case SACTSNAP_STEP: /* frame step - this is basically the same,
569                                                      * since we don't have any remapping going on */
570                                 {
571                                         tdn->h1[0] = floorf(tdn->h1[0] + 0.5f);
572                                         tdn->h2[0] = floorf(tdn->h2[0] + 0.5f);
573                                         break;
574                                 }
575
576                                 case SACTSNAP_SECOND: /* snap to nearest second */
577                                 case SACTSNAP_TSTEP: /* second step - this is basically the same,
578                                                       * since we don't have any remapping going on */
579                                 {
580                                         /* This case behaves differently from the rest, since lengths of strips
581                                          * may not be multiples of a second. If we just naively resize adjust
582                                          * the handles, things may not work correctly. Instead, we only snap
583                                          * the first handle, and move the other to fit.
584                                          *
585                                          * FIXME: we do run into problems here when user attempts to negatively
586                                          *        scale the strip, as it then just compresses down and refuses
587                                          *        to expand out the other end.
588                                          */
589                                         float h1_new = (float)(floor(((double)tdn->h1[0] / secf) + 0.5) * secf);
590                                         float delta  = h1_new - tdn->h1[0];
591
592                                         tdn->h1[0] = h1_new;
593                                         tdn->h2[0] += delta;
594                                         break;
595                                 }
596
597                                 case SACTSNAP_MARKER: /* snap to nearest marker */
598                                 {
599                                         tdn->h1[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]);
600                                         tdn->h2[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]);
601                                         break;
602                                 }
603                         }
604                 }
605
606                 /* Use RNA to write the values to ensure that constraints on these are obeyed
607                  * (e.g. for transition strips, the values are taken from the neighbors)
608                  *
609                  * NOTE: we write these twice to avoid truncation errors which can arise when
610                  * moving the strips a large distance using numeric input [#33852]
611                  */
612                 RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
613
614                 RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
615                 RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
616
617                 RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
618                 RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
619
620                 /* flush transforms to child strips (since this should be a meta) */
621                 BKE_nlameta_flush_transforms(strip);
622
623
624                 /* now, check if we need to try and move track
625                  * - we need to calculate both, as only one may have been altered by transform if only 1 handle moved
626                  */
627                 delta_y1 = ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
628                 delta_y2 = ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
629
630                 if (delta_y1 || delta_y2) {
631                         NlaTrack *track;
632                         int delta = (delta_y2) ? delta_y2 : delta_y1;
633                         int n;
634
635                         /* move in the requested direction, checking at each layer if there's space for strip to pass through,
636                          * stopping on the last track available or that we're able to fit in
637                          */
638                         if (delta > 0) {
639                                 for (track = tdn->nlt->next, n = 0; (track) && (n < delta); track = track->next, n++) {
640                                         /* check if space in this track for the strip */
641                                         if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
642                                                 /* move strip to this track */
643                                                 BLI_remlink(&tdn->nlt->strips, strip);
644                                                 BKE_nlatrack_add_strip(track, strip);
645
646                                                 tdn->nlt = track;
647                                                 tdn->trackIndex++;
648                                         }
649                                         else /* can't move any further */
650                                                 break;
651                                 }
652                         }
653                         else {
654                                 /* make delta 'positive' before using it, since we now know to go backwards */
655                                 delta = -delta;
656
657                                 for (track = tdn->nlt->prev, n = 0; (track) && (n < delta); track = track->prev, n++) {
658                                         /* check if space in this track for the strip */
659                                         if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
660                                                 /* move strip to this track */
661                                                 BLI_remlink(&tdn->nlt->strips, strip);
662                                                 BKE_nlatrack_add_strip(track, strip);
663
664                                                 tdn->nlt = track;
665                                                 tdn->trackIndex--;
666                                         }
667                                         else /* can't move any further */
668                                                 break;
669                                 }
670                         }
671                 }
672         }
673 }
674
675 static void recalcData_mask_common(TransInfo *t)
676 {
677         Mask *mask = CTX_data_edit_mask(t->context);
678
679         flushTransMasking(t);
680
681         DEG_id_tag_update(&mask->id, 0);
682 }
683
684 /* helper for recalcData() - for Image Editor transforms */
685 static void recalcData_image(TransInfo *t)
686 {
687         if (t->options & CTX_MASK) {
688                 recalcData_mask_common(t);
689         }
690         else if (t->options & CTX_PAINT_CURVE) {
691                 flushTransPaintCurve(t);
692         }
693         else if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
694                 SpaceImage *sima = t->sa->spacedata.first;
695
696                 flushTransUVs(t);
697                 if (sima->flag & SI_LIVE_UNWRAP)
698                         ED_uvedit_live_unwrap_re_solve();
699
700                 FOREACH_TRANS_DATA_CONTAINER (t, tc) {
701                         if (tc->data_len) {
702                                 DEG_id_tag_update(tc->obedit->data, 0);
703                         }
704                 }
705         }
706 }
707
708 /* helper for recalcData() - for Movie Clip transforms */
709 static void recalcData_spaceclip(TransInfo *t)
710 {
711         SpaceClip *sc = t->sa->spacedata.first;
712
713         if (ED_space_clip_check_show_trackedit(sc)) {
714                 MovieClip *clip = ED_space_clip_get_clip(sc);
715                 ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
716                 MovieTrackingTrack *track;
717                 int framenr = ED_space_clip_get_clip_frame_number(sc);
718
719                 flushTransTracking(t);
720
721                 track = tracksbase->first;
722                 while (track) {
723                         if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
724                                 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
725
726                                 if (t->mode == TFM_TRANSLATION) {
727                                         if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
728                                                 BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
729                                         if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
730                                                 BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_POS);
731                                 }
732                                 else if (t->mode == TFM_RESIZE) {
733                                         if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
734                                                 BKE_tracking_marker_clamp(marker, CLAMP_PAT_DIM);
735                                         if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
736                                                 BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_DIM);
737                                 }
738                                 else if (t->mode == TFM_ROTATION) {
739                                         if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
740                                                 BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
741                                 }
742                         }
743
744                         track = track->next;
745                 }
746
747                 DEG_id_tag_update(&clip->id, 0);
748         }
749         else if (t->options & CTX_MASK) {
750                 recalcData_mask_common(t);
751         }
752 }
753
754 /* helper for recalcData() - for object transforms, typically in the 3D view */
755 static void recalcData_objects(TransInfo *t)
756 {
757         Base *base = t->view_layer->basact;
758
759         if (t->obedit_type != -1) {
760                 if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) {
761
762                         if (t->state != TRANS_CANCEL) {
763                                 clipMirrorModifier(t);
764                                 applyProject(t);
765                         }
766
767                         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
768                                 Curve *cu = tc->obedit->data;
769                                 ListBase *nurbs = BKE_curve_editNurbs_get(cu);
770                                 Nurb *nu = nurbs->first;
771
772                                 DEG_id_tag_update(tc->obedit->data, 0);  /* sets recalc flags */
773
774                                 if (t->state == TRANS_CANCEL) {
775                                         while (nu) {
776                                                 /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
777                                                 BKE_nurb_handles_calc(nu);
778                                                 nu = nu->next;
779                                         }
780                                 }
781                                 else {
782                                         /* Normal updating */
783                                         while (nu) {
784                                                 BKE_nurb_test_2d(nu);
785                                                 BKE_nurb_handles_calc(nu);
786                                                 nu = nu->next;
787                                         }
788                                 }
789                         }
790                 }
791                 else if (t->obedit_type == OB_LATTICE) {
792
793                         if (t->state != TRANS_CANCEL) {
794                                 applyProject(t);
795                         }
796
797                         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
798                                 Lattice *la = tc->obedit->data;
799                                 DEG_id_tag_update(tc->obedit->data, 0);  /* sets recalc flags */
800                                 if (la->editlatt->latt->flag & LT_OUTSIDE) {
801                                         outside_lattice(la->editlatt->latt);
802                                 }
803                         }
804                 }
805                 else if (t->obedit_type == OB_MESH) {
806                         /* mirror modifier clipping? */
807                         if (t->state != TRANS_CANCEL) {
808                                 /* apply clipping after so we never project past the clip plane [#25423] */
809                                 applyProject(t);
810                                 clipMirrorModifier(t);
811                         }
812                         if ((t->flag & T_NO_MIRROR) == 0 &&
813                             (t->options & CTX_NO_MIRROR) == 0)
814                         {
815                                 editbmesh_apply_to_mirror(t);
816                         }
817
818                         if (t->mode == TFM_EDGE_SLIDE) {
819                                 projectEdgeSlideData(t, false);
820                         }
821                         else if (t->mode == TFM_VERT_SLIDE) {
822                                 projectVertSlideData(t, false);
823                         }
824
825                         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
826                                 DEG_id_tag_update(tc->obedit->data, 0);  /* sets recalc flags */
827                                 BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
828                                 EDBM_mesh_normals_update(em);
829                                 BKE_editmesh_tessface_calc(em);
830                         }
831                 }
832                 else if (t->obedit_type == OB_ARMATURE) { /* no recalc flag, does pose */
833
834                         if (t->state != TRANS_CANCEL) {
835                                 applyProject(t);
836                         }
837
838                         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
839                                 bArmature *arm = tc->obedit->data;
840                                 ListBase *edbo = arm->edbo;
841                                 EditBone *ebo, *ebo_parent;
842                                 TransData *td = tc->data;
843                                 int i;
844
845                                 /* Ensure all bones are correctly adjusted */
846                                 for (ebo = edbo->first; ebo; ebo = ebo->next) {
847                                         ebo_parent = (ebo->flag & BONE_CONNECTED) ? ebo->parent : NULL;
848
849                                         if (ebo_parent) {
850                                                 /* If this bone has a parent tip that has been moved */
851                                                 if (ebo_parent->flag & BONE_TIPSEL) {
852                                                         copy_v3_v3(ebo->head, ebo_parent->tail);
853                                                         if (t->mode == TFM_BONE_ENVELOPE) ebo->rad_head = ebo_parent->rad_tail;
854                                                 }
855                                                 /* If this bone has a parent tip that has NOT been moved */
856                                                 else {
857                                                         copy_v3_v3(ebo_parent->tail, ebo->head);
858                                                         if (t->mode == TFM_BONE_ENVELOPE) ebo_parent->rad_tail = ebo->rad_head;
859                                                 }
860                                         }
861
862                                         /* on extrude bones, oldlength==0.0f, so we scale radius of points */
863                                         ebo->length = len_v3v3(ebo->head, ebo->tail);
864                                         if (ebo->oldlength == 0.0f) {
865                                                 ebo->rad_head = 0.25f * ebo->length;
866                                                 ebo->rad_tail = 0.10f * ebo->length;
867                                                 ebo->dist = 0.25f * ebo->length;
868                                                 if (ebo->parent) {
869                                                         if (ebo->rad_head > ebo->parent->rad_tail)
870                                                                 ebo->rad_head = ebo->parent->rad_tail;
871                                                 }
872                                         }
873                                         else if (t->mode != TFM_BONE_ENVELOPE) {
874                                                 /* if bones change length, lets do that for the deform distance as well */
875                                                 ebo->dist *= ebo->length / ebo->oldlength;
876                                                 ebo->rad_head *= ebo->length / ebo->oldlength;
877                                                 ebo->rad_tail *= ebo->length / ebo->oldlength;
878                                                 ebo->oldlength = ebo->length;
879
880                                                 if (ebo_parent) {
881                                                         ebo_parent->rad_tail = ebo->rad_head;
882                                                 }
883                                         }
884                                 }
885
886                                 if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONE_ENVELOPE_DIST, TFM_BONESIZE)) {
887                                         /* fix roll */
888                                         for (i = 0; i < tc->data_len; i++, td++) {
889                                                 if (td->extra) {
890                                                         float vec[3], up_axis[3];
891                                                         float qrot[4];
892                                                         float roll;
893
894                                                         ebo = td->extra;
895
896                                                         if (t->state == TRANS_CANCEL) {
897                                                                 /* restore roll */
898                                                                 ebo->roll = td->ival;
899                                                         }
900                                                         else {
901                                                                 copy_v3_v3(up_axis, td->axismtx[2]);
902
903                                                                 sub_v3_v3v3(vec, ebo->tail, ebo->head);
904                                                                 normalize_v3(vec);
905                                                                 rotation_between_vecs_to_quat(qrot, td->axismtx[1], vec);
906                                                                 mul_qt_v3(qrot, up_axis);
907
908                                                                 /* roll has a tendency to flip in certain orientations - [#34283], [#33974] */
909                                                                 roll = ED_armature_ebone_roll_to_vector(ebo, up_axis, false);
910                                                                 ebo->roll = angle_compat_rad(roll, td->ival);
911                                                         }
912                                                 }
913                                         }
914                                 }
915
916                                 if (arm->flag & ARM_MIRROR_EDIT) {
917                                         if (t->state != TRANS_CANCEL) {
918                                                 ED_armature_edit_transform_mirror_update(tc->obedit);
919                                         }
920                                         else {
921                                                 restoreBones(tc);
922                                         }
923                                 }
924                         }
925                 }
926                 else {
927                         if (t->state != TRANS_CANCEL) {
928                                 applyProject(t);
929                         }
930                         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
931                                 if (tc->data_len) {
932                                         DEG_id_tag_update(tc->obedit->data, 0);  /* sets recalc flags */
933                                 }
934                         }
935                 }
936
937         }
938         else if (t->flag & T_POSE) {
939                 GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
940
941                 FOREACH_TRANS_DATA_CONTAINER (t, tc) {
942                         Object *ob = tc->poseobj;
943                         bArmature *arm = ob->data;
944
945                         /* if animtimer is running, and the object already has animation data,
946                          * check if the auto-record feature means that we should record 'samples'
947                          * (i.e. uneditable animation values)
948                          *
949                          * context is needed for keying set poll() functions.
950                          */
951                         // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
952                         if ((t->animtimer) && (t->context) && IS_AUTOKEY_ON(t->scene)) {
953                                 int targetless_ik = (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
954
955                                 animrecord_check_state(t->scene, &ob->id, t->animtimer);
956                                 autokeyframe_pose(t->context, t->scene, ob, t->mode, targetless_ik);
957                         }
958
959                         if (motionpath_need_update_pose(t->scene, ob)) {
960                                 BLI_gset_insert(motionpath_updates, ob);
961                         }
962
963                         /* old optimize trick... this enforces to bypass the depgraph */
964                         if (!(arm->flag & ARM_DELAYDEFORM)) {
965                                 DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);  /* sets recalc flags */
966                                 /* transformation of pose may affect IK tree, make sure it is rebuilt */
967                                 BIK_clear_data(ob->pose);
968                         }
969                         else {
970                                 BKE_pose_where_is(t->depsgraph, t->scene, ob);
971                         }
972                 }
973
974                 /* Update motion paths once for all transformed bones in an object. */
975                 GSetIterator gs_iter;
976                 GSET_ITER (gs_iter, motionpath_updates) {
977                         Object *ob = BLI_gsetIterator_getKey(&gs_iter);
978                         ED_pose_recalculate_paths(t->context, t->scene, ob, true);
979                 }
980                 BLI_gset_free(motionpath_updates, NULL);
981         }
982         else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) &&
983                  PE_get_current(t->scene, base->object))
984         {
985                 if (t->state != TRANS_CANCEL) {
986                         applyProject(t);
987                 }
988                 flushTransParticles(t);
989         }
990         else {
991                 bool motionpath_update = false;
992
993                 if (t->state != TRANS_CANCEL) {
994                         applyProject(t);
995                 }
996
997                 FOREACH_TRANS_DATA_CONTAINER (t, tc) {
998                         TransData *td = tc->data;
999
1000                         for (int i = 0; i < tc->data_len; i++, td++) {
1001                                 Object *ob = td->ob;
1002
1003                                 if (td->flag & TD_NOACTION)
1004                                         break;
1005
1006                                 if (td->flag & TD_SKIP)
1007                                         continue;
1008
1009                                 /* if animtimer is running, and the object already has animation data,
1010                                  * check if the auto-record feature means that we should record 'samples'
1011                                  * (i.e. uneditable animation values)
1012                                  */
1013                                 // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
1014                                 if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
1015                                         animrecord_check_state(t->scene, &ob->id, t->animtimer);
1016                                         autokeyframe_object(t->context, t->scene, t->view_layer, ob, t->mode);
1017                                 }
1018
1019                                 motionpath_update |= motionpath_need_update_object(t->scene, ob);
1020
1021                                 /* sets recalc flags fully, instead of flushing existing ones
1022                                  * otherwise proxies don't function correctly
1023                                  */
1024                                 DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
1025
1026                                 if (t->flag & T_TEXTURE)
1027                                         DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
1028                         }
1029                 }
1030
1031                 if (motionpath_update) {
1032                         /* Update motion paths once for all transformed objects. */
1033                         ED_objects_recalculate_paths(t->context, t->scene, true);
1034                 }
1035         }
1036 }
1037
1038 static void recalcData_cursor(TransInfo *t)
1039 {
1040         DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
1041 }
1042
1043 /* helper for recalcData() - for sequencer transforms */
1044 static void recalcData_sequencer(TransInfo *t)
1045 {
1046         TransData *td;
1047         int a;
1048         Sequence *seq_prev = NULL;
1049
1050         TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
1051
1052         for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
1053                 TransDataSeq *tdsq = (TransDataSeq *) td->extra;
1054                 Sequence *seq = tdsq->seq;
1055
1056                 if (seq != seq_prev) {
1057                         if (BKE_sequence_tx_fullupdate_test(seq)) {
1058                                 /* A few effect strip types need a complete recache on transform. */
1059                                 BKE_sequence_invalidate_cache(t->scene, seq);
1060                         }
1061                         else {
1062                                 BKE_sequence_invalidate_dependent(t->scene, seq);
1063                         }
1064                 }
1065
1066                 seq_prev = seq;
1067         }
1068
1069         BKE_sequencer_preprocessed_cache_cleanup();
1070
1071         flushTransSeq(t);
1072 }
1073
1074 /* force recalculation of triangles during transformation */
1075 static void recalcData_gpencil_strokes(TransInfo *t)
1076 {
1077         TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
1078
1079         TransData *td = tc->data;
1080         for (int i = 0; i < tc->data_len; i++, td++) {
1081                 bGPDstroke *gps = td->extra;
1082                 if (gps != NULL) {
1083                         gps->flag |= GP_STROKE_RECALC_GEOMETRY;
1084                 }
1085         }
1086 }
1087
1088 /* called for updating while transform acts, once per redraw */
1089 void recalcData(TransInfo *t)
1090 {
1091         /* if tests must match createTransData for correct updates */
1092         if (t->options & CTX_CURSOR) {
1093                 recalcData_cursor(t);
1094         }
1095         else if (t->options & CTX_TEXTURE) {
1096                 recalcData_objects(t);
1097         }
1098         else if (t->options & CTX_EDGE) {
1099                 recalcData_objects(t);
1100         }
1101         else if (t->options & CTX_PAINT_CURVE) {
1102                 flushTransPaintCurve(t);
1103         }
1104         else if (t->options & CTX_GPENCIL_STROKES) {
1105                 /* set recalc triangle cache flag */
1106                 recalcData_gpencil_strokes(t);
1107         }
1108         else if (t->spacetype == SPACE_IMAGE) {
1109                 recalcData_image(t);
1110         }
1111         else if (t->spacetype == SPACE_ACTION) {
1112                 recalcData_actedit(t);
1113         }
1114         else if (t->spacetype == SPACE_NLA) {
1115                 recalcData_nla(t);
1116         }
1117         else if (t->spacetype == SPACE_SEQ) {
1118                 recalcData_sequencer(t);
1119         }
1120         else if (t->spacetype == SPACE_IPO) {
1121                 recalcData_graphedit(t);
1122         }
1123         else if (t->spacetype == SPACE_NODE) {
1124                 flushTransNodes(t);
1125         }
1126         else if (t->spacetype == SPACE_CLIP) {
1127                 recalcData_spaceclip(t);
1128         }
1129         else {
1130                 recalcData_objects(t);
1131         }
1132 }
1133
1134 void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options)
1135 {
1136         float v1[3], v2[3], v3[3];
1137         unsigned char col[3], col2[3];
1138
1139         if (t->spacetype == SPACE_VIEW3D) {
1140                 View3D *v3d = t->view;
1141
1142                 GPU_matrix_push();
1143
1144                 copy_v3_v3(v3, dir);
1145                 mul_v3_fl(v3, v3d->far);
1146
1147                 sub_v3_v3v3(v2, center, v3);
1148                 add_v3_v3v3(v1, center, v3);
1149
1150                 if (options & DRAWLIGHT) {
1151                         col[0] = col[1] = col[2] = 220;
1152                 }
1153                 else {
1154                         UI_GetThemeColor3ubv(TH_GRID, col);
1155                 }
1156                 UI_make_axis_color(col, col2, axis);
1157
1158                 uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1159
1160                 immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
1161                 immUniformColor3ubv(col2);
1162
1163                 immBegin(GPU_PRIM_LINES, 2);
1164                 immVertex3fv(pos, v1);
1165                 immVertex3fv(pos, v2);
1166                 immEnd();
1167
1168                 immUnbindProgram();
1169
1170                 GPU_matrix_pop();
1171         }
1172 }
1173
1174 /**
1175  * Free data before switching to another mode.
1176  */
1177 void resetTransModal(TransInfo *t)
1178 {
1179         freeTransCustomDataForMode(t);
1180 }
1181
1182 void resetTransRestrictions(TransInfo *t)
1183 {
1184         t->flag &= ~T_ALL_RESTRICTIONS;
1185 }
1186
1187 static int initTransInfo_edit_pet_to_flag(const int proportional)
1188 {
1189         switch (proportional) {
1190                 case PROP_EDIT_ON:
1191                         return T_PROP_EDIT;
1192                 case PROP_EDIT_CONNECTED:
1193                         return T_PROP_EDIT | T_PROP_CONNECTED;
1194                 case PROP_EDIT_PROJECTED:
1195                         return T_PROP_EDIT | T_PROP_PROJECTED;
1196                 default:
1197                         return 0;
1198         }
1199 }
1200
1201 void initTransDataContainers_FromObjectData(TransInfo *t, Object *obact, Object **objects, uint objects_len)
1202 {
1203         const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
1204         const short object_type = obact ? obact->type : -1;
1205
1206         if ((object_mode & OB_MODE_EDIT) || (t->options & CTX_GPENCIL_STROKES) ||
1207             ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE)))
1208         {
1209                 if (t->data_container) {
1210                         MEM_freeN(t->data_container);
1211                 }
1212
1213                 bool free_objects = false;
1214                 if (objects == NULL) {
1215                         objects = BKE_view_layer_array_from_objects_in_mode(
1216                                 t->view_layer,
1217                                 (t->spacetype == SPACE_VIEW3D) ? t->view : NULL,
1218                                 &objects_len, {
1219                                     .object_mode = object_mode,
1220                                     .no_dup_data = true,
1221                                 });
1222                         free_objects = true;
1223                 }
1224
1225                 t->data_container = MEM_callocN(sizeof(*t->data_container) * objects_len, __func__);
1226                 t->data_container_len = objects_len;
1227
1228                 for (int i = 0; i < objects_len; i++) {
1229                         TransDataContainer *tc = &t->data_container[i];
1230                         /* TODO, multiple axes. */
1231                         tc->mirror.axis_flag = (
1232                                 ((t->flag & T_NO_MIRROR) == 0) &&
1233                                 ((t->options & CTX_NO_MIRROR) == 0) &&
1234                                 (((Mesh *)objects[i]->data)->editflag & ME_EDIT_MIRROR_X) != 0);
1235
1236                         if (object_mode & OB_MODE_EDIT) {
1237                                 tc->obedit = objects[i];
1238                                 /* Check needed for UV's */
1239                                 if ((t->flag & T_2D_EDIT) == 0) {
1240                                         tc->use_local_mat = true;
1241                                 }
1242                         }
1243                         else if (object_mode & OB_MODE_POSE) {
1244                                 tc->poseobj = objects[i];
1245                                 tc->use_local_mat = true;
1246                         }
1247                         else if (t->options & CTX_GPENCIL_STROKES) {
1248                                 tc->use_local_mat = true;
1249                         }
1250
1251                         if (tc->use_local_mat) {
1252                                 BLI_assert((t->flag & T_2D_EDIT) == 0);
1253                                 copy_m4_m4(tc->mat, objects[i]->obmat);
1254                                 copy_m3_m4(tc->mat3, tc->mat);
1255                                 invert_m4_m4(tc->imat, tc->mat);
1256                                 invert_m3_m3(tc->imat3, tc->mat3);
1257                                 normalize_m3_m3(tc->mat3_unit, tc->mat3);
1258                         }
1259                         /* Otherwise leave as zero. */
1260                 }
1261
1262                 if (free_objects) {
1263                         MEM_freeN(objects);
1264                 }
1265         }
1266 }
1267
1268 /**
1269  * Setup internal data, mouse, vectors
1270  *
1271  * \note \a op and \a event can be NULL
1272  *
1273  * \see #saveTransform does the reverse.
1274  */
1275 void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
1276 {
1277         Depsgraph *depsgraph = CTX_data_depsgraph(C);
1278         Scene *sce = CTX_data_scene(C);
1279         ViewLayer *view_layer = CTX_data_view_layer(C);
1280         const eObjectMode object_mode = OBACT(view_layer) ? OBACT(view_layer)->mode : OB_MODE_OBJECT;
1281         const short object_type = OBACT(view_layer) ? OBACT(view_layer)->type : -1;
1282         ToolSettings *ts = CTX_data_tool_settings(C);
1283         ARegion *ar = CTX_wm_region(C);
1284         ScrArea *sa = CTX_wm_area(C);
1285
1286         bGPdata *gpd = CTX_data_gpencil_data(C);
1287         PropertyRNA *prop;
1288
1289         t->depsgraph = depsgraph;
1290         t->scene = sce;
1291         t->view_layer = view_layer;
1292         t->sa = sa;
1293         t->ar = ar;
1294         t->settings = ts;
1295         t->reports = op ? op->reports : NULL;
1296
1297         t->helpline = HLP_NONE;
1298
1299         t->flag = 0;
1300
1301         t->obedit_type = ((object_mode == OB_MODE_EDIT) || (object_mode == OB_MODE_EDIT_GPENCIL)) ? object_type : -1;
1302
1303         /* Many kinds of transform only use a single handle. */
1304         if (t->data_container == NULL) {
1305                 t->data_container = MEM_callocN(sizeof(*t->data_container), __func__);
1306                 t->data_container_len = 1;
1307         }
1308
1309         t->redraw = TREDRAW_HARD;  /* redraw first time */
1310
1311         if (event) {
1312                 t->mouse.imval[0] = event->mval[0];
1313                 t->mouse.imval[1] = event->mval[1];
1314         }
1315         else {
1316                 t->mouse.imval[0] = 0;
1317                 t->mouse.imval[1] = 0;
1318         }
1319
1320         t->con.imval[0] = t->mouse.imval[0];
1321         t->con.imval[1] = t->mouse.imval[1];
1322
1323         t->mval[0] = t->mouse.imval[0];
1324         t->mval[1] = t->mouse.imval[1];
1325
1326         t->transform        = NULL;
1327         t->handleEvent      = NULL;
1328
1329         t->data_len_all = 0;
1330
1331         t->val = 0.0f;
1332
1333         zero_v3(t->vec);
1334         zero_v3(t->center_global);
1335
1336         unit_m3(t->mat);
1337
1338         /* if there's an event, we're modal */
1339         if (event) {
1340                 t->flag |= T_MODAL;
1341         }
1342
1343         /* Crease needs edge flag */
1344         if (ELEM(t->mode, TFM_CREASE, TFM_BWEIGHT)) {
1345                 t->options |= CTX_EDGE;
1346         }
1347
1348         t->remove_on_cancel = false;
1349
1350         if (op && (prop = RNA_struct_find_property(op->ptr, "remove_on_cancel")) && RNA_property_is_set(op->ptr, prop)) {
1351                 if (RNA_property_boolean_get(op->ptr, prop)) {
1352                         t->remove_on_cancel = true;
1353                 }
1354         }
1355
1356         /* GPencil editing context */
1357         if (GPENCIL_EDIT_MODE(gpd)) {
1358                 t->options |= CTX_GPENCIL_STROKES;
1359         }
1360
1361         /* Assign the space type, some exceptions for running in different mode */
1362         if (sa == NULL) {
1363                 /* background mode */
1364                 t->spacetype = SPACE_EMPTY;
1365         }
1366         else if ((ar == NULL) && (sa->spacetype == SPACE_VIEW3D)) {
1367                 /* running in the text editor */
1368                 t->spacetype = SPACE_EMPTY;
1369         }
1370         else {
1371                 /* normal operation */
1372                 t->spacetype = sa->spacetype;
1373         }
1374
1375         /* handle T_ALT_TRANSFORM initialization, we may use for different operators */
1376         if (op) {
1377                 const char *prop_id = NULL;
1378                 if (t->mode == TFM_SHRINKFATTEN) {
1379                         prop_id = "use_even_offset";
1380                 }
1381
1382                 if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) {
1383                         SET_FLAG_FROM_TEST(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM);
1384                 }
1385         }
1386
1387         if (t->spacetype == SPACE_VIEW3D) {
1388                 View3D *v3d = sa->spacedata.first;
1389                 bScreen *animscreen = ED_screen_animation_playing(CTX_wm_manager(C));
1390
1391                 t->view = v3d;
1392                 t->animtimer = (animscreen) ? animscreen->animtimer : NULL;
1393
1394                 /* turn gizmo off during transform */
1395                 if (t->flag & T_MODAL) {
1396                         t->gizmo_flag = v3d->gizmo_flag;
1397                         v3d->gizmo_flag = V3D_GIZMO_HIDE;
1398                 }
1399
1400                 if (t->scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) {
1401                         t->flag |= T_V3D_ALIGN;
1402                 }
1403                 t->around = t->scene->toolsettings->transform_pivot_point;
1404
1405                 /* bend always uses the cursor */
1406                 if (t->mode == TFM_BEND) {
1407                         t->around = V3D_AROUND_CURSOR;
1408                 }
1409
1410                 TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
1411                 t->orientation.user = orient_slot->type;
1412                 t->orientation.custom = BKE_scene_transform_orientation_find(t->scene, orient_slot->index_custom);
1413
1414                 t->orientation.index = 0;
1415                 ARRAY_SET_ITEMS(
1416                         t->orientation.types,
1417                         &t->orientation.user,
1418                         NULL);
1419
1420                 /* Make second orientation local if both are global. */
1421                 if (t->orientation.user == V3D_MANIP_GLOBAL) {
1422                         t->orientation.user_alt = V3D_MANIP_LOCAL;
1423                         t->orientation.types[0] = &t->orientation.user_alt;
1424                         SWAP(short *, t->orientation.types[0], t->orientation.types[1]);
1425                 }
1426
1427                 /* exceptional case */
1428                 if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
1429                         if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
1430                                 const bool use_island = transdata_check_local_islands(t, t->around);
1431
1432                                 if ((t->obedit_type != -1) && !use_island) {
1433                                         t->options |= CTX_NO_PET;
1434                                 }
1435                         }
1436                 }
1437
1438                 if (object_mode & OB_MODE_ALL_PAINT) {
1439                         Paint *p = BKE_paint_get_active_from_context(C);
1440                         if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
1441                                 t->options |= CTX_PAINT_CURVE;
1442                         }
1443                 }
1444
1445                 /* initialize UV transform from */
1446                 if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) {
1447                         if (RNA_property_is_set(op->ptr, prop)) {
1448                                 if (RNA_property_boolean_get(op->ptr, prop)) {
1449                                         t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
1450                                 }
1451                                 else {
1452                                         t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT;
1453                                 }
1454                         }
1455                         else {
1456                                 RNA_property_boolean_set(op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
1457                         }
1458                 }
1459
1460         }
1461         else if (t->spacetype == SPACE_IMAGE) {
1462                 SpaceImage *sima = sa->spacedata.first;
1463                 // XXX for now, get View2D from the active region
1464                 t->view = &ar->v2d;
1465                 t->around = sima->around;
1466
1467                 if (ED_space_image_show_uvedit(sima, OBACT(t->view_layer))) {
1468                         /* UV transform */
1469                 }
1470                 else if (sima->mode == SI_MODE_MASK) {
1471                         t->options |= CTX_MASK;
1472                 }
1473                 else if (sima->mode == SI_MODE_PAINT) {
1474                         Paint *p = &sce->toolsettings->imapaint.paint;
1475                         if (p->brush && (p->brush->flag & BRUSH_CURVE)) {
1476                                 t->options |= CTX_PAINT_CURVE;
1477                         }
1478                 }
1479                 /* image not in uv edit, nor in mask mode, can happen for some tools */
1480         }
1481         else if (t->spacetype == SPACE_NODE) {
1482                 // XXX for now, get View2D from the active region
1483                 t->view = &ar->v2d;
1484                 t->around = V3D_AROUND_CENTER_BOUNDS;
1485         }
1486         else if (t->spacetype == SPACE_IPO) {
1487                 SpaceIpo *sipo = sa->spacedata.first;
1488                 t->view = &ar->v2d;
1489                 t->around = sipo->around;
1490         }
1491         else if (t->spacetype == SPACE_CLIP) {
1492                 SpaceClip *sclip = sa->spacedata.first;
1493                 t->view = &ar->v2d;
1494                 t->around = sclip->around;
1495
1496                 if (ED_space_clip_check_show_trackedit(sclip))
1497                         t->options |= CTX_MOVIECLIP;
1498                 else if (ED_space_clip_check_show_maskedit(sclip))
1499                         t->options |= CTX_MASK;
1500         }
1501         else {
1502                 if (ar) {
1503                         // XXX for now, get View2D  from the active region
1504                         t->view = &ar->v2d;
1505                         // XXX for now, the center point is the midpoint of the data
1506                 }
1507                 else {
1508                         t->view = NULL;
1509                 }
1510                 t->around = V3D_AROUND_CENTER_BOUNDS;
1511         }
1512
1513         if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_matrix")) &&
1514                    RNA_property_is_set(op->ptr, prop)))
1515         {
1516                 RNA_property_float_get_array(op->ptr, prop, &t->spacemtx[0][0]);
1517                 t->orientation.user = V3D_MANIP_CUSTOM_MATRIX;
1518                 t->orientation.custom = 0;
1519         }
1520         else if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) &&
1521                         RNA_property_is_set(op->ptr, prop)))
1522         {
1523                 short orientation = RNA_property_enum_get(op->ptr, prop);
1524                 TransformOrientation *custom_orientation = NULL;
1525
1526                 if (orientation >= V3D_MANIP_CUSTOM) {
1527                         if (orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) {
1528                                 orientation = V3D_MANIP_GLOBAL;
1529                         }
1530                         else {
1531                                 custom_orientation = BKE_scene_transform_orientation_find(
1532                                         t->scene, orientation - V3D_MANIP_CUSTOM);
1533                                 orientation = V3D_MANIP_CUSTOM;
1534                         }
1535                 }
1536
1537                 t->orientation.user = orientation;
1538                 t->orientation.custom = custom_orientation;
1539         }
1540
1541         if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
1542                    RNA_property_is_set(op->ptr, prop)))
1543         {
1544                 if (RNA_property_boolean_get(op->ptr, prop)) {
1545                         t->flag |= T_RELEASE_CONFIRM;
1546                 }
1547         }
1548         else {
1549                 if (U.flag & USER_RELEASECONFIRM) {
1550                         t->flag |= T_RELEASE_CONFIRM;
1551                 }
1552         }
1553
1554         if (op && ((prop = RNA_struct_find_property(op->ptr, "mirror")) &&
1555                    RNA_property_is_set(op->ptr, prop)))
1556         {
1557                 if (!RNA_property_boolean_get(op->ptr, prop)) {
1558                         t->flag |= T_NO_MIRROR;
1559                 }
1560         }
1561         else if ((t->spacetype == SPACE_VIEW3D) && (t->obedit_type == OB_MESH)) {
1562                 /* pass */
1563         }
1564         else {
1565                 /* Avoid mirroring for unsupported contexts. */
1566                 t->options |= CTX_NO_MIRROR;
1567         }
1568
1569         /* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */
1570         if (op && (prop = RNA_struct_find_property(op->ptr, "proportional"))) {
1571                 if (RNA_property_is_set(op->ptr, prop)) {
1572                         t->flag |= initTransInfo_edit_pet_to_flag(RNA_property_enum_get(op->ptr, prop));
1573                 }
1574                 else {
1575                         /* use settings from scene only if modal */
1576                         if (t->flag & T_MODAL) {
1577                                 if ((t->options & CTX_NO_PET) == 0) {
1578                                         if (t->spacetype == SPACE_IPO) {
1579                                                 t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_fcurve);
1580                                         }
1581                                         else if (t->spacetype == SPACE_ACTION) {
1582                                                 t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action);
1583                                         }
1584                                         else if (t->obedit_type != -1) {
1585                                                 t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
1586                                         }
1587                                         else if (t->options & CTX_GPENCIL_STROKES) {
1588                                                 t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
1589                                         }
1590                                         else if (t->options & CTX_MASK) {
1591                                                 if (ts->proportional_mask) {
1592                                                         t->flag |= T_PROP_EDIT;
1593
1594                                                         if (ts->proportional == PROP_EDIT_CONNECTED) {
1595                                                                 t->flag |= T_PROP_CONNECTED;
1596                                                         }
1597                                                 }
1598                                         }
1599                                         else if ((t->obedit_type == -1) && ts->proportional_objects) {
1600                                                 t->flag |= T_PROP_EDIT;
1601                                         }
1602                                 }
1603                         }
1604                 }
1605
1606                 if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
1607                            RNA_property_is_set(op->ptr, prop)))
1608                 {
1609                         t->prop_size = RNA_property_float_get(op->ptr, prop);
1610                 }
1611                 else {
1612                         t->prop_size = ts->proportional_size;
1613                 }
1614
1615
1616                 /* TRANSFORM_FIX_ME rna restrictions */
1617                 if (t->prop_size <= 0.00001f) {
1618                         printf("Proportional size (%f) under 0.00001, resetting to 1!\n", t->prop_size);
1619                         t->prop_size = 1.0f;
1620                 }
1621
1622                 if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
1623                            RNA_property_is_set(op->ptr, prop)))
1624                 {
1625                         t->prop_mode = RNA_property_enum_get(op->ptr, prop);
1626                 }
1627                 else {
1628                         t->prop_mode = ts->prop_mode;
1629                 }
1630         }
1631         else { /* add not pet option to context when not available */
1632                 t->options |= CTX_NO_PET;
1633         }
1634
1635         // Mirror is not supported with PET, turn it off.
1636 #if 0
1637         if (t->flag & T_PROP_EDIT) {
1638                 t->flag &= ~T_MIRROR;
1639         }
1640 #endif
1641
1642         setTransformViewAspect(t, t->aspect);
1643
1644         if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) && RNA_property_is_set(op->ptr, prop)) {
1645                 RNA_property_float_get_array(op->ptr, prop, t->center_global);
1646                 mul_v3_v3(t->center_global, t->aspect);
1647                 t->flag |= T_OVERRIDE_CENTER;
1648         }
1649
1650         setTransformViewMatrices(t);
1651         initNumInput(&t->num);
1652 }
1653
1654
1655 static void freeTransCustomData(
1656         TransInfo *t, TransDataContainer *tc,
1657         TransCustomData *custom_data)
1658 {
1659         if (custom_data->free_cb) {
1660                 /* Can take over freeing t->data and data_2d etc... */
1661                 custom_data->free_cb(t, tc, custom_data);
1662                 BLI_assert(custom_data->data == NULL);
1663         }
1664         else if ((custom_data->data != NULL) && custom_data->use_free) {
1665                 MEM_freeN(custom_data->data);
1666                 custom_data->data = NULL;
1667         }
1668         /* In case modes are switched in the same transform session. */
1669         custom_data->free_cb = false;
1670         custom_data->use_free = false;
1671 }
1672
1673 static void freeTransCustomDataContainer(TransInfo *t, TransDataContainer *tc, TransCustomDataContainer *tcdc)
1674 {
1675         TransCustomData *custom_data = &tcdc->first_elem;
1676         for (int i = 0; i < TRANS_CUSTOM_DATA_ELEM_MAX; i++, custom_data++) {
1677                 freeTransCustomData(t, tc, custom_data);
1678         }
1679 }
1680
1681 /**
1682  * Needed for mode switching.
1683  */
1684 void freeTransCustomDataForMode(TransInfo *t)
1685 {
1686         freeTransCustomData(t, NULL, &t->custom.mode);
1687         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1688                 freeTransCustomData(t, tc, &tc->custom.mode);
1689         }
1690 }
1691
1692 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
1693 void postTrans(bContext *C, TransInfo *t)
1694 {
1695         if (t->draw_handle_view)
1696                 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_view);
1697         if (t->draw_handle_apply)
1698                 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_apply);
1699         if (t->draw_handle_pixel)
1700                 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_pixel);
1701         if (t->draw_handle_cursor)
1702                 WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
1703
1704         if (t->flag & T_MODAL_CURSOR_SET) {
1705                 WM_cursor_modal_restore(CTX_wm_window(C));
1706         }
1707
1708         /* Free all custom-data */
1709         freeTransCustomDataContainer(t, NULL, &t->custom);
1710         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1711                 freeTransCustomDataContainer(t, tc, &tc->custom);
1712         }
1713
1714         /* postTrans can be called when nothing is selected, so data is NULL already */
1715         if (t->data_len_all != 0) {
1716                 FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1717                         /* free data malloced per trans-data */
1718                         if (ELEM(t->obedit_type, OB_CURVE, OB_SURF) ||
1719                             (t->spacetype == SPACE_IPO))
1720                         {
1721                                 TransData *td = tc->data;
1722                                 for (int a = 0; a < tc->data_len; a++, td++) {
1723                                         if (td->flag & TD_BEZTRIPLE) {
1724                                                 MEM_freeN(td->hdata);
1725                                         }
1726                                 }
1727                         }
1728                         MEM_freeN(tc->data);
1729
1730                         MEM_SAFE_FREE(tc->data_ext);
1731                         MEM_SAFE_FREE(tc->data_2d);
1732                 }
1733         }
1734
1735         MEM_SAFE_FREE(t->data_container);
1736         t->data_container = NULL;
1737
1738         BLI_freelistN(&t->tsnap.points);
1739
1740         if (t->spacetype == SPACE_IMAGE) {
1741                 if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
1742                         /* pass */
1743                 }
1744                 else {
1745                         SpaceImage *sima = t->sa->spacedata.first;
1746                         if (sima->flag & SI_LIVE_UNWRAP)
1747                                 ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL);
1748                 }
1749         }
1750         else if (t->spacetype == SPACE_VIEW3D) {
1751                 View3D *v3d = t->sa->spacedata.first;
1752                 /* restore gizmo */
1753                 if (t->flag & T_MODAL) {
1754                         v3d->gizmo_flag = t->gizmo_flag;
1755                 }
1756         }
1757
1758         if (t->mouse.data) {
1759                 MEM_freeN(t->mouse.data);
1760         }
1761
1762         if (t->rng != NULL) {
1763                 BLI_rng_free(t->rng);
1764         }
1765
1766         freeSnapping(t);
1767 }
1768
1769 void applyTransObjects(TransInfo *t)
1770 {
1771         TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
1772
1773         TransData *td;
1774
1775         for (td = tc->data; td < tc->data + tc->data_len; td++) {
1776                 copy_v3_v3(td->iloc, td->loc);
1777                 if (td->ext->rot) {
1778                         copy_v3_v3(td->ext->irot, td->ext->rot);
1779                 }
1780                 if (td->ext->size) {
1781                         copy_v3_v3(td->ext->isize, td->ext->size);
1782                 }
1783         }
1784         recalcData(t);
1785 }
1786
1787 static void restoreElement(TransData *td)
1788 {
1789         /* TransData for crease has no loc */
1790         if (td->loc) {
1791                 copy_v3_v3(td->loc, td->iloc);
1792         }
1793         if (td->val) {
1794                 *td->val = td->ival;
1795         }
1796
1797         if (td->ext && (td->flag & TD_NO_EXT) == 0) {
1798                 if (td->ext->rot) {
1799                         copy_v3_v3(td->ext->rot, td->ext->irot);
1800                 }
1801                 if (td->ext->rotAngle) {
1802                         *td->ext->rotAngle = td->ext->irotAngle;
1803                 }
1804                 if (td->ext->rotAxis) {
1805                         copy_v3_v3(td->ext->rotAxis, td->ext->irotAxis);
1806                 }
1807                 /* XXX, drotAngle & drotAxis not used yet */
1808                 if (td->ext->size) {
1809                         copy_v3_v3(td->ext->size, td->ext->isize);
1810                 }
1811                 if (td->ext->quat) {
1812                         copy_qt_qt(td->ext->quat, td->ext->iquat);
1813                 }
1814         }
1815
1816         if (td->flag & TD_BEZTRIPLE) {
1817                 *(td->hdata->h1) = td->hdata->ih1;
1818                 *(td->hdata->h2) = td->hdata->ih2;
1819         }
1820 }
1821
1822 void restoreTransObjects(TransInfo *t)
1823 {
1824         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1825
1826                 TransData *td;
1827                 TransData2D *td2d;
1828
1829                 for (td = tc->data; td < tc->data + tc->data_len; td++) {
1830                         restoreElement(td);
1831                 }
1832
1833                 for (td2d = tc->data_2d; tc->data_2d && td2d < tc->data_2d + tc->data_len; td2d++) {
1834                         if (td2d->h1) {
1835                                 td2d->h1[0] = td2d->ih1[0];
1836                                 td2d->h1[1] = td2d->ih1[1];
1837                         }
1838                         if (td2d->h2) {
1839                                 td2d->h2[0] = td2d->ih2[0];
1840                                 td2d->h2[1] = td2d->ih2[1];
1841                         }
1842                 }
1843
1844                 unit_m3(t->mat);
1845
1846         }
1847
1848         recalcData(t);
1849 }
1850
1851 void calculateCenter2D(TransInfo *t)
1852 {
1853         BLI_assert(!is_zero_v3(t->aspect));
1854         projectFloatView(t, t->center_global, t->center2d);
1855 }
1856
1857 void calculateCenterLocal(
1858         TransInfo *t, const float center_global[3])
1859 {
1860         /* setting constraint center */
1861         /* note, init functions may over-ride t->center */
1862         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1863                 if (tc->use_local_mat) {
1864                         mul_v3_m4v3(tc->center_local, tc->imat, center_global);
1865                 }
1866                 else {
1867                         copy_v3_v3(tc->center_local, center_global);
1868                 }
1869         }
1870 }
1871
1872 void calculateCenterCursor(TransInfo *t, float r_center[3])
1873 {
1874         const float *cursor = t->scene->cursor.location;
1875         copy_v3_v3(r_center, cursor);
1876
1877         /* If edit or pose mode, move cursor in local space */
1878         if (t->options & CTX_PAINT_CURVE) {
1879                 if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
1880                         r_center[0] = t->ar->winx / 2.0f;
1881                         r_center[1] = t->ar->winy / 2.0f;
1882                 }
1883                 r_center[2] = 0.0f;
1884         }
1885 }
1886
1887 void calculateCenterCursor2D(TransInfo *t, float r_center[2])
1888 {
1889         const float *cursor = NULL;
1890
1891         if (t->spacetype == SPACE_IMAGE) {
1892                 SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
1893                 cursor = sima->cursor;
1894         }
1895         else if (t->spacetype == SPACE_CLIP) {
1896                 SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
1897                 cursor = space_clip->cursor;
1898         }
1899
1900         if (cursor) {
1901                 if (t->options & CTX_MASK) {
1902                         float co[2];
1903
1904                         if (t->spacetype == SPACE_IMAGE) {
1905                                 SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
1906                                 BKE_mask_coord_from_image(sima->image, &sima->iuser, co, cursor);
1907                         }
1908                         else if (t->spacetype == SPACE_CLIP) {
1909                                 SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
1910                                 BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor);
1911                         }
1912                         else {
1913                                 BLI_assert(!"Shall not happen");
1914                         }
1915
1916                         r_center[0] = co[0] * t->aspect[0];
1917                         r_center[1] = co[1] * t->aspect[1];
1918                 }
1919                 else if (t->options & CTX_PAINT_CURVE) {
1920                         if (t->spacetype == SPACE_IMAGE) {
1921                                 r_center[0] = UI_view2d_view_to_region_x(&t->ar->v2d, cursor[0]);
1922                                 r_center[1] = UI_view2d_view_to_region_y(&t->ar->v2d, cursor[1]);
1923                         }
1924                 }
1925                 else {
1926                         r_center[0] = cursor[0] * t->aspect[0];
1927                         r_center[1] = cursor[1] * t->aspect[1];
1928                 }
1929         }
1930 }
1931
1932 void calculateCenterCursorGraph2D(TransInfo *t, float r_center[2])
1933 {
1934         SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
1935         Scene *scene = t->scene;
1936
1937         /* cursor is combination of current frame, and graph-editor cursor value */
1938         if (sipo->mode == SIPO_MODE_DRIVERS) {
1939                 r_center[0] = sipo->cursorTime;
1940                 r_center[1] = sipo->cursorVal;
1941         }
1942         else {
1943                 r_center[0] = (float)(scene->r.cfra);
1944                 r_center[1] = sipo->cursorVal;
1945         }
1946 }
1947
1948 void calculateCenterMedian(TransInfo *t, float r_center[3])
1949 {
1950         float partial[3] = {0.0f, 0.0f, 0.0f};
1951         int total = 0;
1952
1953         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1954                 for (int i = 0; i < tc->data_len; i++) {
1955                         if (tc->data[i].flag & TD_SELECTED) {
1956                                 if (!(tc->data[i].flag & TD_NOCENTER)) {
1957                                         if (tc->use_local_mat) {
1958                                                 float v[3];
1959                                                 mul_v3_m4v3(v, tc->mat, tc->data[i].center);
1960                                                 add_v3_v3(partial, v);
1961                                         }
1962                                         else {
1963                                                 add_v3_v3(partial, tc->data[i].center);
1964                                         }
1965                                         total++;
1966                                 }
1967                         }
1968                 }
1969         }
1970         if (total) {
1971                 mul_v3_fl(partial, 1.0f / (float)total);
1972         }
1973         copy_v3_v3(r_center, partial);
1974 }
1975
1976 void calculateCenterBound(TransInfo *t, float r_center[3])
1977 {
1978         float max[3], min[3];
1979         bool changed = false;
1980         INIT_MINMAX(min, max);
1981         FOREACH_TRANS_DATA_CONTAINER (t, tc) {
1982                 for (int i = 0; i < tc->data_len; i++) {
1983                         if (tc->data[i].flag & TD_SELECTED) {
1984                                 if (!(tc->data[i].flag & TD_NOCENTER)) {
1985                                         if (tc->use_local_mat) {
1986                                                 float v[3];
1987                                                 mul_v3_m4v3(v, tc->mat, tc->data[i].center);
1988                                                 minmax_v3v3_v3(min, max, v);
1989                                         }
1990                                         else {
1991                                                 minmax_v3v3_v3(min, max, tc->data[i].center);
1992                                         }
1993                                         changed = true;
1994                                 }
1995                         }
1996                 }
1997         }
1998         if (changed) {
1999                 mid_v3_v3v3(r_center, min, max);
2000         }
2001 }
2002
2003 /**
2004  * \param select_only: only get active center from data being transformed.
2005  */
2006 bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
2007 {
2008         TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
2009
2010         if (t->spacetype != SPACE_VIEW3D) {
2011                 return false;
2012         }
2013         else if (tc->obedit) {
2014                 if (ED_object_calc_active_center_for_editmode(tc->obedit, select_only, r_center)) {
2015                         mul_m4_v3(tc->obedit->obmat, r_center);
2016                         return true;
2017                 }
2018         }
2019         else if (t->flag & T_POSE) {
2020                 ViewLayer *view_layer = t->view_layer;
2021                 Object *ob = OBACT(view_layer) ;
2022                 if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
2023                         mul_m4_v3(ob->obmat, r_center);
2024                         return true;
2025                 }
2026         }
2027         else if (t->options & CTX_PAINT_CURVE) {
2028                 Paint *p = BKE_paint_get_active(t->scene, t->view_layer);
2029                 Brush *br = p->brush;
2030                 PaintCurve *pc = br->paint_curve;
2031                 copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
2032                 r_center[2] = 0.0f;
2033                 return true;
2034         }
2035         else {
2036                 /* object mode */
2037                 ViewLayer *view_layer = t->view_layer;
2038                 Object *ob = OBACT(view_layer);
2039                 Base *base = BASACT(view_layer);
2040                 if (ob && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) {
2041                         copy_v3_v3(r_center, ob->obmat[3]);
2042                         return true;
2043                 }
2044         }
2045
2046         return false;
2047 }
2048
2049 static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[3])
2050 {
2051         switch (around) {
2052                 case V3D_AROUND_CENTER_BOUNDS:
2053                         calculateCenterBound(t, r_center);
2054                         break;
2055                 case V3D_AROUND_CENTER_MEDIAN:
2056                         calculateCenterMedian(t, r_center);
2057                         break;
2058                 case V3D_AROUND_CURSOR:
2059                         if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP))
2060                                 calculateCenterCursor2D(t, r_center);
2061                         else if (t->spacetype == SPACE_IPO)
2062                                 calculateCenterCursorGraph2D(t, r_center);
2063                         else
2064                                 calculateCenterCursor(t, r_center);
2065                         break;
2066                 case V3D_AROUND_LOCAL_ORIGINS:
2067                         /* Individual element center uses median center for helpline and such */
2068                         calculateCenterMedian(t, r_center);
2069                         break;
2070                 case V3D_AROUND_ACTIVE:
2071                 {
2072                         if (calculateCenterActive(t, false, r_center)) {
2073                                 /* pass */
2074                         }
2075                         else {
2076                                 /* fallback */
2077                                 calculateCenterMedian(t, r_center);
2078                         }
2079                         break;
2080                 }
2081         }
2082 }
2083
2084 void calculateCenter(TransInfo *t)
2085 {
2086         if ((t->flag & T_OVERRIDE_CENTER) == 0) {
2087                 calculateCenter_FromAround(t, t->around, t->center_global);
2088         }
2089         calculateCenterLocal(t, t->center_global);
2090
2091         /* avoid calculating again */
2092         {
2093                 TransCenterData *cd = &t->center_cache[t->around];
2094                 copy_v3_v3(cd->global, t->center_global);
2095                 cd->is_set = true;
2096         }
2097
2098         calculateCenter2D(t);
2099
2100         /* for panning from cameraview */
2101         if ((t->flag & T_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) {
2102                 if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
2103
2104                         if (t->flag & T_CAMERA) {
2105                                 float axis[3];
2106                                 /* persinv is nasty, use viewinv instead, always right */
2107                                 copy_v3_v3(axis, t->viewinv[2]);
2108                                 normalize_v3(axis);
2109
2110                                 /* 6.0 = 6 grid units */
2111                                 axis[0] = t->center_global[0] - 6.0f * axis[0];
2112                                 axis[1] = t->center_global[1] - 6.0f * axis[1];
2113                                 axis[2] = t->center_global[2] - 6.0f * axis[2];
2114
2115                                 projectFloatView(t, axis, t->center2d);
2116
2117                                 /* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
2118                                 if (t->mode == TFM_TRANSLATION) {
2119                                         copy_v3_v3(t->center_global, axis);
2120                                 }
2121                         }
2122                 }
2123         }
2124
2125         if (t->spacetype == SPACE_VIEW3D) {
2126                 /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, used in ED_view3d_win_to_delta() */
2127
2128                 /* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW
2129                  * and never used in other cases.
2130                  *
2131                  * We need special case here as well, since ED_view3d_calc_zfac will crash when called
2132                  * for a region different from RGN_TYPE_WINDOW.
2133                  */
2134                 if (t->ar->regiontype == RGN_TYPE_WINDOW) {
2135                         t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, t->center_global, NULL);
2136                 }
2137                 else {
2138                         t->zfac = 0.0f;
2139                 }
2140         }
2141 }
2142
2143 BLI_STATIC_ASSERT(ARRAY_SIZE(((TransInfo *)NULL)->center_cache) == (V3D_AROUND_ACTIVE + 1), "test size");
2144
2145 /**
2146  * Lazy initialize transform center data, when we need to access center values from other types.
2147  */
2148 const TransCenterData *transformCenter_from_type(TransInfo *t, int around)
2149 {
2150         BLI_assert(around <= V3D_AROUND_ACTIVE);
2151         TransCenterData *cd = &t->center_cache[around];
2152         if (cd->is_set == false) {
2153                 calculateCenter_FromAround(t, around, cd->global);
2154                 cd->is_set = true;
2155         }
2156         return cd;
2157 }
2158
2159 void calculatePropRatio(TransInfo *t)
2160 {
2161         int i;
2162         float dist;
2163         const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
2164
2165         t->proptext[0] = '\0';
2166
2167         if (t->flag & T_PROP_EDIT) {
2168                 const char *pet_id = NULL;
2169                 FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2170                         TransData *td = tc->data;
2171                         for (i = 0; i < tc->data_len; i++, td++) {
2172                                 if (td->flag & TD_SELECTED) {
2173                                         td->factor = 1.0f;
2174                                 }
2175                                 else if (tc->mirror.axis_flag && (td->loc[0] * tc->mirror.sign) < -0.00001f) {
2176                                         td->flag |= TD_SKIP;
2177                                         td->factor = 0.0f;
2178                                         restoreElement(td);
2179                                 }
2180                                 else if ((connected && (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size)) ||
2181                                          (connected == 0 && td->rdist > t->prop_size))
2182                                 {
2183                                         /*
2184                                          * The elements are sorted according to their dist member in the array,
2185                                          * that means we can stop when it finds one element outside of the propsize.
2186                                          * do not set 'td->flag |= TD_NOACTION', the prop circle is being changed.
2187                                          */
2188
2189                                         td->factor = 0.0f;
2190                                         restoreElement(td);
2191                                 }
2192                                 else {
2193                                         /* Use rdist for falloff calculations, it is the real distance */
2194                                         td->flag &= ~TD_NOACTION;
2195
2196                                         if (connected)
2197                                                 dist = (t->prop_size - td->dist) / t->prop_size;
2198                                         else
2199                                                 dist = (t->prop_size - td->rdist) / t->prop_size;
2200
2201                                         /*
2202                                          * Clamp to positive numbers.
2203                                          * Certain corner cases with connectivity and individual centers
2204                                          * can give values of rdist larger than propsize.
2205                                          */
2206                                         if (dist < 0.0f)
2207                                                 dist = 0.0f;
2208
2209                                         switch (t->prop_mode) {
2210                                                 case PROP_SHARP:
2211                                                         td->factor = dist * dist;
2212                                                         break;
2213                                                 case PROP_SMOOTH:
2214                                                         td->factor = 3.0f * dist * dist - 2.0f * dist * dist * dist;
2215                                                         break;
2216                                                 case PROP_ROOT:
2217                                                         td->factor = sqrtf(dist);
2218                                                         break;
2219                                                 case PROP_LIN:
2220                                                         td->factor = dist;
2221                                                         break;
2222                                                 case PROP_CONST:
2223                                                         td->factor = 1.0f;
2224                                                         break;
2225                                                 case PROP_SPHERE:
2226                                                         td->factor = sqrtf(2 * dist - dist * dist);
2227                                                         break;
2228                                                 case PROP_RANDOM:
2229                                                         if (t->rng == NULL) {
2230                                                                 /* Lazy initialization. */
2231                                                                 uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
2232                                                                 t->rng = BLI_rng_new(rng_seed);
2233                                                         }
2234                                                         td->factor = BLI_rng_get_float(t->rng) * dist;
2235                                                         break;
2236                                                 case PROP_INVSQUARE:
2237                                                         td->factor = dist * (2.0f - dist);
2238                                                         break;
2239                                                 default:
2240                                                         td->factor = 1;
2241                                                         break;
2242                                         }
2243                                 }
2244                         }
2245                 }
2246
2247                 switch (t->prop_mode) {
2248                         case PROP_SHARP:
2249                                 pet_id = N_("(Sharp)");
2250                                 break;
2251                         case PROP_SMOOTH:
2252                                 pet_id = N_("(Smooth)");
2253                                 break;
2254                         case PROP_ROOT:
2255                                 pet_id = N_("(Root)");
2256                                 break;
2257                         case PROP_LIN:
2258                                 pet_id = N_("(Linear)");
2259                                 break;
2260                         case PROP_CONST:
2261                                 pet_id = N_("(Constant)");
2262                                 break;
2263                         case PROP_SPHERE:
2264                                 pet_id = N_("(Sphere)");
2265                                 break;
2266                         case PROP_RANDOM:
2267                                 pet_id = N_("(Random)");
2268                                 break;
2269                         case PROP_INVSQUARE:
2270                                 pet_id = N_("(InvSquare)");
2271                                 break;
2272                         default:
2273                                 break;
2274                 }
2275
2276                 if (pet_id) {
2277                         BLI_strncpy(t->proptext, IFACE_(pet_id), sizeof(t->proptext));
2278                 }
2279         }
2280         else {
2281                 FOREACH_TRANS_DATA_CONTAINER (t, tc) {
2282                         TransData *td = tc->data;
2283                         for (i = 0; i < tc->data_len; i++, td++) {
2284                                 td->factor = 1.0;
2285                         }
2286                 }
2287         }
2288 }
2289
2290 /**
2291  * Rotate an element, low level code, ignore protected channels.
2292  * (use for objects or pose-bones)
2293  * Similar to #ElementRotation.
2294  */
2295 void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot)
2296 {
2297         float totmat[3][3];
2298         float smat[3][3];
2299         float fmat[3][3];
2300         float obmat[3][3];
2301
2302         float dmat[3][3];  /* delta rotation */
2303         float dmat_inv[3][3];
2304
2305         mul_m3_m3m3(totmat, mat, td->mtx);
2306         mul_m3_m3m3(smat, td->smtx, mat);
2307
2308         /* logic from BKE_object_rot_to_mat3 */
2309         if (use_drot) {
2310                 if (td->ext->rotOrder > 0) {
2311                         eulO_to_mat3(dmat, td->ext->drot, td->ext->rotOrder);
2312                 }
2313                 else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
2314 #if 0
2315                         axis_angle_to_mat3(dmat, td->ext->drotAxis, td->ext->drotAngle);
2316 #else
2317                         unit_m3(dmat);
2318 #endif
2319                 }
2320                 else {
2321                         float tquat[4];
2322                         normalize_qt_qt(tquat, td->ext->dquat);
2323                         quat_to_mat3(dmat, tquat);
2324                 }
2325
2326                 invert_m3_m3(dmat_inv, dmat);
2327         }
2328
2329
2330         if (td->ext->rotOrder == ROT_MODE_QUAT) {
2331                 float quat[4];
2332
2333                 /* calculate the total rotatation */
2334                 quat_to_mat3(obmat, td->ext->iquat);
2335                 if (use_drot) {
2336                         mul_m3_m3m3(obmat, dmat, obmat);
2337                 }
2338
2339                 /* mat = transform, obmat = object rotation */
2340                 mul_m3_m3m3(fmat, smat, obmat);
2341
2342                 if (use_drot) {
2343                         mul_m3_m3m3(fmat, dmat_inv, fmat);
2344                 }
2345
2346                 mat3_to_quat(quat, fmat);
2347
2348                 /* apply */
2349                 copy_qt_qt(td->ext->quat, quat);
2350         }
2351         else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
2352                 float axis[3], angle;
2353
2354                 /* calculate the total rotatation */
2355                 axis_angle_to_mat3(obmat, td->ext->irotAxis, td->ext->irotAngle);
2356                 if (use_drot) {
2357                         mul_m3_m3m3(obmat, dmat, obmat);
2358                 }
2359
2360                 /* mat = transform, obmat = object rotation */
2361                 mul_m3_m3m3(fmat, smat, obmat);
2362
2363                 if (use_drot) {
2364                         mul_m3_m3m3(fmat, dmat_inv, fmat);
2365                 }
2366
2367                 mat3_to_axis_angle(axis, &angle, fmat);
2368
2369                 /* apply */
2370                 copy_v3_v3(td->ext->rotAxis, axis);
2371                 *td->ext->rotAngle = angle;
2372         }
2373         else {
2374                 float eul[3];
2375
2376                 /* calculate the total rotatation */
2377                 eulO_to_mat3(obmat, td->ext->irot, td->ext->rotOrder);
2378                 if (use_drot) {
2379                         mul_m3_m3m3(obmat, dmat, obmat);
2380                 }
2381
2382                 /* mat = transform, obmat = object rotation */
2383                 mul_m3_m3m3(fmat, smat, obmat);
2384
2385                 if (use_drot) {
2386                         mul_m3_m3m3(fmat, dmat_inv, fmat);
2387                 }
2388
2389                 mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
2390
2391                 /* apply */
2392                 copy_v3_v3(td->ext->rot, eul);
2393         }
2394 }