1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup edtransform
22  */
23 
24 #pragma once
25 
26 #include "ED_numinput.h"
27 #include "ED_transform.h"
28 #include "ED_view3d.h"
29 
30 #include "RE_engine.h"
31 
32 #include "DNA_listBase.h"
33 #include "DNA_object_enums.h"
34 
35 #include "DEG_depsgraph.h"
36 
37 #include "transform_data.h"
38 
39 /* ************************** Types ***************************** */
40 
41 struct ARegion;
42 struct Depsgraph;
43 struct NumInput;
44 struct Object;
45 struct RNG;
46 struct ReportList;
47 struct Scene;
48 struct ScrArea;
49 struct SnapObjectContext;
50 struct TransDataContainer;
51 struct TransInfo;
52 struct TransSnap;
53 struct TransformOrientation;
54 struct ViewLayer;
55 struct bContext;
56 struct wmEvent;
57 struct wmKeyConfig;
58 struct wmKeyMap;
59 struct wmTimer;
60 
61 /* transinfo->redraw */
62 typedef enum {
63   TREDRAW_NOTHING = 0,
64   TREDRAW_HARD = 1,
65   TREDRAW_SOFT = 2,
66 } eRedrawFlag;
67 
68 typedef struct TransSnapPoint {
69   struct TransSnapPoint *next, *prev;
70   float co[3];
71 } TransSnapPoint;
72 
73 typedef struct TransSnap {
74   short mode;
75   short target;
76   short modePoint;
77   short modeSelect;
78   bool align;
79   bool project;
80   bool snap_self;
81   bool peel;
82   bool use_backface_culling;
83   char status;
84   /* Snapped Element Type (currently for objects only). */
85   char snapElem;
86   /** snapping from this point (in global-space). */
87   float snapPoint[3];
88   /** to this point (in global-space). */
89   float snapTarget[3];
90   float snapNormal[3];
91   char snapNodeBorder;
92   ListBase points;
93   TransSnapPoint *selectedPoint;
94   double last;
95   void (*applySnap)(struct TransInfo *, float *);
96   void (*calcSnap)(struct TransInfo *, float *);
97   void (*targetSnap)(struct TransInfo *);
98   /**
99    * Get the transform distance between two points (used by Closest snap)
100    *
101    * \note Return value can be anything,
102    * where the smallest absolute value defines what's closest.
103    */
104   float (*distance)(struct TransInfo *t, const float p1[3], const float p2[3]);
105 
106   /**
107    * Re-usable snap context data.
108    */
109   struct SnapObjectContext *object_context;
110 } TransSnap;
111 
112 typedef struct TransCon {
113   /** Description of the constraint for header_print. */
114   char text[50];
115   /** Projection constraint matrix (same as #imtx with some axis == 0). */
116   float pmtx[3][3];
117   /** Initial mouse value for visual calculation
118    * the one in #TransInfo is not guarantee to stay the same (Rotates change it). */
119   int imval[2];
120   /** Mode flags of the constraint. */
121   int mode;
122   void (*drawExtra)(struct TransInfo *t);
123 
124   /* Note: if 'tc' is NULL, 'td' must also be NULL.
125    * For constraints that needs to draw differently from the other
126    * uses this instead of the generic draw function. */
127 
128   /** Apply function pointer for linear vectorial transformation
129    * The last three parameters are pointers to the in/out/printable vectors. */
130   void (*applyVec)(struct TransInfo *t,
131                    struct TransDataContainer *tc,
132                    struct TransData *td,
133                    const float in[3],
134                    float out[3]);
135   /** Apply function pointer for size transformation. */
136   void (*applySize)(struct TransInfo *t,
137                     struct TransDataContainer *tc,
138                     struct TransData *td,
139                     float smat[3][3]);
140   /** Apply function pointer for rotation transformation */
141   void (*applyRot)(struct TransInfo *t,
142                    struct TransDataContainer *tc,
143                    struct TransData *td,
144                    float vec[3],
145                    float *angle);
146 } TransCon;
147 
148 typedef struct MouseInput {
149   void (*apply)(struct TransInfo *t, struct MouseInput *mi, const double mval[2], float output[3]);
150   void (*post)(struct TransInfo *t, float values[3]);
151 
152   /** Initial mouse position. */
153   int imval[2];
154   bool precision;
155   float precision_factor;
156   float center[2];
157   float factor;
158   /** Additional data, if needed by the particular function. */
159   void *data;
160 
161   /**
162    * Use virtual cursor, which takes precision into account
163    * keeping track of the cursors 'virtual' location,
164    * to avoid jumping values when its toggled.
165    *
166    * This works well for scaling drag motion,
167    * but not for rotating around a point (rotation needs its own custom accumulator)
168    */
169   bool use_virtual_mval;
170   struct {
171     double prev[2];
172     double accum[2];
173   } virtual_mval;
174 } MouseInput;
175 
176 typedef struct TransCustomData {
177   void *data;
178   void (*free_cb)(struct TransInfo *,
179                   struct TransDataContainer *tc,
180                   struct TransCustomData *custom_data);
181   unsigned int use_free : 1;
182 } TransCustomData;
183 
184 typedef struct TransCenterData {
185   float global[3];
186   unsigned int is_set : 1;
187 } TransCenterData;
188 
189 /**
190  * Rule of thumb for choosing between mode/type:
191  * - If transform mode uses the data, assign to `mode`
192  *   (typically in transform.c).
193  * - If conversion uses the data as an extension to the #TransData, assign to `type`
194  *   (typically in transform_conversion.c).
195  */
196 typedef struct TransCustomDataContainer {
197   /** Owned by the mode (grab, scale, bend... ).*/
198   union {
199     TransCustomData mode, first_elem;
200   };
201   TransCustomData type;
202 } TransCustomDataContainer;
203 #define TRANS_CUSTOM_DATA_ELEM_MAX (sizeof(TransCustomDataContainer) / sizeof(TransCustomData))
204 
205 typedef struct TransDataContainer {
206   /** Transformed data (array). */
207   TransData *data;
208   /** Transformed data extension (array). */
209   TransDataExtension *data_ext;
210   /** Transformed data for 2d (array). */
211   TransData2D *data_2d;
212   /** Transformed data for mirror elements (array). */
213   TransDataMirror *data_mirror;
214 
215   /** Total number of transformed data, data_ext, data_2d. */
216   int data_len;
217   /** Total number of transformed data_mirror. */
218   int data_mirror_len;
219 
220   struct Object *obedit;
221 
222   float mat[4][4];
223   float imat[4][4];
224   /** 3x3 copies of matrices above. */
225   float mat3[3][3];
226   float imat3[3][3];
227 
228   /** Normalized 'mat3' */
229   float mat3_unit[3][3];
230 
231   /** if 't->flag & T_POSE', this denotes pose object */
232   struct Object *poseobj;
233 
234   /** Center of transformation (in local-space), Calculated from #TransInfo.center_global. */
235   float center_local[3];
236 
237   /**
238    * Use for cases we care about the active, eg: active vert of active mesh.
239    * if set this will _always_ be the first item in the array.
240    */
241   bool is_active;
242 
243   /**
244    * Store matrix, this avoids having to have duplicate check all over
245    * Typically: 'obedit->obmat' or 'poseobj->obmat', but may be used elsewhere too.
246    */
247   bool use_local_mat;
248 
249   /**  Mirror option. */
250   union {
251     struct {
252       uint use_mirror_axis_x : 1;
253       uint use_mirror_axis_y : 1;
254       uint use_mirror_axis_z : 1;
255     };
256     /* For easy checking. */
257     char use_mirror_axis_any;
258   };
259 
260   TransCustomDataContainer custom;
261 } TransDataContainer;
262 
263 typedef struct TransInfo {
264   TransDataContainer *data_container;
265   int data_container_len;
266 
267   /** eTransConvertType
268    * TODO: It should be a member of TransDataContainer. */
269   int data_type;
270 
271   /** Combine length of all #TransDataContainer.data_len
272    * Use to check if nothing is selected or if we have a single selection. */
273   int data_len_all;
274 
275   /** Current mode. */
276   int mode;
277   /** Generic flags for special behaviors. */
278   int flag;
279   /** Special modifiers, by function, not key. */
280   int modifiers;
281   /** Current state (running, canceled. */
282   short state;
283   /** Current context/options for transform. */
284   int options;
285   void (*transform)(struct TransInfo *, const int[2]);
286   /** Transform function pointer. */
287   eRedrawFlag (*handleEvent)(struct TransInfo *, const struct wmEvent *);
288   /* event handler function pointer  RETURN 1 if redraw is needed */
289   /** transformed constraint. */
290   TransCon con;
291   TransSnap tsnap;
292   /** numerical input. */
293   NumInput num;
294   /** mouse input. */
295   MouseInput mouse;
296   /** redraw flag. */
297   eRedrawFlag redraw;
298   /** proportional circle radius. */
299   float prop_size;
300   /** proportional falloff text. */
301   char proptext[20];
302   /**
303    * Spaces using non 1:1 aspect, (uv's, f-curve, movie-clip... etc)
304    * use for conversion and snapping.
305    */
306   float aspect[3];
307   /** center of transformation (in global-space) */
308   float center_global[3];
309   /** center in screen coordinates. */
310   float center2d[2];
311   /* Lazy initialize center data for when we need other center values.
312    * V3D_AROUND_ACTIVE + 1 (static assert checks this) */
313   TransCenterData center_cache[5];
314   /** maximum index on the input vector. */
315   short idx_max;
316   /** Snapping Gears. */
317   float snap[2];
318   /** Spatial snapping gears(even when rotating, scaling... etc). */
319   float snap_spatial[2];
320   /** Mouse side of the current frame, 'L', 'R' or 'B' */
321   char frame_side;
322 
323   /** copy from G.vd, prevents feedback. */
324   float viewmat[4][4];
325   /** and to make sure we don't have to. */
326   float viewinv[4][4];
327   /** access G.vd from other space types. */
328   float persmat[4][4];
329   float persinv[4][4];
330   short persp;
331   short around;
332   /** spacetype where transforming is. */
333   char spacetype;
334   /** Choice of custom cursor with or without a help line from the gizmo to the mouse position. */
335   char helpline;
336   /** Avoid looking inside TransDataContainer obedit. */
337   short obedit_type;
338 
339   /** translation, to show for widget. */
340   float vec[3];
341   /** rot/rescale, to show for widget. */
342   float mat[3][3];
343 
344   /** orientation matrix of the current space. */
345   float spacemtx[3][3];
346   float spacemtx_inv[3][3];
347   /** name of the current space, MAX_NAME. */
348   char spacename[64];
349 
350   /*************** NEW STUFF *********************/
351   /** event type used to launch transform. */
352   short launch_event;
353   /** Is the actual launch event a tweak event? (launch_event above is set to the corresponding
354    * mouse button then.) */
355   bool is_launch_event_tweak;
356 
357   struct {
358     short type;
359     float matrix[3][3];
360   } orient[3];
361   short orient_curr;
362 
363   /** backup from view3d, to restore on end. */
364   short gizmo_flag;
365 
366   short prop_mode;
367 
368   /** Value taken as input, either through mouse coordinates or entered as a parameter. */
369   float values[4];
370 
371   /** Offset applied ontop of modal input. */
372   float values_modal_offset[4];
373 
374   /** Final value of the transformation (displayed in the redo panel).
375    * If the operator is executed directly (not modal), this value is usually the
376    * value of the input parameter, except when a constrain is entered. */
377   float values_final[4];
378 
379   /* Axis members for modes that use an axis separate from the orientation (rotate & shear). */
380 
381   /** Primary axis, rotate only uses this. */
382   int orient_axis;
383   /** Secondary axis, shear uses this. */
384   int orient_axis_ortho;
385 
386   /** remove elements if operator is canceled. */
387   bool remove_on_cancel;
388 
389   void *view;
390   /** Only valid (non null) during an operator called function. */
391   struct bContext *context;
392   struct wmMsgBus *mbus;
393   struct ScrArea *area;
394   struct ARegion *region;
395   struct Depsgraph *depsgraph;
396   struct Scene *scene;
397   struct ViewLayer *view_layer;
398   struct ToolSettings *settings;
399   struct wmTimer *animtimer;
400   /** so we can do lookups for header text. */
401   struct wmKeyMap *keymap;
402   /** assign from the operator, or can be NULL. */
403   struct ReportList *reports;
404   /** current mouse position. */
405   int mval[2];
406   /** use for 3d view. */
407   float zfac;
408   void *draw_handle_apply;
409   void *draw_handle_view;
410   void *draw_handle_pixel;
411   void *draw_handle_cursor;
412 
413   /** Currently only used for random curve of proportional editing. */
414   struct RNG *rng;
415 
416   /** Typically for mode settings. */
417   TransCustomDataContainer custom;
418 } TransInfo;
419 
420 /* ******************** Macros & Prototypes *********************** */
421 
422 /* transinfo->state */
423 enum {
424   TRANS_STARTING = 0,
425   TRANS_RUNNING = 1,
426   TRANS_CONFIRM = 2,
427   TRANS_CANCEL = 3,
428 };
429 
430 /* transinfo->flag */
431 enum {
432   T_OBJECT = 1 << 0,
433   /** \note We could remove 'T_EDIT' and use 'obedit_type', for now ensure they're in sync. */
434   T_EDIT = 1 << 1,
435   T_POSE = 1 << 2,
436   T_TEXTURE = 1 << 3,
437   /** Transforming the 3d view. */
438   T_CAMERA = 1 << 4,
439   /** Transforming the 3D cursor. */
440   T_CURSOR = 1 << 5,
441   /** Transform points, having no rotation/scale. */
442   T_POINTS = 1 << 6,
443   /** restrictions flags */
444   T_NO_CONSTRAINT = 1 << 7,
445   T_NULL_ONE = 1 << 8,
446   T_NO_ZERO = 1 << 9,
447   T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO,
448 
449   T_PROP_EDIT = 1 << 10,
450   T_PROP_CONNECTED = 1 << 11,
451   T_PROP_PROJECTED = 1 << 12,
452   T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED,
453 
454   T_V3D_ALIGN = 1 << 13,
455   /** For 2d views like uv or fcurve. */
456   T_2D_EDIT = 1 << 14,
457   T_CLIP_UV = 1 << 15,
458 
459   /** Auto-ik is on. */
460   T_AUTOIK = 1 << 16,
461 
462   /** Don't use mirror even if the data-block option is set. */
463   T_NO_MIRROR = 1 << 17,
464 
465   /** To indicate that the value set in the `value` parameter is the final
466    * value of the transformation, modified only by the constrain. */
467   T_INPUT_IS_VALUES_FINAL = 1 << 18,
468 
469   /** To specify if we save back settings at the end. */
470   T_MODAL = 1 << 19,
471 
472   /** No retopo. */
473   T_NO_PROJECT = 1 << 20,
474 
475   T_RELEASE_CONFIRM = 1 << 21,
476 
477   /** Alternative transformation. used to add offset to tracking markers. */
478   T_ALT_TRANSFORM = 1 << 22,
479 
480   /** #TransInfo.center has been set, don't change it. */
481   T_OVERRIDE_CENTER = 1 << 23,
482 
483   T_MODAL_CURSOR_SET = 1 << 24,
484 
485   T_CLNOR_REBUILD = 1 << 25,
486 
487   /* Special Aftertrans. */
488   T_AUTOMERGE = 1 << 26,
489   T_AUTOSPLIT = 1 << 27,
490 };
491 
492 /** #TransInfo.modifiers */
493 enum {
494   MOD_CONSTRAINT_SELECT = 1 << 0,
495   MOD_PRECISION = 1 << 1,
496   MOD_SNAP = 1 << 2,
497   MOD_SNAP_INVERT = 1 << 3,
498   MOD_CONSTRAINT_PLANE = 1 << 4,
499 };
500 
501 /* use node center for transform instead of upper-left corner.
502  * disabled since it makes absolute snapping not work so nicely
503  */
504 // #define USE_NODE_CENTER
505 
506 /* ******************************************************************************** */
507 
508 /** #TransInfo.helpline */
509 enum {
510   HLP_NONE = 0,
511   HLP_SPRING = 1,
512   HLP_ANGLE = 2,
513   HLP_HARROW = 3,
514   HLP_VARROW = 4,
515   HLP_CARROW = 5,
516   HLP_TRACKBALL = 6,
517 };
518 
519 /** #TransCon.mode, #TransInfo.con.mode */
520 enum {
521   /** When set constraints are in use. */
522   CON_APPLY = 1 << 0,
523   /** These are only used for modal execution. */
524   CON_AXIS0 = 1 << 1,
525   CON_AXIS1 = 1 << 2,
526   CON_AXIS2 = 1 << 3,
527   CON_SELECT = 1 << 4,
528   /** Does not reorient vector to face viewport when on. */
529   CON_NOFLIP = 1 << 5,
530   CON_USER = 1 << 6,
531 };
532 
533 /** #TransSnap.status */
534 enum {
535   SNAP_FORCED = 1 << 0,
536   TARGET_INIT = 1 << 1,
537   POINT_INIT = 1 << 2,
538   MULTI_POINTS = 1 << 3,
539 };
540 
541 /** keymap modal items */
542 /* NOTE: these values are saved in keymap files, do not change then but just add new ones. */
543 enum {
544   TFM_MODAL_CANCEL = 1,
545   TFM_MODAL_CONFIRM = 2,
546   TFM_MODAL_TRANSLATE = 3,
547   TFM_MODAL_ROTATE = 4,
548   TFM_MODAL_RESIZE = 5,
549   TFM_MODAL_SNAP_INV_ON = 6,
550   TFM_MODAL_SNAP_INV_OFF = 7,
551   TFM_MODAL_SNAP_TOGGLE = 8,
552   TFM_MODAL_AXIS_X = 9,
553   TFM_MODAL_AXIS_Y = 10,
554   TFM_MODAL_AXIS_Z = 11,
555   TFM_MODAL_PLANE_X = 12,
556   TFM_MODAL_PLANE_Y = 13,
557   TFM_MODAL_PLANE_Z = 14,
558   TFM_MODAL_CONS_OFF = 15,
559   TFM_MODAL_ADD_SNAP = 16,
560   TFM_MODAL_REMOVE_SNAP = 17,
561 
562   /* 18 and 19 used by numinput, defined in transform.h */
563 
564   TFM_MODAL_PROPSIZE_UP = 20,
565   TFM_MODAL_PROPSIZE_DOWN = 21,
566   TFM_MODAL_AUTOIK_LEN_INC = 22,
567   TFM_MODAL_AUTOIK_LEN_DEC = 23,
568 
569   TFM_MODAL_EDGESLIDE_UP = 24,
570   TFM_MODAL_EDGESLIDE_DOWN = 25,
571 
572   /* for analog input, like trackpad */
573   TFM_MODAL_PROPSIZE = 26,
574   /* node editor insert offset (aka auto-offset) direction toggle */
575   TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27,
576 
577   TFM_MODAL_AUTOCONSTRAINT = 28,
578   TFM_MODAL_AUTOCONSTRAINTPLANE = 29,
579 };
580 
581 bool initTransform(struct bContext *C,
582                    struct TransInfo *t,
583                    struct wmOperator *op,
584                    const struct wmEvent *event,
585                    int mode);
586 void saveTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op);
587 int transformEvent(TransInfo *t, const struct wmEvent *event);
588 void transformApply(struct bContext *C, TransInfo *t);
589 int transformEnd(struct bContext *C, TransInfo *t);
590 
591 void setTransformViewMatrices(TransInfo *t);
592 void setTransformViewAspect(TransInfo *t, float r_aspect[3]);
593 void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy);
594 void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag);
595 void projectIntView(TransInfo *t, const float vec[3], int adr[2]);
596 void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag);
597 void projectFloatView(TransInfo *t, const float vec[3], float adr[2]);
598 
599 void applyAspectRatio(TransInfo *t, float vec[2]);
600 void removeAspectRatio(TransInfo *t, float vec[2]);
601 
602 struct wmKeyMap *transform_modal_keymap(struct wmKeyConfig *keyconf);
603 
604 /*********************** transform_gizmo.c ********** */
605 
606 #define GIZMO_AXIS_LINE_WIDTH 2.0f
607 
608 /* return 0 when no gimbal for selection */
609 bool gimbal_axis(struct Object *ob, float gmat[3][3]);
610 void drawDial3d(const TransInfo *t);
611 
612 /*********************** TransData Creation and General Handling *********** */
613 bool transdata_check_local_islands(TransInfo *t, short around);
614 
615 /********************** Mouse Input ******************************/
616 
617 typedef enum {
618   INPUT_NONE,
619   INPUT_VECTOR,
620   INPUT_SPRING,
621   INPUT_SPRING_FLIP,
622   INPUT_SPRING_DELTA,
623   INPUT_ANGLE,
624   INPUT_ANGLE_SPRING,
625   INPUT_TRACKBALL,
626   INPUT_HORIZONTAL_RATIO,
627   INPUT_HORIZONTAL_ABSOLUTE,
628   INPUT_VERTICAL_RATIO,
629   INPUT_VERTICAL_ABSOLUTE,
630   INPUT_CUSTOM_RATIO,
631   INPUT_CUSTOM_RATIO_FLIP,
632 } MouseInputMode;
633 
634 void initMouseInput(
635     TransInfo *t, MouseInput *mi, const float center[2], const int mval[2], const bool precision);
636 void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode);
637 eRedrawFlag handleMouseInput(struct TransInfo *t,
638                              struct MouseInput *mi,
639                              const struct wmEvent *event);
640 void applyMouseInput(struct TransInfo *t,
641                      struct MouseInput *mi,
642                      const int mval[2],
643                      float output[3]);
644 
645 void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]);
646 void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]);
647 void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]));
648 
649 /*********************** Generics ********************************/
650 
651 void initTransDataContainers_FromObjectData(TransInfo *t,
652                                             struct Object *obact,
653                                             struct Object **objects,
654                                             uint objects_len);
655 void initTransInfo(struct bContext *C,
656                    TransInfo *t,
657                    struct wmOperator *op,
658                    const struct wmEvent *event);
659 void freeTransCustomDataForMode(TransInfo *t);
660 void postTrans(struct bContext *C, TransInfo *t);
661 void resetTransModal(TransInfo *t);
662 void resetTransRestrictions(TransInfo *t);
663 
664 void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options);
665 
666 /* DRAWLINE options flags */
667 #define DRAWLIGHT 1
668 
669 void applyTransObjects(TransInfo *t);
670 void restoreTransObjects(TransInfo *t);
671 void recalcData(TransInfo *t);
672 
673 void calculateCenter2D(TransInfo *t);
674 void calculateCenterLocal(TransInfo *t, const float center_global[3]);
675 
676 const TransCenterData *transformCenter_from_type(TransInfo *t, int around);
677 void calculateCenter(TransInfo *t);
678 
679 /* API functions for getting center points */
680 void calculateCenterBound(TransInfo *t, float r_center[3]);
681 void calculateCenterMedian(TransInfo *t, float r_center[3]);
682 void calculateCenterCursor(TransInfo *t, float r_center[3]);
683 void calculateCenterCursor2D(TransInfo *t, float r_center[2]);
684 void calculateCenterCursorGraph2D(TransInfo *t, float r_center[2]);
685 bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]);
686 
687 void calculatePropRatio(TransInfo *t);
688 
689 void getViewVector(const TransInfo *t, const float coord[3], float vec[3]);
690 
691 void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot);
692 
693 void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
694 
695 /* TODO. transform_query.c */
696 bool checkUseAxisMatrix(TransInfo *t);
697 
698 #define TRANSFORM_SNAP_MAX_PX 100.0f
699 #define TRANSFORM_DIST_INVALID -FLT_MAX
700 
701 /* Temp macros. */
702 
703 #define TRANS_DATA_CONTAINER_FIRST_OK(t) (&(t)->data_container[0])
704 /* For cases we _know_ there is only one handle. */
705 #define TRANS_DATA_CONTAINER_FIRST_SINGLE(t) \
706   (BLI_assert((t)->data_container_len == 1), (&(t)->data_container[0]))
707 
708 #define FOREACH_TRANS_DATA_CONTAINER(t, th) \
709   for (TransDataContainer *tc = (t)->data_container, \
710                           *tc_end = (t)->data_container + (t)->data_container_len; \
711        th != tc_end; \
712        th++)
713 
714 #define FOREACH_TRANS_DATA_CONTAINER_INDEX(t, th, i) \
715   for (TransDataContainer *tc = ((i = 0), (t)->data_container), \
716                           *tc_end = (t)->data_container + (t)->data_container_len; \
717        th != tc_end; \
718        th++, i++)
719