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