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