Blender  V3.3
transform_gizmo_3d.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
11 #include <float.h>
12 #include <math.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "DNA_armature_types.h"
17 #include "DNA_curve_types.h"
18 #include "DNA_gpencil_types.h"
19 #include "DNA_lattice_types.h"
20 #include "DNA_meta_types.h"
21 #include "DNA_scene_types.h"
22 #include "DNA_screen_types.h"
23 #include "DNA_view3d_types.h"
24 
25 #include "BLI_array_utils.h"
26 #include "BLI_listbase.h"
27 #include "BLI_math.h"
28 #include "BLI_utildefines.h"
29 
30 #include "BKE_action.h"
31 #include "BKE_armature.h"
32 #include "BKE_context.h"
33 #include "BKE_curve.h"
34 #include "BKE_editmesh.h"
35 #include "BKE_global.h"
36 #include "BKE_gpencil.h"
37 #include "BKE_layer.h"
38 #include "BKE_object.h"
39 #include "BKE_paint.h"
40 #include "BKE_pointcache.h"
41 #include "BKE_scene.h"
42 
43 #include "DEG_depsgraph.h"
44 
45 #include "WM_api.h"
46 #include "WM_message.h"
47 #include "WM_types.h"
48 
49 #include "ED_armature.h"
50 #include "ED_gizmo_library.h"
51 #include "ED_gizmo_utils.h"
52 #include "ED_gpencil.h"
53 #include "ED_object.h"
54 #include "ED_particle.h"
55 #include "ED_screen.h"
56 #include "ED_view3d.h"
57 
58 #include "UI_interface.h"
59 #include "UI_resources.h"
60 
61 #include "RNA_access.h"
62 #include "RNA_define.h"
63 
64 /* local module include */
65 #include "transform.h"
66 #include "transform_convert.h"
67 #include "transform_snap.h"
68 
69 #include "MEM_guardedalloc.h"
70 
71 #include "GPU_state.h"
72 
73 static void gizmo_refresh_from_matrix(wmGizmoGroup *gzgroup,
74  const float twmat[4][4],
75  const float scale[3]);
76 
77 /* return codes for select, and drawing flags */
78 
79 #define MAN_TRANS_X (1 << 0)
80 #define MAN_TRANS_Y (1 << 1)
81 #define MAN_TRANS_Z (1 << 2)
82 #define MAN_TRANS_C (MAN_TRANS_X | MAN_TRANS_Y | MAN_TRANS_Z)
83 
84 #define MAN_ROT_X (1 << 3)
85 #define MAN_ROT_Y (1 << 4)
86 #define MAN_ROT_Z (1 << 5)
87 #define MAN_ROT_C (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z)
88 
89 #define MAN_SCALE_X (1 << 8)
90 #define MAN_SCALE_Y (1 << 9)
91 #define MAN_SCALE_Z (1 << 10)
92 #define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z)
93 
94 /* threshold for testing view aligned gizmo axis */
95 static struct {
96  float min, max;
97 } g_tw_axis_range[2] = {
98  /* Regular range */
99  {0.02f, 0.1f},
100  /* Use a different range because we flip the dot product,
101  * also the view aligned planes are harder to see so hiding early is preferred. */
102  {0.175f, 0.25f},
103 };
104 
105 /* axes as index */
106 enum {
111 
115 #define MAN_AXIS_RANGE_TRANS_START MAN_AXIS_TRANS_X
116 #define MAN_AXIS_RANGE_TRANS_END (MAN_AXIS_TRANS_ZX + 1)
117 
122  MAN_AXIS_ROT_T, /* trackball rotation */
123 #define MAN_AXIS_RANGE_ROT_START MAN_AXIS_ROT_X
124 #define MAN_AXIS_RANGE_ROT_END (MAN_AXIS_ROT_T + 1)
125 
133 #define MAN_AXIS_RANGE_SCALE_START MAN_AXIS_SCALE_X
134 #define MAN_AXIS_RANGE_SCALE_END (MAN_AXIS_SCALE_ZX + 1)
135 
137 };
138 
139 /* axis types */
140 enum {
145 };
146 
147 typedef struct GizmoGroup {
149  int twtype;
150 
151  /* Users may change the twtype, detect changes to re-setup gizmo options. */
155 
156  /* Only for view orientation. */
157  struct {
158  float viewinv_m3[3][3];
159  } prev;
160 
161  /* Only for Rotate operator. */
162  float rotation;
163 
166 
167 /* -------------------------------------------------------------------- */
171 /* loop over axes */
172 #define MAN_ITER_AXES_BEGIN(axis, axis_idx) \
173  { \
174  wmGizmo *axis; \
175  int axis_idx; \
176  for (axis_idx = 0; axis_idx < MAN_AXIS_LAST; axis_idx++) { \
177  axis = gizmo_get_axis_from_index(ggd, axis_idx);
178 
179 #define MAN_ITER_AXES_END \
180  } \
181  } \
182  ((void)0)
183 
184 static wmGizmo *gizmo_get_axis_from_index(const GizmoGroup *ggd, const short axis_idx)
185 {
186  BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN_AXIS_TRANS_X, (float)MAN_AXIS_LAST));
187  return ggd->gizmos[axis_idx];
188 }
189 
190 static short gizmo_get_axis_type(const int axis_idx)
191 {
192  if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
193  return MAN_AXES_TRANSLATE;
194  }
195  if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) {
196  return MAN_AXES_ROTATE;
197  }
198  if (axis_idx >= MAN_AXIS_RANGE_SCALE_START && axis_idx < MAN_AXIS_RANGE_SCALE_END) {
199  return MAN_AXES_SCALE;
200  }
201  BLI_assert(0);
202  return -1;
203 }
204 
205 static uint gizmo_orientation_axis(const int axis_idx, bool *r_is_plane)
206 {
207  switch (axis_idx) {
208  case MAN_AXIS_TRANS_YZ:
209  case MAN_AXIS_SCALE_YZ:
210  if (r_is_plane) {
211  *r_is_plane = true;
212  }
214  case MAN_AXIS_TRANS_X:
215  case MAN_AXIS_ROT_X:
216  case MAN_AXIS_SCALE_X:
217  return 0;
218 
219  case MAN_AXIS_TRANS_ZX:
220  case MAN_AXIS_SCALE_ZX:
221  if (r_is_plane) {
222  *r_is_plane = true;
223  }
225  case MAN_AXIS_TRANS_Y:
226  case MAN_AXIS_ROT_Y:
227  case MAN_AXIS_SCALE_Y:
228  return 1;
229 
230  case MAN_AXIS_TRANS_XY:
231  case MAN_AXIS_SCALE_XY:
232  if (r_is_plane) {
233  *r_is_plane = true;
234  }
236  case MAN_AXIS_TRANS_Z:
237  case MAN_AXIS_ROT_Z:
238  case MAN_AXIS_SCALE_Z:
239  return 2;
240  }
241  return 3;
242 }
243 
244 static bool gizmo_is_axis_visible(const RegionView3D *rv3d,
245  const int twtype,
246  const float idot[3],
247  const int axis_type,
248  const int axis_idx)
249 {
250  if ((axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) == 0) {
251  bool is_plane = false;
252  const uint aidx_norm = gizmo_orientation_axis(axis_idx, &is_plane);
253  /* don't draw axis perpendicular to the view */
254  if (aidx_norm < 3) {
255  float idot_axis = idot[aidx_norm];
256  if (is_plane) {
257  idot_axis = 1.0f - idot_axis;
258  }
259  if (idot_axis < g_tw_axis_range[is_plane].min) {
260  return false;
261  }
262  }
263  }
264 
265  if ((axis_type == MAN_AXES_TRANSLATE && !(twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE)) ||
266  (axis_type == MAN_AXES_ROTATE && !(twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE)) ||
267  (axis_type == MAN_AXES_SCALE && !(twtype & V3D_GIZMO_SHOW_OBJECT_SCALE))) {
268  return false;
269  }
270 
271  switch (axis_idx) {
272  case MAN_AXIS_TRANS_X:
273  return (rv3d->twdrawflag & MAN_TRANS_X);
274  case MAN_AXIS_TRANS_Y:
275  return (rv3d->twdrawflag & MAN_TRANS_Y);
276  case MAN_AXIS_TRANS_Z:
277  return (rv3d->twdrawflag & MAN_TRANS_Z);
278  case MAN_AXIS_TRANS_C:
279  return (rv3d->twdrawflag & MAN_TRANS_C);
280  case MAN_AXIS_ROT_X:
281  return (rv3d->twdrawflag & MAN_ROT_X);
282  case MAN_AXIS_ROT_Y:
283  return (rv3d->twdrawflag & MAN_ROT_Y);
284  case MAN_AXIS_ROT_Z:
285  return (rv3d->twdrawflag & MAN_ROT_Z);
286  case MAN_AXIS_ROT_C:
287  case MAN_AXIS_ROT_T:
288  return (rv3d->twdrawflag & MAN_ROT_C);
289  case MAN_AXIS_SCALE_X:
290  return (rv3d->twdrawflag & MAN_SCALE_X);
291  case MAN_AXIS_SCALE_Y:
292  return (rv3d->twdrawflag & MAN_SCALE_Y);
293  case MAN_AXIS_SCALE_Z:
294  return (rv3d->twdrawflag & MAN_SCALE_Z);
295  case MAN_AXIS_SCALE_C:
296  return (rv3d->twdrawflag & MAN_SCALE_C && (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0);
297  case MAN_AXIS_TRANS_XY:
298  return (rv3d->twdrawflag & MAN_TRANS_X && rv3d->twdrawflag & MAN_TRANS_Y &&
299  (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
300  case MAN_AXIS_TRANS_YZ:
301  return (rv3d->twdrawflag & MAN_TRANS_Y && rv3d->twdrawflag & MAN_TRANS_Z &&
302  (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
303  case MAN_AXIS_TRANS_ZX:
304  return (rv3d->twdrawflag & MAN_TRANS_Z && rv3d->twdrawflag & MAN_TRANS_X &&
305  (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
306  case MAN_AXIS_SCALE_XY:
307  return (rv3d->twdrawflag & MAN_SCALE_X && rv3d->twdrawflag & MAN_SCALE_Y &&
308  (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
309  (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
310  case MAN_AXIS_SCALE_YZ:
311  return (rv3d->twdrawflag & MAN_SCALE_Y && rv3d->twdrawflag & MAN_SCALE_Z &&
312  (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
313  (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
314  case MAN_AXIS_SCALE_ZX:
315  return (rv3d->twdrawflag & MAN_SCALE_Z && rv3d->twdrawflag & MAN_SCALE_X &&
316  (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
317  (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
318  }
319  return false;
320 }
321 
322 static void gizmo_get_axis_color(const int axis_idx,
323  const float idot[3],
324  float r_col[4],
325  float r_col_hi[4])
326 {
327  /* alpha values for normal/highlighted states */
328  const float alpha = 0.6f;
329  const float alpha_hi = 1.0f;
330  float alpha_fac;
331 
332  if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) {
333  /* Never fade rotation rings. */
334  /* trackball rotation axis is a special case, we only draw a slight overlay */
335  alpha_fac = (axis_idx == MAN_AXIS_ROT_T) ? 0.05f : 1.0f;
336  }
337  else {
338  bool is_plane = false;
339  const int axis_idx_norm = gizmo_orientation_axis(axis_idx, &is_plane);
340  /* Get alpha fac based on axis angle,
341  * to fade axis out when hiding it because it points towards view. */
342  if (axis_idx_norm < 3) {
343  const float idot_min = g_tw_axis_range[is_plane].min;
344  const float idot_max = g_tw_axis_range[is_plane].max;
345  float idot_axis = idot[axis_idx_norm];
346  if (is_plane) {
347  idot_axis = 1.0f - idot_axis;
348  }
349  alpha_fac = ((idot_axis > idot_max) ? 1.0f :
350  (idot_axis < idot_min) ? 0.0f :
351  ((idot_axis - idot_min) / (idot_max - idot_min)));
352  }
353  else {
354  alpha_fac = 1.0f;
355  }
356  }
357 
358  switch (axis_idx) {
359  case MAN_AXIS_TRANS_X:
360  case MAN_AXIS_ROT_X:
361  case MAN_AXIS_SCALE_X:
362  case MAN_AXIS_TRANS_YZ:
363  case MAN_AXIS_SCALE_YZ:
365  break;
366  case MAN_AXIS_TRANS_Y:
367  case MAN_AXIS_ROT_Y:
368  case MAN_AXIS_SCALE_Y:
369  case MAN_AXIS_TRANS_ZX:
370  case MAN_AXIS_SCALE_ZX:
372  break;
373  case MAN_AXIS_TRANS_Z:
374  case MAN_AXIS_ROT_Z:
375  case MAN_AXIS_SCALE_Z:
376  case MAN_AXIS_TRANS_XY:
377  case MAN_AXIS_SCALE_XY:
379  break;
380  case MAN_AXIS_TRANS_C:
381  case MAN_AXIS_ROT_C:
382  case MAN_AXIS_SCALE_C:
383  case MAN_AXIS_ROT_T:
385  break;
386  }
387 
388  copy_v4_v4(r_col_hi, r_col);
389 
390  r_col[3] = alpha * alpha_fac;
391  r_col_hi[3] = alpha_hi * alpha_fac;
392 }
393 
394 static void gizmo_get_axis_constraint(const int axis_idx, bool r_axis[3])
395 {
396  ARRAY_SET_ITEMS(r_axis, 0, 0, 0);
397 
398  switch (axis_idx) {
399  case MAN_AXIS_TRANS_X:
400  case MAN_AXIS_ROT_X:
401  case MAN_AXIS_SCALE_X:
402  r_axis[0] = 1;
403  break;
404  case MAN_AXIS_TRANS_Y:
405  case MAN_AXIS_ROT_Y:
406  case MAN_AXIS_SCALE_Y:
407  r_axis[1] = 1;
408  break;
409  case MAN_AXIS_TRANS_Z:
410  case MAN_AXIS_ROT_Z:
411  case MAN_AXIS_SCALE_Z:
412  r_axis[2] = 1;
413  break;
414  case MAN_AXIS_TRANS_XY:
415  case MAN_AXIS_SCALE_XY:
416  r_axis[0] = r_axis[1] = 1;
417  break;
418  case MAN_AXIS_TRANS_YZ:
419  case MAN_AXIS_SCALE_YZ:
420  r_axis[1] = r_axis[2] = 1;
421  break;
422  case MAN_AXIS_TRANS_ZX:
423  case MAN_AXIS_SCALE_ZX:
424  r_axis[2] = r_axis[0] = 1;
425  break;
426  default:
427  break;
428  }
429 }
430 
431 /* **************** Preparation Stuff **************** */
432 
433 static void reset_tw_center(struct TransformBounds *tbounds)
434 {
435  INIT_MINMAX(tbounds->min, tbounds->max);
436  zero_v3(tbounds->center);
437 
438  for (int i = 0; i < 3; i++) {
439  tbounds->axis_min[i] = +FLT_MAX;
440  tbounds->axis_max[i] = -FLT_MAX;
441  }
442 }
443 
444 /* transform widget center calc helper for below */
445 static void calc_tw_center(struct TransformBounds *tbounds, const float co[3])
446 {
447  minmax_v3v3_v3(tbounds->min, tbounds->max, co);
448  add_v3_v3(tbounds->center, co);
449 
450  for (int i = 0; i < 3; i++) {
451  const float d = dot_v3v3(tbounds->axis[i], co);
452  tbounds->axis_min[i] = min_ff(d, tbounds->axis_min[i]);
453  tbounds->axis_max[i] = max_ff(d, tbounds->axis_max[i]);
454  }
455 }
456 
457 static void calc_tw_center_with_matrix(struct TransformBounds *tbounds,
458  const float co[3],
459  const bool use_matrix,
460  const float matrix[4][4])
461 {
462  float co_world[3];
463  if (use_matrix) {
464  mul_v3_m4v3(co_world, matrix, co);
465  co = co_world;
466  }
467  calc_tw_center(tbounds, co);
468 }
469 
470 static void protectflag_to_drawflags(short protectflag, short *drawflags)
471 {
472  if (protectflag & OB_LOCK_LOCX) {
473  *drawflags &= ~MAN_TRANS_X;
474  }
475  if (protectflag & OB_LOCK_LOCY) {
476  *drawflags &= ~MAN_TRANS_Y;
477  }
478  if (protectflag & OB_LOCK_LOCZ) {
479  *drawflags &= ~MAN_TRANS_Z;
480  }
481 
482  if (protectflag & OB_LOCK_ROTX) {
483  *drawflags &= ~MAN_ROT_X;
484  }
485  if (protectflag & OB_LOCK_ROTY) {
486  *drawflags &= ~MAN_ROT_Y;
487  }
488  if (protectflag & OB_LOCK_ROTZ) {
489  *drawflags &= ~MAN_ROT_Z;
490  }
491 
492  if (protectflag & OB_LOCK_SCALEX) {
493  *drawflags &= ~MAN_SCALE_X;
494  }
495  if (protectflag & OB_LOCK_SCALEY) {
496  *drawflags &= ~MAN_SCALE_Y;
497  }
498  if (protectflag & OB_LOCK_SCALEZ) {
499  *drawflags &= ~MAN_SCALE_Z;
500  }
501 }
502 
503 /* for pose mode */
505  const bPoseChannel *pchan,
506  short orientation_index)
507 {
508  /* Protect-flags apply to local space in pose mode, so only let them influence axis
509  * visibility if we show the global orientation, otherwise it's confusing. */
510  if (ELEM(orientation_index, V3D_ORIENT_LOCAL, V3D_ORIENT_GIMBAL)) {
512  }
513 }
514 
515 /* For editmode. */
517 {
518  if (ebo->flag & BONE_EDITMODE_LOCKED) {
520  }
521 }
522 
523 /* could move into BLI_math however this is only useful for display/editing purposes */
524 static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], const float angle)
525 {
526  /* X/Y are arbitrary axes, most importantly Z is the axis of rotation. */
527 
528  float cross_vec[3];
529  float quat[4];
530 
531  /* this is an un-scientific method to get a vector to cross with
532  * XYZ intentionally YZX */
533  cross_vec[0] = axis[1];
534  cross_vec[1] = axis[2];
535  cross_vec[2] = axis[0];
536 
537  /* X-axis */
538  cross_v3_v3v3(gmat[0], cross_vec, axis);
539  normalize_v3(gmat[0]);
540  axis_angle_to_quat(quat, axis, angle);
541  mul_qt_v3(quat, gmat[0]);
542 
543  /* Y-axis */
544  axis_angle_to_quat(quat, axis, M_PI_2);
545  copy_v3_v3(gmat[1], gmat[0]);
546  mul_qt_v3(quat, gmat[1]);
547 
548  /* Z-axis */
549  copy_v3_v3(gmat[2], axis);
550 
551  normalize_m3(gmat);
552 }
553 
554 static bool test_rotmode_euler(short rotmode)
555 {
556  return (ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT)) ? 0 : 1;
557 }
558 
559 bool gimbal_axis_pose(Object *ob, const bPoseChannel *pchan, float gmat[3][3])
560 {
561  float mat[3][3], tmat[3][3], obmat[3][3];
562  if (test_rotmode_euler(pchan->rotmode)) {
563  eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode);
564  }
565  else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
566  axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle);
567  }
568  else { /* quat */
569  return 0;
570  }
571 
572  /* apply bone transformation */
573  mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat);
574 
575  if (pchan->parent) {
576  float parent_mat[3][3];
577 
578  copy_m3_m4(parent_mat,
579  (pchan->bone->flag & BONE_HINGE) ? pchan->parent->bone->arm_mat :
580  pchan->parent->pose_mat);
581  mul_m3_m3m3(mat, parent_mat, tmat);
582 
583  /* needed if object transformation isn't identity */
584  copy_m3_m4(obmat, ob->obmat);
585  mul_m3_m3m3(gmat, obmat, mat);
586  }
587  else {
588  /* needed if object transformation isn't identity */
589  copy_m3_m4(obmat, ob->obmat);
590  mul_m3_m3m3(gmat, obmat, tmat);
591  }
592 
593  normalize_m3(gmat);
594  return true;
595 }
596 
597 bool gimbal_axis_object(Object *ob, float gmat[3][3])
598 {
599  if (test_rotmode_euler(ob->rotmode)) {
600  eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode);
601  }
602  else if (ob->rotmode == ROT_MODE_AXISANGLE) {
604  }
605  else { /* quat */
606  return 0;
607  }
608 
609  if (ob->parent) {
610  float parent_mat[3][3];
611  copy_m3_m4(parent_mat, ob->parent->obmat);
612  normalize_m3(parent_mat);
613  mul_m3_m3m3(gmat, parent_mat, gmat);
614  }
615  return 1;
616 }
617 
619  const struct TransformCalcParams *params,
620  struct TransformBounds *tbounds)
621 {
623  ARegion *region = CTX_wm_region(C);
625  /* TODO(sergey): This function is used from operator's modal() and from gizmo's refresh().
626  * Is it fine to possibly evaluate dependency graph here? */
628  ViewLayer *view_layer = CTX_data_view_layer(C);
629  View3D *v3d = area->spacedata.first;
630  RegionView3D *rv3d = region->regiondata;
631  Base *base;
633  const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
634  const bool is_curve_edit = GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
635  int a, totsel = 0;
636 
637  const int pivot_point = scene->toolsettings->transform_pivot_point;
638  const short orient_index = params->orientation_index ?
639  (params->orientation_index - 1) :
641 
642  Object *ob = OBACT(view_layer);
643  Object *obedit = OBEDIT_FROM_OBACT(ob);
644  if (ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
645  Object *obpose = BKE_object_pose_armature_get(ob);
646  if (obpose != NULL) {
647  ob = obpose;
648  }
649  }
650 
651  tbounds->use_matrix_space = false;
652 
653  /* transform widget matrix */
654  unit_m4(rv3d->twmat);
655 
656  unit_m3(rv3d->tw_axis_matrix);
657  zero_v3(rv3d->tw_axis_min);
658  zero_v3(rv3d->tw_axis_max);
659 
660  rv3d->twdrawflag = 0xFFFF;
661 
662  /* global, local or normal orientation?
663  * if we could check 'totsel' now, this should be skipped with no selection. */
664  if (ob) {
665  float mat[3][3];
667  scene, view_layer, v3d, rv3d, ob, obedit, orient_index, pivot_point, mat);
668  copy_m4_m3(rv3d->twmat, mat);
669  }
670 
671  /* transform widget centroid/center */
672  reset_tw_center(tbounds);
673 
674  copy_m3_m4(tbounds->axis, rv3d->twmat);
675  if (params->use_local_axis && (ob && ob->mode & (OB_MODE_EDIT | OB_MODE_POSE))) {
676  float diff_mat[3][3];
677  copy_m3_m4(diff_mat, ob->obmat);
678  normalize_m3(diff_mat);
679  invert_m3(diff_mat);
680  mul_m3_m3_pre(tbounds->axis, diff_mat);
681  normalize_m3(tbounds->axis);
682 
683  tbounds->use_matrix_space = true;
684  copy_m4_m4(tbounds->matrix_space, ob->obmat);
685  }
686 
687  if (is_gp_edit) {
688  float diff_mat[4][4];
689  const bool use_mat_local = true;
690  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
691  /* only editable and visible layers are considered */
692 
693  if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
694 
695  /* calculate difference matrix */
697 
698  LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) {
699  /* skip strokes that are invalid for current view */
700  if (ED_gpencil_stroke_can_use(C, gps) == false) {
701  continue;
702  }
703 
704  if (is_curve_edit) {
705  if (gps->editcurve == NULL) {
706  continue;
707  }
708 
709  bGPDcurve *gpc = gps->editcurve;
710  if (gpc->flag & GP_CURVE_SELECT) {
711  for (uint32_t i = 0; i < gpc->tot_curve_points; i++) {
712  bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
713  BezTriple *bezt = &gpc_pt->bezt;
714  if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
715  for (uint32_t j = 0; j < 3; j++) {
716  if (BEZT_ISSEL_IDX(bezt, j)) {
717  calc_tw_center_with_matrix(tbounds, bezt->vec[j], use_mat_local, diff_mat);
718  totsel++;
719  }
720  }
721  }
722  }
723  }
724  }
725  else {
726  /* we're only interested in selected points here... */
727  if (gps->flag & GP_STROKE_SELECT) {
728  bGPDspoint *pt;
729  int i;
730 
731  /* Change selection status of all points, then make the stroke match */
732  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
733  if (pt->flag & GP_SPOINT_SELECT) {
734  calc_tw_center_with_matrix(tbounds, &pt->x, use_mat_local, diff_mat);
735  totsel++;
736  }
737  }
738  }
739  }
740  }
741  }
742  }
743 
744  /* selection center */
745  if (totsel) {
746  mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
747  }
748  }
749  else if (obedit) {
750 
751 #define FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) \
752  { \
753  invert_m4_m4(obedit->imat, obedit->obmat); \
754  uint objects_len = 0; \
755  Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( \
756  view_layer, CTX_wm_view3d(C), &objects_len); \
757  for (uint ob_index = 0; ob_index < objects_len; ob_index++) { \
758  Object *ob_iter = objects[ob_index]; \
759  const bool use_mat_local = (ob_iter != obedit);
760 
761 #define FOREACH_EDIT_OBJECT_END() \
762  } \
763  MEM_freeN(objects); \
764  } \
765  ((void)0)
766 
767  ob = obedit;
768  if (obedit->type == OB_MESH) {
769  FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
770  BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
771  BMesh *bm = em_iter->bm;
772 
773  if (bm->totvertsel == 0) {
774  continue;
775  }
776 
777  BMVert *eve;
778  BMIter iter;
779 
780  float mat_local[4][4];
781  if (use_mat_local) {
782  mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
783  }
784 
785  BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
786  if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
787  if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
788  calc_tw_center_with_matrix(tbounds, eve->co, use_mat_local, mat_local);
789  totsel++;
790  }
791  }
792  }
793  }
795  } /* end editmesh */
796  else if (obedit->type == OB_ARMATURE) {
797  FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
798  bArmature *arm = ob_iter->data;
799 
800  float mat_local[4][4];
801  if (use_mat_local) {
802  mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
803  }
804  LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
805  if (EBONE_VISIBLE(arm, ebo)) {
806  if (ebo->flag & BONE_TIPSEL) {
807  calc_tw_center_with_matrix(tbounds, ebo->tail, use_mat_local, mat_local);
808  totsel++;
809  }
810  if ((ebo->flag & BONE_ROOTSEL) &&
811  /* don't include same point multiple times */
812  ((ebo->flag & BONE_CONNECTED) && (ebo->parent != NULL) &&
813  (ebo->parent->flag & BONE_TIPSEL) && EBONE_VISIBLE(arm, ebo->parent)) == 0) {
814  calc_tw_center_with_matrix(tbounds, ebo->head, use_mat_local, mat_local);
815  totsel++;
816  }
817  if (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
819  }
820  }
821  }
822  }
824  }
825  else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) {
826  FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
827  Curve *cu = ob_iter->data;
828  Nurb *nu;
829  BezTriple *bezt;
830  BPoint *bp;
831  ListBase *nurbs = BKE_curve_editNurbs_get(cu);
832 
833  float mat_local[4][4];
834  if (use_mat_local) {
835  mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
836  }
837 
838  nu = nurbs->first;
839  while (nu) {
840  if (nu->type == CU_BEZIER) {
841  bezt = nu->bezt;
842  a = nu->pntsu;
843  while (a--) {
844  /* exceptions
845  * if handles are hidden then only check the center points.
846  * If the center knot is selected then only use this as the center point.
847  */
849  if (bezt->f2 & SELECT) {
850  calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
851  totsel++;
852  }
853  }
854  else if (bezt->f2 & SELECT) {
855  calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
856  totsel++;
857  }
858  else {
859  if (bezt->f1 & SELECT) {
860  const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0];
861  calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
862  totsel++;
863  }
864  if (bezt->f3 & SELECT) {
865  const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2];
866  calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
867  totsel++;
868  }
869  }
870  bezt++;
871  }
872  }
873  else {
874  bp = nu->bp;
875  a = nu->pntsu * nu->pntsv;
876  while (a--) {
877  if (bp->f1 & SELECT) {
878  calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
879  totsel++;
880  }
881  bp++;
882  }
883  }
884  nu = nu->next;
885  }
886  }
888  }
889  else if (obedit->type == OB_MBALL) {
890  FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
891  MetaBall *mb = (MetaBall *)ob_iter->data;
892 
893  float mat_local[4][4];
894  if (use_mat_local) {
895  mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
896  }
897 
898  LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
899  if (ml->flag & SELECT) {
900  calc_tw_center_with_matrix(tbounds, &ml->x, use_mat_local, mat_local);
901  totsel++;
902  }
903  }
904  }
906  }
907  else if (obedit->type == OB_LATTICE) {
908  FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
909  Lattice *lt = ((Lattice *)ob_iter->data)->editlatt->latt;
910  BPoint *bp = lt->def;
911  a = lt->pntsu * lt->pntsv * lt->pntsw;
912 
913  float mat_local[4][4];
914  if (use_mat_local) {
915  mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
916  }
917 
918  while (a--) {
919  if (bp->f1 & SELECT) {
920  calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
921  totsel++;
922  }
923  bp++;
924  }
925  }
927  }
928 
929 #undef FOREACH_EDIT_OBJECT_BEGIN
930 #undef FOREACH_EDIT_OBJECT_END
931 
932  /* selection center */
933  if (totsel) {
934  mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
935  mul_m4_v3(obedit->obmat, tbounds->center);
936  mul_m4_v3(obedit->obmat, tbounds->min);
937  mul_m4_v3(obedit->obmat, tbounds->max);
938  }
939  }
940  else if (ob && (ob->mode & OB_MODE_POSE)) {
941  invert_m4_m4(ob->imat, ob->obmat);
942 
943  uint objects_len = 0;
944  Object **objects = BKE_object_pose_array_get(view_layer, v3d, &objects_len);
945 
946  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
947  Object *ob_iter = objects[ob_index];
948  const bool use_mat_local = (ob_iter != ob);
949  /* mislead counting bones... bah. We don't know the gizmo mode, could be mixed */
950  const int mode = TFM_ROTATION;
951 
953 
954  float mat_local[4][4];
955  if (use_mat_local) {
956  mul_m4_m4m4(mat_local, ob->imat, ob_iter->obmat);
957  }
958 
959  /* Use channels to get stats. */
960  LISTBASE_FOREACH (bPoseChannel *, pchan, &ob_iter->pose->chanbase) {
961  if (!(pchan->bone->flag & BONE_TRANSFORM)) {
962  continue;
963  }
964  calc_tw_center_with_matrix(tbounds, pchan->pose_head, use_mat_local, mat_local);
965  protectflag_to_drawflags_pchan(rv3d, pchan, orient_index);
966  totsel++;
967  }
968  }
969  MEM_freeN(objects);
970 
971  if (totsel) {
972  mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
973  mul_m4_v3(ob->obmat, tbounds->center);
974  mul_m4_v3(ob->obmat, tbounds->min);
975  mul_m4_v3(ob->obmat, tbounds->max);
976  }
977  }
978  else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
979  if (ob->mode & OB_MODE_SCULPT) {
980  totsel = 1;
981  calc_tw_center_with_matrix(tbounds, ob->sculpt->pivot_pos, false, ob->obmat);
982  mul_m4_v3(ob->obmat, tbounds->center);
983  mul_m4_v3(ob->obmat, tbounds->min);
984  mul_m4_v3(ob->obmat, tbounds->max);
985  }
986  }
987  else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
990  PTCacheEditKey *ek;
991  int k;
992 
993  if (edit) {
994  point = edit->points;
995  for (a = 0; a < edit->totpoint; a++, point++) {
996  if (point->flag & PEP_HIDE) {
997  continue;
998  }
999 
1000  for (k = 0, ek = point->keys; k < point->totkey; k++, ek++) {
1001  if (ek->flag & PEK_SELECT) {
1002  calc_tw_center(tbounds, (ek->flag & PEK_USE_WCO) ? ek->world_co : ek->co);
1003  totsel++;
1004  }
1005  }
1006  }
1007 
1008  /* selection center */
1009  if (totsel) {
1010  mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
1011  }
1012  }
1013  }
1014  else {
1015 
1016  /* we need the one selected object, if its not active */
1017  base = BASACT(view_layer);
1018  ob = OBACT(view_layer);
1019  if (base && ((base->flag & BASE_SELECTED) == 0)) {
1020  ob = NULL;
1021  }
1022 
1023  for (base = view_layer->object_bases.first; base; base = base->next) {
1024  if (!BASE_SELECTED_EDITABLE(v3d, base)) {
1025  continue;
1026  }
1027  if (ob == NULL) {
1028  ob = base->object;
1029  }
1030 
1031  /* Get the boundbox out of the evaluated object. */
1032  const BoundBox *bb = NULL;
1033  if (params->use_only_center == false) {
1034  bb = BKE_object_boundbox_get(base->object);
1035  }
1036 
1037  if (params->use_only_center || (bb == NULL)) {
1038  calc_tw_center(tbounds, base->object->obmat[3]);
1039  }
1040  else {
1041  for (uint j = 0; j < 8; j++) {
1042  float co[3];
1043  mul_v3_m4v3(co, base->object->obmat, bb->vec[j]);
1044  calc_tw_center(tbounds, co);
1045  }
1046  }
1047 
1048  if (orient_index == V3D_ORIENT_GLOBAL) {
1049  /* Protect-flags apply to world space in object mode,
1050  * so only let them influence axis visibility if we show the global orientation,
1051  * otherwise it's confusing. */
1053  }
1054  else if (ELEM(orient_index, V3D_ORIENT_LOCAL, V3D_ORIENT_GIMBAL)) {
1056  }
1057  totsel++;
1058  }
1059 
1060  /* selection center */
1061  if (totsel) {
1062  mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
1063  }
1064  }
1065 
1066  if (totsel == 0) {
1067  unit_m4(rv3d->twmat);
1068  }
1069  else {
1070  copy_v3_v3(rv3d->tw_axis_min, tbounds->axis_min);
1071  copy_v3_v3(rv3d->tw_axis_max, tbounds->axis_max);
1072  copy_m3_m3(rv3d->tw_axis_matrix, tbounds->axis);
1073  }
1074 
1075  return totsel;
1076 }
1077 
1078 static void gizmo_get_idot(RegionView3D *rv3d, float r_idot[3])
1079 {
1080  float view_vec[3], axis_vec[3];
1081  ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], view_vec);
1082  for (int i = 0; i < 3; i++) {
1083  normalize_v3_v3(axis_vec, rv3d->twmat[i]);
1084  r_idot[i] = 1.0f - fabsf(dot_v3v3(view_vec, axis_vec));
1085  }
1086 }
1087 
1088 static void gizmo_prepare_mat(const bContext *C,
1089  RegionView3D *rv3d,
1090  const struct TransformBounds *tbounds)
1091 {
1093  ViewLayer *view_layer = CTX_data_view_layer(C);
1094 
1097  case V3D_AROUND_ACTIVE: {
1098  mid_v3_v3v3(rv3d->twmat[3], tbounds->min, tbounds->max);
1099 
1102  if (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
1103  /* pass */
1104  }
1105  else {
1106  Object *ob = OBACT(view_layer);
1107  if (ob != NULL) {
1108  if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) {
1109  SculptSession *ss = ob->sculpt;
1110  copy_v3_v3(rv3d->twmat[3], ss->pivot_pos);
1111  }
1112  else {
1113  ED_object_calc_active_center(ob, false, rv3d->twmat[3]);
1114  }
1115  }
1116  }
1117  }
1118  break;
1119  }
1122  copy_v3_v3(rv3d->twmat[3], tbounds->center);
1123  break;
1124  case V3D_AROUND_CURSOR:
1125  copy_v3_v3(rv3d->twmat[3], scene->cursor.location);
1126  break;
1127  }
1128 }
1129 
1134 static void gizmo_line_range(const int twtype, const short axis_type, float *r_start, float *r_len)
1135 {
1136  const float ofs = 0.2f;
1137 
1138  *r_start = 0.2f;
1139  *r_len = 1.0f;
1140 
1141  switch (axis_type) {
1142  case MAN_AXES_TRANSLATE:
1143  if (twtype & V3D_GIZMO_SHOW_OBJECT_SCALE) {
1144  *r_start = *r_len - ofs + 0.075f;
1145  }
1146  if (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
1147  *r_len += ofs;
1148  }
1149  break;
1150  case MAN_AXES_SCALE:
1152  *r_len -= ofs + 0.025f;
1153  }
1154  break;
1155  }
1156 
1157  *r_len -= *r_start;
1158 }
1159 
1161  struct wmMsgBus *mbus,
1162  Scene *scene,
1163  bScreen *screen,
1164  ScrArea *area,
1165  ARegion *region,
1166  const void *type_fn)
1167 {
1168  /* Subscribe to view properties */
1169  wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
1170  .owner = region,
1171  .user_data = gzgroup->parent_gzmap,
1173  };
1174 
1175  int orient_flag = 0;
1176  if (type_fn == VIEW3D_GGT_xform_gizmo) {
1177  GizmoGroup *ggd = gzgroup->customdata;
1178  orient_flag = ggd->twtype_init;
1179  }
1180  else if (type_fn == VIEW3D_GGT_xform_cage) {
1181  orient_flag = V3D_GIZMO_SHOW_OBJECT_SCALE;
1182  /* pass */
1183  }
1184  else if (type_fn == VIEW3D_GGT_xform_shear) {
1185  orient_flag = V3D_GIZMO_SHOW_OBJECT_ROTATE;
1186  }
1188  orient_flag);
1189  PointerRNA orient_ref_ptr;
1190  RNA_pointer_create(&scene->id, &RNA_TransformOrientationSlot, orient_slot, &orient_ref_ptr);
1191  const ToolSettings *ts = scene->toolsettings;
1192 
1193  PointerRNA scene_ptr;
1194  RNA_id_pointer_create(&scene->id, &scene_ptr);
1195  {
1196  const PropertyRNA *props[] = {
1197  &rna_Scene_transform_orientation_slots,
1198  };
1199  for (int i = 0; i < ARRAY_SIZE(props); i++) {
1200  WM_msg_subscribe_rna(mbus, &scene_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
1201  }
1202  }
1203 
1205  (orient_slot->type == V3D_ORIENT_CURSOR)) {
1206  /* We could be more specific here, for now subscribe to any cursor change. */
1207  PointerRNA cursor_ptr;
1208  RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &cursor_ptr);
1209  WM_msg_subscribe_rna(mbus, &cursor_ptr, NULL, &msg_sub_value_gz_tag_refresh, __func__);
1210  }
1211 
1212  {
1213  const PropertyRNA *props[] = {
1214  &rna_TransformOrientationSlot_type,
1215  &rna_TransformOrientationSlot_use,
1216  };
1217  for (int i = 0; i < ARRAY_SIZE(props); i++) {
1218  if (props[i]) {
1220  mbus, &orient_ref_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
1221  }
1222  }
1223  }
1224 
1225  PointerRNA toolsettings_ptr;
1226  RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &toolsettings_ptr);
1227 
1229  const PropertyRNA *props[] = {
1230  &rna_ToolSettings_transform_pivot_point,
1231  };
1232  for (int i = 0; i < ARRAY_SIZE(props); i++) {
1234  mbus, &toolsettings_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
1235  }
1236  }
1237 
1238  {
1239  const PropertyRNA *props[] = {
1240  &rna_ToolSettings_workspace_tool_type,
1241  };
1242  for (int i = 0; i < ARRAY_SIZE(props); i++) {
1244  mbus, &toolsettings_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
1245  }
1246  }
1247 
1248  PointerRNA view3d_ptr;
1249  RNA_pointer_create(&screen->id, &RNA_SpaceView3D, area->spacedata.first, &view3d_ptr);
1250 
1251  if (type_fn == VIEW3D_GGT_xform_gizmo) {
1252  GizmoGroup *ggd = gzgroup->customdata;
1253  if (ggd->use_twtype_refresh) {
1254  const PropertyRNA *props[] = {
1255  &rna_SpaceView3D_show_gizmo_object_translate,
1256  &rna_SpaceView3D_show_gizmo_object_rotate,
1257  &rna_SpaceView3D_show_gizmo_object_scale,
1258  };
1259  for (int i = 0; i < ARRAY_SIZE(props); i++) {
1260  WM_msg_subscribe_rna(mbus, &view3d_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
1261  }
1262  }
1263  }
1264  else if (type_fn == VIEW3D_GGT_xform_cage) {
1265  /* pass */
1266  }
1267  else if (type_fn == VIEW3D_GGT_xform_shear) {
1268  /* pass */
1269  }
1270  else {
1271  BLI_assert(0);
1272  }
1273 
1274  WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_gz_tag_refresh);
1275  WM_msg_subscribe_rna_anon_prop(mbus, EditBone, lock, &msg_sub_value_gz_tag_refresh);
1276 }
1277 
1278 static void gizmo_3d_dial_matrixbasis_calc(const ARegion *region,
1279  float axis[3],
1280  float center_global[3],
1281  float mval_init[2],
1282  float r_mat_basis[4][4])
1283 {
1284  copy_v3_v3(r_mat_basis[2], axis);
1285  copy_v3_v3(r_mat_basis[3], center_global);
1286  r_mat_basis[2][3] = -dot_v3v3(axis, center_global);
1287 
1288  if (ED_view3d_win_to_3d_on_plane(region, axis, mval_init, false, r_mat_basis[1])) {
1289  sub_v3_v3(r_mat_basis[1], center_global);
1290  normalize_v3(r_mat_basis[1]);
1291  cross_v3_v3v3(r_mat_basis[0], r_mat_basis[1], r_mat_basis[2]);
1292  }
1293  else {
1294  /* The plane and the mouse direction are parallel.
1295  * Calculate a matrix orthogonal to the axis. */
1296  ortho_basis_v3v3_v3(r_mat_basis[0], r_mat_basis[1], r_mat_basis[2]);
1297  }
1298 
1299  r_mat_basis[0][3] = 0.0f;
1300  r_mat_basis[1][3] = 0.0f;
1301  r_mat_basis[2][3] = 0.0f;
1302  r_mat_basis[3][3] = 1.0f;
1303 }
1304 
1307 /* -------------------------------------------------------------------- */
1312 #define MAN_AXIS_SCALE_PLANE_SCALE 0.07f
1314 #define MAN_AXIS_SCALE_PLANE_OFFSET 7.0f
1315 
1316 static void rotation_get_fn(const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, void *value)
1317 {
1318  const GizmoGroup *ggd = (const GizmoGroup *)gz_prop->custom_func.user_data;
1319  *(float *)value = ggd->rotation;
1320 }
1321 
1322 static void rotation_set_fn(const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, const void *value)
1323 {
1324  GizmoGroup *ggd = (GizmoGroup *)gz_prop->custom_func.user_data;
1325  ggd->rotation = *(const float *)value;
1326 }
1327 
1329 {
1330  GizmoGroup *ggd;
1331 
1332  ggd = MEM_callocN(sizeof(GizmoGroup), "gizmo_data");
1333 
1334  const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
1335  const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
1336  const wmGizmoType *gzt_prim = WM_gizmotype_find("GIZMO_GT_primitive_3d", true);
1337 
1339  .value_get_fn = rotation_get_fn, .value_set_fn = rotation_set_fn, .user_data = ggd};
1340 
1341 #define GIZMO_NEW_ARROW(v, draw_style) \
1342  { \
1343  ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); \
1344  RNA_enum_set(ggd->gizmos[v]->ptr, "draw_style", draw_style); \
1345  } \
1346  ((void)0)
1347 #define GIZMO_NEW_DIAL(v, draw_options) \
1348  { \
1349  ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL); \
1350  RNA_enum_set(ggd->gizmos[v]->ptr, "draw_options", draw_options); \
1351  WM_gizmo_target_property_def_func(ggd->gizmos[v], "offset", &params); \
1352  } \
1353  ((void)0)
1354 #define GIZMO_NEW_PRIM(v, draw_style) \
1355  { \
1356  ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_prim, gzgroup, NULL); \
1357  RNA_enum_set(ggd->gizmos[v]->ptr, "draw_style", draw_style); \
1358  } \
1359  ((void)0)
1360 
1361  /* add/init widgets - order matters! */
1363 
1365 
1369 
1373 
1377 
1378  /* init screen aligned widget last here, looks better, behaves better */
1380 
1382 
1386 
1390 
1392 
1393  /* Prevent axis gizmos overlapping the center point, see: T63744. */
1394  ggd->gizmos[MAN_AXIS_TRANS_C]->select_bias = 2.0f;
1395 
1396  ggd->gizmos[MAN_AXIS_SCALE_C]->select_bias = -2.0f;
1397 
1398  /* Use 1/6 since this is '0.2' if the main scale is 1.2. */
1399  RNA_float_set(ggd->gizmos[MAN_AXIS_SCALE_C]->ptr, "arc_inner_factor", 1.0 / 6.0);
1400 
1401  return ggd;
1402 }
1403 
1407 static int gizmo_modal(bContext *C,
1408  wmGizmo *widget,
1409  const wmEvent *event,
1410  eWM_GizmoFlagTweak UNUSED(tweak_flag))
1411 {
1412  /* Avoid unnecessary updates, partially address: T55458. */
1413  if (ELEM(event->type, TIMER, INBETWEEN_MOUSEMOVE)) {
1414  return OPERATOR_RUNNING_MODAL;
1415  }
1416 
1417  ARegion *region = CTX_wm_region(C);
1418  RegionView3D *rv3d = region->regiondata;
1419  wmGizmoGroup *gzgroup = widget->parent_gzgroup;
1420 
1421  /* Recalculating the orientation has two problems.
1422  * - The matrix calculated based on the transformed selection may not match the matrix
1423  * that was set when transform started.
1424  * - Inspecting the selection for every update is expensive (for *every* redraw).
1425  *
1426  * Instead, use #transform_apply_matrix to transform `rv3d->twmat` or the final scale value
1427  * when scaling.
1428  */
1429  if (false) {
1430  struct TransformBounds tbounds;
1431 
1433  &(struct TransformCalcParams){
1434  .use_only_center = true,
1435  },
1436  &tbounds)) {
1437  gizmo_prepare_mat(C, rv3d, &tbounds);
1438  for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
1439  WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
1440  }
1441  }
1442  }
1443  else {
1444  GizmoGroup *ggd = gzgroup->customdata;
1445 
1446  short axis_type = 0;
1447  MAN_ITER_AXES_BEGIN (axis, axis_idx) {
1448  if (axis == widget) {
1449  axis_type = gizmo_get_axis_type(axis_idx);
1450  break;
1451  }
1452  }
1454 
1455  /* Showing axes which aren't being manipulated doesn't always work so well.
1456  *
1457  * For rotate: global axis will reset after finish.
1458  * Also, gimbal axis isn't properly recalculated while transforming.
1459  */
1460  if (axis_type == MAN_AXES_ROTATE) {
1461  MAN_ITER_AXES_BEGIN (axis, axis_idx) {
1462  if (axis == widget) {
1463  continue;
1464  }
1465 
1466  bool is_plane_dummy;
1467  const uint aidx_norm = gizmo_orientation_axis(axis_idx, &is_plane_dummy);
1468  /* Always show the axis-aligned handle as it's distracting when it's disabled. */
1469  if (aidx_norm == 3) {
1470  continue;
1471  }
1473  }
1475  }
1476 
1477  wmWindow *win = CTX_wm_window(C);
1478  wmOperator *op = NULL;
1479  for (int i = 0; i < widget->op_data_len; i++) {
1480  wmGizmoOpElem *gzop = WM_gizmo_operator_get(widget, i);
1481  op = WM_operator_find_modal_by_type(win, gzop->type);
1482  if (op != NULL) {
1483  break;
1484  }
1485  }
1486 
1487  if (op != NULL) {
1488  float twmat[4][4];
1489  float scale_buf[3];
1490  float *scale = NULL;
1491  bool update = false;
1492  copy_m4_m4(twmat, rv3d->twmat);
1493 
1494  if (axis_type == MAN_AXES_SCALE) {
1495  scale = scale_buf;
1496  transform_final_value_get(op->customdata, scale, 3);
1497  update = true;
1498  }
1499  else if (axis_type == MAN_AXES_ROTATE) {
1501  if (widget != ggd->gizmos[MAN_AXIS_ROT_C]) {
1502  ggd->rotation *= -1;
1503  }
1504  RNA_float_set(
1505  widget->ptr, "incremental_angle", transform_snap_increment_get(op->customdata));
1506  }
1507  else if (transform_apply_matrix(op->customdata, twmat)) {
1508  update = true;
1509  }
1510 
1511  if (update) {
1512  gizmo_refresh_from_matrix(gzgroup, twmat, scale);
1514  }
1515  }
1516  }
1517 
1518  return OPERATOR_RUNNING_MODAL;
1519 }
1520 
1522 {
1523  struct {
1524  wmOperatorType *translate, *rotate, *trackball, *resize;
1525  } ot_store = {NULL};
1526  GizmoGroup *ggd = gzgroup->customdata;
1527 
1528  MAN_ITER_AXES_BEGIN (axis, axis_idx) {
1529  const short axis_type = gizmo_get_axis_type(axis_idx);
1530  bool constraint_axis[3] = {1, 0, 0};
1531  PointerRNA *ptr = NULL;
1532 
1533  gizmo_get_axis_constraint(axis_idx, constraint_axis);
1534 
1535  /* custom handler! */
1537 
1538  switch (axis_idx) {
1539  case MAN_AXIS_TRANS_X:
1540  case MAN_AXIS_TRANS_Y:
1541  case MAN_AXIS_TRANS_Z:
1542  case MAN_AXIS_SCALE_X:
1543  case MAN_AXIS_SCALE_Y:
1544  case MAN_AXIS_SCALE_Z:
1545  if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
1546  int draw_options = 0;
1548  draw_options |= ED_GIZMO_ARROW_DRAW_FLAG_STEM;
1549  }
1550  RNA_enum_set(axis->ptr, "draw_options", draw_options);
1551  }
1552 
1554  break;
1555  case MAN_AXIS_ROT_X:
1556  case MAN_AXIS_ROT_Y:
1557  case MAN_AXIS_ROT_Z:
1558  /* increased line width for better display */
1561  break;
1562  case MAN_AXIS_TRANS_XY:
1563  case MAN_AXIS_TRANS_YZ:
1564  case MAN_AXIS_TRANS_ZX:
1565  case MAN_AXIS_SCALE_XY:
1566  case MAN_AXIS_SCALE_YZ:
1567  case MAN_AXIS_SCALE_ZX: {
1568  const float ofs[3] = {MAN_AXIS_SCALE_PLANE_OFFSET, MAN_AXIS_SCALE_PLANE_OFFSET, 0.0f};
1572  break;
1573  }
1574  case MAN_AXIS_TRANS_C:
1575  case MAN_AXIS_ROT_C:
1576  case MAN_AXIS_SCALE_C:
1577  case MAN_AXIS_ROT_T:
1579  if (axis_idx == MAN_AXIS_ROT_T) {
1581  }
1582  else if (axis_idx == MAN_AXIS_ROT_C) {
1584  WM_gizmo_set_scale(axis, 1.2f);
1585  }
1586  else if (axis_idx == MAN_AXIS_SCALE_C) {
1587  WM_gizmo_set_scale(axis, 1.2f);
1588  }
1589  else {
1590  WM_gizmo_set_scale(axis, 0.2f);
1591  }
1592  break;
1593  }
1594 
1595  switch (axis_type) {
1596  case MAN_AXES_TRANSLATE:
1597  if (ot_store.translate == NULL) {
1598  ot_store.translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
1599  }
1600  ptr = WM_gizmo_operator_set(axis, 0, ot_store.translate, NULL);
1601  break;
1602  case MAN_AXES_ROTATE: {
1603  wmOperatorType *ot_rotate;
1604  if (axis_idx == MAN_AXIS_ROT_T) {
1605  if (ot_store.trackball == NULL) {
1606  ot_store.trackball = WM_operatortype_find("TRANSFORM_OT_trackball", true);
1607  }
1608  ot_rotate = ot_store.trackball;
1609  }
1610  else {
1611  if (ot_store.rotate == NULL) {
1612  ot_store.rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true);
1613  }
1614  ot_rotate = ot_store.rotate;
1615  }
1616  ptr = WM_gizmo_operator_set(axis, 0, ot_rotate, NULL);
1617  break;
1618  }
1619  case MAN_AXES_SCALE: {
1620  if (ot_store.resize == NULL) {
1621  ot_store.resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
1622  }
1623  ptr = WM_gizmo_operator_set(axis, 0, ot_store.resize, NULL);
1624  break;
1625  }
1626  }
1627 
1628  if (ptr) {
1629  PropertyRNA *prop;
1630  if (ELEM(true, UNPACK3(constraint_axis))) {
1631  if ((prop = RNA_struct_find_property(ptr, "constraint_axis"))) {
1632  RNA_property_boolean_set_array(ptr, prop, constraint_axis);
1633  }
1634  }
1635 
1636  RNA_boolean_set(ptr, "release_confirm", 1);
1637  }
1638  }
1640 }
1641 
1642 static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *gzgroup)
1643 {
1644  GizmoGroup *ggd = gizmogroup_init(gzgroup);
1645 
1646  gzgroup->customdata = ggd;
1647 
1648  {
1649  ScrArea *area = CTX_wm_area(C);
1650  const bToolRef *tref = area->runtime.tool;
1651 
1652  ggd->twtype = 0;
1653  if (tref && STREQ(tref->idname, "builtin.move")) {
1655  }
1656  else if (tref && STREQ(tref->idname, "builtin.rotate")) {
1658  }
1659  else if (tref && STREQ(tref->idname, "builtin.scale")) {
1661  }
1662  else if (tref && STREQ(tref->idname, "builtin.transform")) {
1665  }
1666  else {
1667  /* This is also correct logic for 'builtin.transform', no special check needed. */
1668  /* Setup all gizmos, they can be toggled via 'ToolSettings.gizmo_flag' */
1671  ggd->use_twtype_refresh = true;
1672  }
1673  BLI_assert(ggd->twtype != 0);
1674  ggd->twtype_init = ggd->twtype;
1675  }
1676 
1677  /* *** set properties for axes *** */
1679 }
1680 
1688  const float twmat[4][4],
1689  const float scale[3])
1690 {
1691  GizmoGroup *ggd = gzgroup->customdata;
1692 
1693  MAN_ITER_AXES_BEGIN (axis, axis_idx) {
1694  const short axis_type = gizmo_get_axis_type(axis_idx);
1695  const int aidx_norm = gizmo_orientation_axis(axis_idx, NULL);
1696 
1697  WM_gizmo_set_matrix_location(axis, twmat[3]);
1698  switch (axis_idx) {
1699  case MAN_AXIS_TRANS_X:
1700  case MAN_AXIS_TRANS_Y:
1701  case MAN_AXIS_TRANS_Z:
1702  case MAN_AXIS_SCALE_X:
1703  case MAN_AXIS_SCALE_Y:
1704  case MAN_AXIS_SCALE_Z: {
1705  float start_co[3] = {0.0f, 0.0f, 0.0f};
1706  float len;
1707 
1708  gizmo_line_range(ggd->twtype, axis_type, &start_co[2], &len);
1709 
1710  const float *z_axis = twmat[aidx_norm];
1711  if (axis_type == MAN_AXES_SCALE) {
1712  /* Scale handles are cubes that don't look right when not aligned with other axes.
1713  * This is noticeable when the axis is rotated to something besides the global-axis. */
1714  const int aidx_norm_y = (aidx_norm + 2) % 3;
1715  const float *y_axis = twmat[aidx_norm_y];
1716  WM_gizmo_set_matrix_rotation_from_yz_axis(axis, y_axis, z_axis);
1717  }
1718  else {
1720  }
1721 
1722  if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
1723  if (ggd->twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
1724  /* Avoid rotate and translate arrows overlap. */
1725  start_co[2] += 0.215f;
1726  }
1727  }
1728 
1729  if (scale) {
1730  if (axis_type == MAN_AXES_SCALE) {
1731  len = ((start_co[2] + len) * scale[aidx_norm]) - start_co[2];
1732  }
1733  }
1734 
1735  RNA_float_set(axis->ptr, "length", len);
1736 
1737  WM_gizmo_set_matrix_offset_location(axis, start_co);
1738 
1740 
1741  break;
1742  }
1743  case MAN_AXIS_ROT_X:
1744  case MAN_AXIS_ROT_Y:
1745  case MAN_AXIS_ROT_Z:
1746  case MAN_AXIS_ROT_C: {
1747  if (axis_idx != MAN_AXIS_ROT_C) {
1748  WM_gizmo_set_matrix_rotation_from_z_axis(axis, twmat[aidx_norm]);
1749  }
1750 
1751  /* Remove #ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE. It is used only for modal drawing. */
1752  PropertyRNA *prop = RNA_struct_find_property(axis->ptr, "draw_options");
1753  RNA_property_enum_set(axis->ptr,
1754  prop,
1755  RNA_property_enum_get(axis->ptr, prop) &
1757  } break;
1758  case MAN_AXIS_TRANS_XY:
1759  case MAN_AXIS_TRANS_YZ:
1760  case MAN_AXIS_TRANS_ZX:
1761  case MAN_AXIS_SCALE_XY:
1762  case MAN_AXIS_SCALE_YZ:
1763  case MAN_AXIS_SCALE_ZX: {
1764  const int aidx_norm_x = (aidx_norm + 1) % 3;
1765  const int aidx_norm_y = (aidx_norm + 2) % 3;
1766  const float *y_axis = twmat[aidx_norm_y];
1767  const float *z_axis = twmat[aidx_norm];
1768  WM_gizmo_set_matrix_rotation_from_yz_axis(axis, y_axis, z_axis);
1769 
1770  if (axis_type == MAN_AXES_SCALE) {
1772  if (scale) {
1773  ofs[0] *= scale[aidx_norm_x];
1774  ofs[1] *= scale[aidx_norm_y];
1775  }
1777  }
1778  break;
1779  }
1780  }
1781  }
1783 
1784  /* Ensure rotate disks don't overlap scale arrows, especially in ortho view. */
1785  float rotate_select_bias = 0.0f;
1787  rotate_select_bias = -2.0f;
1788  }
1789  for (int i = MAN_AXIS_RANGE_ROT_START; i < MAN_AXIS_RANGE_ROT_END; i++) {
1790  ggd->gizmos[i]->select_bias = rotate_select_bias;
1791  }
1792 }
1793 
1794 static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup)
1795 {
1796  ARegion *region = CTX_wm_region(C);
1797 
1798  {
1799  wmGizmo *gz = WM_gizmomap_get_modal(region->gizmo_map);
1800  if (gz && gz->parent_gzgroup == gzgroup) {
1801  return;
1802  }
1803  }
1804 
1805  GizmoGroup *ggd = gzgroup->customdata;
1807  ScrArea *area = CTX_wm_area(C);
1808  View3D *v3d = area->spacedata.first;
1809  RegionView3D *rv3d = region->regiondata;
1810  struct TransformBounds tbounds;
1811 
1812  if (ggd->use_twtype_refresh) {
1813  ggd->twtype = v3d->gizmo_show_object & ggd->twtype_init;
1814  if (ggd->twtype != ggd->twtype_prev) {
1815  ggd->twtype_prev = ggd->twtype;
1817  }
1818  }
1819 
1820  const int orient_index = BKE_scene_orientation_get_index_from_flag(scene, ggd->twtype_init);
1821 
1822  /* skip, we don't draw anything anyway */
1824  &(struct TransformCalcParams){
1825  .use_only_center = true,
1826  .orientation_index = orient_index + 1,
1827  },
1828  &tbounds) == 0))) {
1829  return;
1830  }
1831 
1832  gizmo_prepare_mat(C, rv3d, &tbounds);
1833 
1834  gizmo_refresh_from_matrix(gzgroup, rv3d->twmat, NULL);
1835 }
1836 
1838  wmGizmoGroup *gzgroup,
1839  struct wmMsgBus *mbus)
1840 {
1842  bScreen *screen = CTX_wm_screen(C);
1843  ScrArea *area = CTX_wm_area(C);
1844  ARegion *region = CTX_wm_region(C);
1846  gzgroup, mbus, scene, screen, area, region, VIEW3D_GGT_xform_gizmo);
1847 }
1848 
1850 {
1851  GizmoGroup *ggd = gzgroup->customdata;
1852  // ScrArea *area = CTX_wm_area(C);
1853  ARegion *region = CTX_wm_region(C);
1854  // View3D *v3d = area->spacedata.first;
1855  RegionView3D *rv3d = region->regiondata;
1856  float viewinv_m3[3][3];
1857  copy_m3_m4(viewinv_m3, rv3d->viewinv);
1858  float idot[3];
1859 
1860  /* Re-calculate hidden unless modal. */
1861  bool is_modal = false;
1862  {
1863  wmGizmo *gz = WM_gizmomap_get_modal(region->gizmo_map);
1864  if (gz && gz->parent_gzgroup == gzgroup) {
1865  is_modal = true;
1866  }
1867  }
1868 
1869  /* when looking through a selected camera, the gizmo can be at the
1870  * exact same position as the view, skip so we don't break selection */
1871  if (ggd->all_hidden || fabsf(ED_view3d_pixel_size(rv3d, rv3d->twmat[3])) < 5e-7f) {
1872  MAN_ITER_AXES_BEGIN (axis, axis_idx) {
1873  if (!is_modal) {
1875  }
1876  }
1878  return;
1879  }
1880  gizmo_get_idot(rv3d, idot);
1881 
1882  /* *** set properties for axes *** */
1883  MAN_ITER_AXES_BEGIN (axis, axis_idx) {
1884  const short axis_type = gizmo_get_axis_type(axis_idx);
1885  /* XXX maybe unset _HIDDEN flag on redraw? */
1886  if (gizmo_is_axis_visible(rv3d, ggd->twtype, idot, axis_type, axis_idx)) {
1887  if (!is_modal) {
1889  }
1890  }
1891  else {
1892  if (!is_modal) {
1894  }
1895  continue;
1896  }
1897 
1898  float color[4], color_hi[4];
1899  gizmo_get_axis_color(axis_idx, idot, color, color_hi);
1902 
1903  if (!is_modal) {
1904  switch (axis_idx) {
1905  case MAN_AXIS_TRANS_C:
1906  case MAN_AXIS_ROT_C:
1907  case MAN_AXIS_SCALE_C:
1908  case MAN_AXIS_ROT_T:
1910  break;
1911  }
1912  }
1913  }
1915 
1916  /* Refresh handled above when using view orientation. */
1917  if (!equals_m3m3(viewinv_m3, ggd->prev.viewinv_m3)) {
1918  {
1921  scene, ggd->twtype_init);
1922  switch (orient_slot->type) {
1923  case V3D_ORIENT_VIEW: {
1924  WIDGETGROUP_gizmo_refresh(C, gzgroup);
1925  break;
1926  }
1927  }
1928  }
1929  copy_m3_m4(ggd->prev.viewinv_m3, rv3d->viewinv);
1930  }
1931 }
1932 
1934  wmGizmoGroup *gzgroup,
1935  wmGizmo *gz,
1936  const wmEvent *event)
1937 {
1938 
1939  GizmoGroup *ggd = gzgroup->customdata;
1940 
1941  /* Support gizmo specific orientation. */
1942  if (gz != ggd->gizmos[MAN_AXIS_ROT_T]) {
1944  wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
1945  PointerRNA *ptr = &gzop->ptr;
1946  PropertyRNA *prop_orient_type = RNA_struct_find_property(ptr, "orient_type");
1948  scene, ggd->twtype_init);
1949  if ((gz == ggd->gizmos[MAN_AXIS_ROT_C]) ||
1950  (orient_slot == &scene->orientation_slots[SCE_ORIENT_DEFAULT])) {
1951  /* #MAN_AXIS_ROT_C always uses the #V3D_ORIENT_VIEW orientation,
1952  * optionally we could set this orientation instead of unset the property. */
1953  RNA_property_unset(ptr, prop_orient_type);
1954  }
1955  else {
1956  /* TODO: APIfunction */
1957  int index = BKE_scene_orientation_slot_get_index(orient_slot);
1958  RNA_property_enum_set(ptr, prop_orient_type, index);
1959  }
1960  }
1961 
1962  /* Support shift click to constrain axis. */
1963  const int axis_idx = BLI_array_findindex(ggd->gizmos, ARRAY_SIZE(ggd->gizmos), &gz);
1964  int axis = -1;
1965  switch (axis_idx) {
1966  case MAN_AXIS_TRANS_X:
1967  case MAN_AXIS_TRANS_Y:
1968  case MAN_AXIS_TRANS_Z:
1969  axis = axis_idx - MAN_AXIS_TRANS_X;
1970  break;
1971  case MAN_AXIS_SCALE_X:
1972  case MAN_AXIS_SCALE_Y:
1973  case MAN_AXIS_SCALE_Z:
1974  axis = axis_idx - MAN_AXIS_SCALE_X;
1975  break;
1976  }
1977 
1978  if (axis != -1) {
1979  /* Swap single axis for two-axis constraint. */
1980  const bool flip = (event->modifier & KM_SHIFT) != 0;
1981  BLI_assert(axis_idx != -1);
1982  const short axis_type = gizmo_get_axis_type(axis_idx);
1983  if (axis_type != MAN_AXES_ROTATE) {
1984  wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
1985  PointerRNA *ptr = &gzop->ptr;
1986  PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
1987  if (prop_constraint_axis) {
1988  bool constraint[3] = {false};
1989  constraint[axis] = true;
1990  if (flip) {
1991  for (int i = 0; i < ARRAY_SIZE(constraint); i++) {
1992  constraint[i] = !constraint[i];
1993  }
1994  }
1995  RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
1996  }
1997  }
1998  }
2001  gz->matrix_basis[2],
2002  gz->matrix_basis[3],
2003  (float[2]){UNPACK2(event->mval)},
2004  gz->matrix_basis);
2005  PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "draw_options");
2008  RNA_float_set(gz->ptr, "incremental_angle", 0.0f);
2009  }
2010 }
2011 
2013 {
2014  if (v3d->gizmo_flag & V3D_GIZMO_HIDE) {
2015  return false;
2016  }
2017  if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
2018  return false;
2019  }
2020  return true;
2021 }
2022 
2023 static bool WIDGETGROUP_gizmo_poll_context(const struct bContext *C,
2024  struct wmGizmoGroupType *UNUSED(gzgt))
2025 {
2026  ScrArea *area = CTX_wm_area(C);
2027  View3D *v3d = area->spacedata.first;
2028  if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
2029  return false;
2030  }
2031 
2032  const bToolRef *tref = area->runtime.tool;
2033  if (v3d->gizmo_flag & V3D_GIZMO_HIDE_CONTEXT) {
2034  return false;
2035  }
2037  V3D_GIZMO_SHOW_OBJECT_SCALE)) == 0) {
2038  return false;
2039  }
2040 
2041  /* Don't show if the tool has a gizmo. */
2042  if (tref && tref->runtime && tref->runtime->gizmo_group[0]) {
2043  return false;
2044  }
2045  return true;
2046 }
2047 
2048 static bool WIDGETGROUP_gizmo_poll_tool(const struct bContext *C, struct wmGizmoGroupType *gzgt)
2049 {
2051  return false;
2052  }
2053 
2054  ScrArea *area = CTX_wm_area(C);
2055  View3D *v3d = area->spacedata.first;
2056  if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
2057  return false;
2058  }
2059 
2060  if (v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) {
2061  return false;
2062  }
2063 
2064  return true;
2065 }
2066 
2067 /* Expose as multiple gizmos so tools use one, persistent context another.
2068  * Needed because they use different options which isn't so simple to dynamically update. */
2069 
2071 {
2072  gzgt->name = "3D View: Transform Gizmo";
2073  gzgt->idname = "VIEW3D_GGT_xform_gizmo";
2074 
2077 
2080 
2088 
2089  static const EnumPropertyItem rna_enum_gizmo_items[] = {
2090  {V3D_GIZMO_SHOW_OBJECT_TRANSLATE, "TRANSLATE", 0, "Move", ""},
2091  {V3D_GIZMO_SHOW_OBJECT_ROTATE, "ROTATE", 0, "Rotate", ""},
2092  {V3D_GIZMO_SHOW_OBJECT_SCALE, "SCALE", 0, "Scale", ""},
2093  {0, "NONE", 0, "None", ""},
2094  {0, NULL, 0, NULL, NULL},
2095  };
2096  RNA_def_enum(gzgt->srna,
2097  "drag_action",
2098  rna_enum_gizmo_items,
2100  "Drag Action",
2101  "");
2102 }
2103 
2105 {
2106  gzgt->name = "3D View: Transform Gizmo Context";
2107  gzgt->idname = "VIEW3D_GGT_xform_gizmo_context";
2108 
2111 
2119 }
2120 
2123 /* -------------------------------------------------------------------- */
2129  /* Only for view orientation. */
2130  struct {
2131  float viewinv_m3[3][3];
2132  } prev;
2133 };
2134 
2136 {
2138  return false;
2139  }
2140  View3D *v3d = CTX_wm_view3d(C);
2142  return false;
2143  }
2144  if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
2145  return false;
2146  }
2147  return true;
2148 }
2149 
2151 {
2152  struct XFormCageWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormCageWidgetGroup),
2153  __func__);
2154  const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
2155  xgzgroup->gizmo = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
2156  wmGizmo *gz = xgzgroup->gizmo;
2157 
2158  RNA_enum_set(gz->ptr,
2159  "transform",
2161 
2162  gz->color[0] = 1;
2163  gz->color_hi[0] = 1;
2164 
2165  gzgroup->customdata = xgzgroup;
2166 
2167  {
2168  wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
2169  PointerRNA *ptr;
2170 
2171  /* assign operator */
2172  PropertyRNA *prop_release_confirm = NULL;
2173  PropertyRNA *prop_constraint_axis = NULL;
2174 
2176  for (int x = 0; x < 3; x++) {
2177  for (int y = 0; y < 3; y++) {
2178  for (int z = 0; z < 3; z++) {
2179  const bool constraint[3] = {x != 1, y != 1, z != 1};
2180  ptr = WM_gizmo_operator_set(gz, i, ot_resize, NULL);
2181  if (prop_release_confirm == NULL) {
2182  prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
2183  prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
2184  }
2185  RNA_property_boolean_set(ptr, prop_release_confirm, true);
2186  RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
2187  i++;
2188  }
2189  }
2190  }
2191  }
2192 }
2193 
2195 {
2196  ARegion *region = CTX_wm_region(C);
2197  RegionView3D *rv3d = region->regiondata;
2199 
2200  struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
2201  wmGizmo *gz = xgzgroup->gizmo;
2202 
2203  struct TransformBounds tbounds;
2204 
2206 
2208  &(struct TransformCalcParams){
2209  .use_local_axis = true,
2210  .orientation_index = orient_index + 1,
2211  },
2212  &tbounds) == 0) ||
2213  equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max)) {
2215  }
2216  else {
2217  if (tbounds.use_matrix_space) {
2218  copy_m4_m4(gz->matrix_space, tbounds.matrix_space);
2219  }
2220  else {
2221  unit_m4(gz->matrix_space);
2222  }
2223 
2224  gizmo_prepare_mat(C, rv3d, &tbounds);
2225 
2226  WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
2228 
2229  float dims[3];
2230  sub_v3_v3v3(dims, rv3d->tw_axis_max, rv3d->tw_axis_min);
2231  RNA_float_set_array(gz->ptr, "dimensions", dims);
2232  mul_v3_fl(dims, 0.5f);
2233 
2235  mid_v3_v3v3(gz->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min);
2236  mul_m3_v3(rv3d->tw_axis_matrix, gz->matrix_offset[3]);
2237 
2238  float matrix_offset_global[4][4];
2239  mul_m4_m4m4(matrix_offset_global, gz->matrix_space, gz->matrix_offset);
2240 
2241  PropertyRNA *prop_center_override = NULL;
2242  float center[3];
2243  float center_global[3];
2245  for (int x = 0; x < 3; x++) {
2246  center[0] = (float)(1 - x) * dims[0];
2247  for (int y = 0; y < 3; y++) {
2248  center[1] = (float)(1 - y) * dims[1];
2249  for (int z = 0; z < 3; z++) {
2250  center[2] = (float)(1 - z) * dims[2];
2251  struct wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, i);
2252  if (prop_center_override == NULL) {
2253  prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
2254  }
2255  mul_v3_m4v3(center_global, matrix_offset_global, center);
2256  RNA_property_float_set_array(&gzop->ptr, prop_center_override, center_global);
2257  i++;
2258  }
2259  }
2260  }
2261  }
2262 
2263  /* Needed to test view orientation changes. */
2264  copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
2265 }
2266 
2268  wmGizmoGroup *gzgroup,
2269  struct wmMsgBus *mbus)
2270 {
2272  bScreen *screen = CTX_wm_screen(C);
2273  ScrArea *area = CTX_wm_area(C);
2274  ARegion *region = CTX_wm_region(C);
2275  gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, area, region, VIEW3D_GGT_xform_cage);
2276 }
2277 
2279 {
2280  struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
2281 
2283  {
2287  switch (orient_slot->type) {
2288  case V3D_ORIENT_VIEW: {
2289  float viewinv_m3[3][3];
2290  copy_m3_m4(viewinv_m3, rv3d->viewinv);
2291  if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
2292  /* Take care calling refresh from draw_prepare,
2293  * this should be OK because it's only adjusting the cage orientation. */
2295  }
2296  break;
2297  }
2298  }
2299  }
2300 }
2301 
2303 {
2304  gzgt->name = "Transform Cage";
2305  gzgt->idname = "VIEW3D_GGT_xform_cage";
2306 
2309 
2312 
2319 }
2320 
2323 /* -------------------------------------------------------------------- */
2328  wmGizmo *gizmo[3][2];
2331 
2332  /* Only for view orientation. */
2333  struct {
2334  float viewinv_m3[3][3];
2335  } prev;
2336 };
2337 
2339 {
2341  return false;
2342  }
2343  View3D *v3d = CTX_wm_view3d(C);
2345  return false;
2346  }
2347  return true;
2348 }
2349 
2351 {
2352  struct XFormShearWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormShearWidgetGroup),
2353  __func__);
2354  const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
2355  wmOperatorType *ot_shear = WM_operatortype_find("TRANSFORM_OT_shear", true);
2356 
2357  float axis_color[3][3];
2358  for (int i = 0; i < 3; i++) {
2359  UI_GetThemeColor3fv(TH_AXIS_X + i, axis_color[i]);
2360  }
2361 
2362  for (int i = 0; i < 3; i++) {
2363  for (int j = 0; j < 2; j++) {
2364  wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
2365  RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
2366  const int i_ortho_a = (i + j + 1) % 3;
2367  const int i_ortho_b = (i + (1 - j) + 1) % 3;
2368  interp_v3_v3v3(gz->color, axis_color[i_ortho_a], axis_color[i_ortho_b], 0.75f);
2369  gz->color[3] = 0.5f;
2370  PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, NULL);
2371  RNA_boolean_set(ptr, "release_confirm", 1);
2372  xgzgroup->gizmo[i][j] = gz;
2373  }
2374  }
2375 
2376  for (int i = 0; i < 4; i++) {
2377  wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
2378  RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
2379  RNA_enum_set(gz->ptr, "draw_options", 0); /* No stem. */
2380  copy_v3_fl(gz->color, 1.0f);
2381  gz->color[3] = 0.5f;
2383  PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, NULL);
2384  RNA_boolean_set(ptr, "release_confirm", 1);
2385  xgzgroup->gizmo_view[i] = gz;
2386 
2387  /* Unlike the other gizmos, this never changes so can be set on setup. */
2388  wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
2389  RNA_enum_set(&gzop->ptr, "orient_type", V3D_ORIENT_VIEW);
2390 
2391  RNA_enum_set(&gzop->ptr, "orient_axis", 2);
2392  RNA_enum_set(&gzop->ptr, "orient_axis_ortho", ((i % 2) ? 0 : 1));
2393  }
2394 
2395  gzgroup->customdata = xgzgroup;
2396 }
2397 
2399 {
2401  ARegion *region = CTX_wm_region(C);
2402  RegionView3D *rv3d = region->regiondata;
2403 
2404  struct XFormShearWidgetGroup *xgzgroup = gzgroup->customdata;
2405  struct TransformBounds tbounds;
2406 
2407  /* Needed to test view orientation changes. */
2408  copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
2409 
2412  const int orient_index = BKE_scene_orientation_slot_get_index(orient_slot);
2413 
2415  &(struct TransformCalcParams){
2416  .use_local_axis = false,
2417  .orientation_index = orient_index + 1,
2418  },
2419  &tbounds) == 0) {
2420  for (int i = 0; i < 3; i++) {
2421  for (int j = 0; j < 2; j++) {
2422  wmGizmo *gz = xgzgroup->gizmo[i][j];
2424  }
2425  }
2426 
2427  for (int i = 0; i < 4; i++) {
2428  wmGizmo *gz = xgzgroup->gizmo_view[i];
2430  }
2431  }
2432  else {
2433  gizmo_prepare_mat(C, rv3d, &tbounds);
2434  for (int i = 0; i < 3; i++) {
2435  for (int j = 0; j < 2; j++) {
2436  wmGizmo *gz = xgzgroup->gizmo[i][j];
2437  WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
2439 
2440  wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
2441  const int i_ortho_a = (i + j + 1) % 3;
2442  const int i_ortho_b = (i + (1 - j) + 1) % 3;
2443  WM_gizmo_set_matrix_rotation_from_yz_axis(gz, rv3d->twmat[i_ortho_a], rv3d->twmat[i]);
2444  WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
2445 
2446  RNA_float_set_array(&gzop->ptr, "orient_matrix", &tbounds.axis[0][0]);
2447  RNA_enum_set(&gzop->ptr, "orient_type", orient_slot->type);
2448 
2449  RNA_enum_set(&gzop->ptr, "orient_axis", i_ortho_b);
2450  RNA_enum_set(&gzop->ptr, "orient_axis_ortho", i_ortho_a);
2451 
2452  mul_v3_fl(gz->matrix_basis[0], 0.5f);
2453  mul_v3_fl(gz->matrix_basis[1], 6.0f);
2454  }
2455  }
2456 
2457  for (int i = 0; i < 4; i++) {
2458  wmGizmo *gz = xgzgroup->gizmo_view[i];
2459  WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
2460  }
2461  }
2462 }
2463 
2465  wmGizmoGroup *gzgroup,
2466  struct wmMsgBus *mbus)
2467 {
2469  bScreen *screen = CTX_wm_screen(C);
2470  ScrArea *area = CTX_wm_area(C);
2471  ARegion *region = CTX_wm_region(C);
2473  gzgroup, mbus, scene, screen, area, region, VIEW3D_GGT_xform_shear);
2474 }
2475 
2477 {
2478  struct XFormShearWidgetGroup *xgzgroup = gzgroup->customdata;
2480  {
2482  /* Shear is like rotate, use the rotate setting. */
2485  switch (orient_slot->type) {
2486  case V3D_ORIENT_VIEW: {
2487  float viewinv_m3[3][3];
2488  copy_m3_m4(viewinv_m3, rv3d->viewinv);
2489  if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
2490  /* Take care calling refresh from draw_prepare,
2491  * this should be OK because it's only adjusting the cage orientation. */
2493  }
2494  break;
2495  }
2496  }
2497  }
2498 
2499  for (int i = 0; i < 4; i++) {
2500  const float outer_thin = 0.3f;
2501  const float outer_offset = 1.0f / 0.3f;
2502  wmGizmo *gz = xgzgroup->gizmo_view[i];
2504  gz, rv3d->viewinv[(i + 1) % 2], rv3d->viewinv[i % 2]);
2505  if (i >= 2) {
2506  negate_v3(gz->matrix_basis[1]);
2507  negate_v3(gz->matrix_basis[2]);
2508  }
2509 
2510  /* No need for depth with view aligned gizmos. */
2511  mul_v3_fl(gz->matrix_basis[0], 0.0f);
2512  mul_v3_fl(gz->matrix_basis[1], 20.0f + ((1.0f / outer_thin) * 1.8f));
2513  mul_v3_fl(gz->matrix_basis[2], outer_thin);
2514  WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
2515  gz->matrix_offset[3][2] = outer_offset;
2516  }
2517 
2518  /* Basic ordering for drawing only. */
2519  {
2520  LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
2521  /* Since we have two pairs of each axis,
2522  * bias the values so gizmos that are orthogonal to the view get priority.
2523  * This means we never default to shearing along
2524  * the view axis in the case of an overlap. */
2525  float axis_order[3], axis_bias[3];
2526  copy_v3_v3(axis_order, gz->matrix_basis[2]);
2527  copy_v3_v3(axis_bias, gz->matrix_basis[1]);
2528  if (dot_v3v3(axis_bias, rv3d->viewinv[2]) < 0.0f) {
2529  negate_v3(axis_bias);
2530  }
2531  madd_v3_v3fl(axis_order, axis_bias, 0.01f);
2532  gz->temp.f = dot_v3v3(rv3d->viewinv[2], axis_order);
2533  }
2535  }
2536 }
2537 
2539 {
2540  gzgt->name = "Transform Shear";
2541  gzgt->idname = "VIEW3D_GGT_xform_shear";
2542 
2545 
2548 
2555 }
2556 
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct bGPdata * CTX_data_gpencil_data(const bContext *C)
Definition: context.c:1445
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct Depsgraph * CTX_data_expect_evaluated_depsgraph(const bContext *C)
Definition: context.c:1519
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:733
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:793
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
struct ListBase * BKE_curve_editNurbs_get(struct Curve *cu)
Definition: curve.cc:426
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:58
@ G_TRANSFORM_OBJ
Definition: BKE_global.h:247
@ G_TRANSFORM_EDIT
Definition: BKE_global.h:248
bool BKE_gpencil_layer_is_editable(const struct bGPDlayer *gpl)
void BKE_gpencil_layer_transform_matrix_get(const struct Depsgraph *depsgraph, struct Object *obact, struct bGPDlayer *gpl, float diff_mat[4][4])
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_pose_armature_get(struct Object *ob)
Definition: object.cc:2511
struct Object ** BKE_object_pose_array_get(struct ViewLayer *view_layer, struct View3D *v3d, unsigned int *r_objects_len)
Definition: object.cc:2598
const struct BoundBox * BKE_object_boundbox_get(struct Object *ob)
Definition: object.cc:3684
#define PEP_HIDE
#define PEK_SELECT
#define PEK_USE_WCO
int BKE_scene_orientation_slot_get_index(const struct TransformOrientationSlot *orient_slot)
int BKE_scene_orientation_get_index(struct Scene *scene, int slot_index)
Definition: scene.cc:2470
struct TransformOrientationSlot * BKE_scene_orientation_slot_get(struct Scene *scene, int slot_index)
Definition: scene.cc:2431
struct TransformOrientationSlot * BKE_scene_orientation_slot_get_from_flag(struct Scene *scene, int flag)
Definition: scene.cc:2439
int BKE_scene_orientation_get_index_from_flag(struct Scene *scene, int flag)
Definition: scene.cc:2476
Generic array manipulation API.
#define BLI_array_findindex(arr, arr_len, p)
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define ATTR_FALLTHROUGH
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void void BLI_listbase_sort(struct ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
#define M_PI_2
Definition: BLI_math_base.h:23
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void mul_m3_m3_pre(float R[3][3], const float A[3][3])
Definition: math_matrix.c:401
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:71
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void unit_m4(float m[4][4])
Definition: rct.c:1090
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:102
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void normalize_m3(float R[3][3]) ATTR_NONNULL()
Definition: math_matrix.c:1912
bool equals_m3m3(const float mat1[3][3], const float mat2[3][3])
Definition: math_matrix.c:2525
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
bool invert_m3(float R[3][3])
Definition: math_matrix.c:1171
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:388
void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], short order)
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
void mul_qt_v3(const float q[4], float r[3])
Definition: math_rotation.c:59
MINLINE void copy_v4_v4(float r[4], const float a[4])
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:867
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:237
void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3])
Definition: math_vector.c:707
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
unsigned int uint
Definition: BLI_sys_types.h:67
#define INIT_MINMAX(min, max)
#define ARRAY_SIZE(arr)
#define ARRAY_SET_ITEMS(...)
#define UNUSED(x)
#define UNPACK3(a)
#define ELEM(...)
#define IN_RANGE_INCL(a, b, c)
#define STREQ(a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ ROT_MODE_QUAT
@ ROT_MODE_AXISANGLE
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_TRANSFORM
@ BONE_EDITMODE_LOCKED
@ BONE_TIPSEL
@ BONE_CONNECTED
@ BONE_HINGE
@ CU_BEZIER
#define BEZT_ISSEL_IDX(bezt, i)
@ GP_CURVE_SELECT
@ GP_STROKE_SELECT
@ GP_DATA_STROKE_EDITMODE
#define GPENCIL_ANY_MODE(gpd)
#define GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)
@ GP_CURVE_POINT_SELECT
@ GP_SPOINT_SELECT
@ BASE_SELECTED
#define OB_MODE_ALL_PAINT
@ OB_MODE_PARTICLE_EDIT
@ OB_MODE_EDIT
@ OB_MODE_WEIGHT_PAINT
@ OB_MODE_SCULPT
@ OB_MODE_POSE
#define OB_MODE_ALL_SCULPT
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVES_LEGACY
@ OB_LOCK_ROTZ
@ OB_LOCK_ROT
@ OB_LOCK_SCALEZ
@ OB_LOCK_ROTX
@ OB_LOCK_SCALEX
@ OB_LOCK_LOCY
@ OB_LOCK_LOCZ
@ OB_LOCK_ROTY
@ OB_LOCK_SCALEY
@ OB_LOCK_LOC
@ OB_LOCK_LOCX
@ OB_LOCK_SCALE
#define BASE_SELECTED_EDITABLE(v3d, base)
#define OBEDIT_FROM_OBACT(ob)
#define BASACT(_view_layer)
#define OBACT(_view_layer)
@ SCE_ORIENT_DEFAULT
@ SCE_ORIENT_ROTATE
@ SCE_ORIENT_SCALE
@ RGN_TYPE_WINDOW
@ SPACE_VIEW3D
@ V3D_AROUND_ACTIVE
@ V3D_AROUND_CENTER_BOUNDS
@ V3D_AROUND_CURSOR
@ V3D_AROUND_CENTER_MEDIAN
@ V3D_AROUND_LOCAL_ORIGINS
@ V3D_ORIENT_GLOBAL
@ V3D_ORIENT_LOCAL
@ V3D_ORIENT_VIEW
@ V3D_ORIENT_CURSOR
@ V3D_ORIENT_GIMBAL
@ V3D_GIZMO_HIDE_TOOL
@ V3D_GIZMO_HIDE
@ V3D_GIZMO_HIDE_CONTEXT
@ V3D_GIZMO_SHOW_OBJECT_ROTATE
@ V3D_GIZMO_SHOW_OBJECT_SCALE
@ V3D_GIZMO_SHOW_OBJECT_TRANSLATE
@ CURVE_HANDLE_NONE
@ OPERATOR_RUNNING_MODAL
#define EBONE_VISIBLE(arm, ebone)
Definition: ED_armature.h:47
@ ED_GIZMO_ARROW_DRAW_FLAG_STEM
@ ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT
@ ED_GIZMO_DIAL_DRAW_FLAG_FILL
@ ED_GIZMO_DIAL_DRAW_FLAG_NOP
@ ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE
@ ED_GIZMO_DIAL_DRAW_FLAG_CLIP
@ ED_GIZMO_PRIMITIVE_STYLE_PLANE
@ ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z
@ ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE
@ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE
@ ED_GIZMO_ARROW_STYLE_BOX
@ ED_GIZMO_ARROW_STYLE_NORMAL
bool ED_gizmo_poll_or_unlink_delayed_from_tool(const struct bContext *C, struct wmGizmoGroupType *gzgt)
bool ED_object_calc_active_center(struct Object *ob, bool select_only, float r_center[3])
Definition: object_utils.c:112
struct PTCacheEdit * PE_get_current(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
void ED_region_tag_redraw_editor_overlays(struct ARegion *region)
Definition: area.c:690
@ TFM_ROTATION
Definition: ED_transform.h:31
short ED_transform_calc_orientation_from_type_ex(const struct Scene *scene, struct ViewLayer *view_layer, const struct View3D *v3d, const struct RegionView3D *rv3d, struct Object *ob, struct Object *obedit, short orientation_index, int pivot_point, float r_mat[3][3])
bool ED_view3d_win_to_3d_on_plane(const struct ARegion *region, const float plane[4], const float mval[2], bool do_clip, float r_out[3])
float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3])
void ED_view3d_global_to_vector(const struct RegionView3D *rv3d, const float coord[3], float vec[3])
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
#define C
Definition: RandGen.cpp:25
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1165
@ TH_GIZMO_VIEW_ALIGN
Definition: UI_resources.h:307
@ TH_AXIS_Y
Definition: UI_resources.h:301
@ TH_AXIS_X
Definition: UI_resources.h:300
@ TH_AXIS_Z
Definition: UI_resources.h:302
void UI_GetThemeColor4fv(int colorid, float col[4])
Definition: resources.c:1173
eWM_GizmoFlagTweak
Gizmo tweak flag. Bit-flag passed to gizmo while tweaking.
@ WM_GIZMO_HIDDEN
@ WM_GIZMO_DRAW_VALUE
@ WM_GIZMO_MOVE_CURSOR
@ WM_GIZMO_DRAW_HOVER
@ WM_GIZMO_DRAW_OFFSET_SCALE
@ WM_GIZMO_SELECT_BACKGROUND
@ WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE
@ WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP
@ WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK
@ WM_GIZMOGROUPTYPE_3D
@ WM_GIZMOGROUPTYPE_PERSISTENT
@ KM_SHIFT
Definition: WM_types.h:238
volatile int lock
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_VERTS_OF_MESH
ATTR_WARN_UNUSED_RESULT BMesh * bm
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
SIMD_FORCE_INLINE btVector3 rotate(const btVector3 &wAxis, const btScalar angle) const
Return a rotated version of this vector.
#define SELECT
Scene scene
const Depsgraph * depsgraph
int len
Definition: draw_manager.c:108
bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define G(x, y, z)
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned a[3]
Definition: RandGen.cpp:78
static void area(int d1, int d2, int e1, int e2, float weights[2])
static void update(bNodeTree *ntree)
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:4874
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
Definition: rna_access.c:3421
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
Definition: rna_access.c:2180
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:4968
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
Definition: rna_access.c:2978
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3402
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
Definition: rna_access.c:4992
void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5281
void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const bool *values)
Definition: rna_access.c:2304
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
unsigned int uint32_t
Definition: stdint.h:80
void * regiondata
struct wmGizmoMap * gizmo_map
struct BMesh * bm
Definition: BKE_editmesh.h:40
float co[3]
Definition: bmesh_class.h:87
int totvertsel
Definition: bmesh_class.h:298
uint8_t f1
float vec[4]
struct Base * next
short flag
struct Object * object
uint8_t f3
float vec[3][3]
uint8_t f1
uint8_t f2
float arm_mat[4][4]
float bone_mat[3][3]
float vec[8][3]
struct Lattice * latt
struct wmGizmo * gizmos[MAN_AXIS_LAST]
struct GizmoGroup::@612 prev
float viewinv_m3[3][3]
struct EditLatt * editlatt
struct BPoint * def
void * first
Definition: DNA_listBase.h:31
ListBase * editelems
struct Nurb * next
short type
BezTriple * bezt
BPoint * bp
struct bPose * pose
float imat[4][4]
float rot[3]
float obmat[4][4]
short rotmode
float rotAngle
float rotAxis[3]
short protectflag
struct Object * parent
struct SculptSession * sculpt
PTCacheEditPoint * points
float tw_axis_matrix[3][3]
float tw_axis_min[3]
float tw_axis_max[3]
float twmat[4][4]
float viewinv[4][4]
struct ToolSettings * toolsettings
View3DCursor cursor
TransformOrientationSlot orientation_slots[4]
float pivot_pos[3]
Definition: BKE_paint.h:612
char transform_pivot_point
float axis_min[3]
Definition: ED_transform.h:180
float axis[3][3]
Definition: ED_transform.h:179
float axis_max[3]
Definition: ED_transform.h:180
float matrix_space[4][4]
Definition: ED_transform.h:187
View3DOverlay overlay
char gizmo_flag
char gizmo_show_object
ListBase object_bases
struct XFormCageWidgetGroup::@613 prev
struct XFormShearWidgetGroup::@614 prev
ListBase * edbo
bGPDcurve_point * curve_points
ListBase layers
struct Bone * bone
struct bPoseChannel * parent
float pose_mat[4][4]
ListBase chanbase
char idname[64]
bToolRef_Runtime * runtime
short type
Definition: WM_types.h:678
wmGizmoGroupFnSetupKeymap setup_keymap
wmGizmoGroupFnMsgBusSubscribe message_subscribe
wmGizmoGroupFnRefresh refresh
wmGizmoGroupFnInit setup
const char * idname
wmGizmoGroupFnInvokePrepare invoke_prepare
eWM_GizmoFlagGroupTypeFlag flag
wmGizmoGroupFnPoll poll
struct StructRNA * srna
struct wmGizmoMapType_Params gzmap_params
const char * name
wmGizmoGroupFnDrawPrepare draw_prepare
ListBase gizmos
struct wmGizmoMap * parent_gzmap
PointerRNA ptr
struct wmOperatorType * type
struct wmGizmoProperty::@1185 custom_func
struct wmGizmoGroup * parent_gzgroup
float matrix_basis[4][4]
float select_bias
float matrix_offset[4][4]
float color_hi[4]
int op_data_len
float color[4]
struct PointerRNA * ptr
float matrix_space[4][4]
eWM_GizmoFlag flag
void transform_final_value_get(const TransInfo *t, float *value, const int value_num)
Definition: transform.c:2085
bool transform_apply_matrix(TransInfo *t, float mat[4][4])
Definition: transform.c:2076
conversion and adaptation of different datablocks to a common struct.
void transform_convert_pose_transflags_update(Object *ob, int mode, short around)
#define MAN_AXIS_RANGE_SCALE_START
#define MAN_AXIS_RANGE_ROT_END
static void WIDGETGROUP_xform_shear_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
static bool WIDGETGROUP_gizmo_poll_generic(View3D *v3d)
static bool test_rotmode_euler(short rotmode)
float max
void VIEW3D_GGT_xform_gizmo_context(wmGizmoGroupType *gzgt)
static void protectflag_to_drawflags(short protectflag, short *drawflags)
@ MAN_AXIS_LAST
@ MAN_AXIS_SCALE_X
@ MAN_AXIS_TRANS_ZX
@ MAN_AXIS_ROT_Z
@ MAN_AXIS_TRANS_Z
@ MAN_AXIS_SCALE_XY
@ MAN_AXIS_TRANS_XY
@ MAN_AXIS_ROT_T
@ MAN_AXIS_TRANS_YZ
@ MAN_AXIS_TRANS_C
@ MAN_AXIS_TRANS_Y
@ MAN_AXIS_SCALE_ZX
@ MAN_AXIS_ROT_X
@ MAN_AXIS_SCALE_C
@ MAN_AXIS_TRANS_X
@ MAN_AXIS_SCALE_Y
@ MAN_AXIS_SCALE_YZ
@ MAN_AXIS_ROT_C
@ MAN_AXIS_ROT_Y
@ MAN_AXIS_SCALE_Z
static bool WIDGETGROUP_gizmo_poll_context(const struct bContext *C, struct wmGizmoGroupType *UNUSED(gzgt))
void VIEW3D_GGT_xform_shear(wmGizmoGroupType *gzgt)
#define MAN_TRANS_C
#define MAN_SCALE_Z
static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *gzgroup)
static void gizmo_get_axis_color(const int axis_idx, const float idot[3], float r_col[4], float r_col_hi[4])
#define MAN_AXIS_SCALE_PLANE_OFFSET
#define MAN_ROT_X
static void calc_tw_center_with_matrix(struct TransformBounds *tbounds, const float co[3], const bool use_matrix, const float matrix[4][4])
float min
void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt)
#define MAN_SCALE_X
static void reset_tw_center(struct TransformBounds *tbounds)
static int gizmo_modal(bContext *C, wmGizmo *widget, const wmEvent *event, eWM_GizmoFlagTweak UNUSED(tweak_flag))
static void gizmo_get_idot(RegionView3D *rv3d, float r_idot[3])
static void rotation_get_fn(const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, void *value)
static void WIDGETGROUP_xform_shear_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *gzgroup)
static void protectflag_to_drawflags_pchan(RegionView3D *rv3d, const bPoseChannel *pchan, short orientation_index)
static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz, const wmEvent *event)
static void protectflag_to_drawflags_ebone(RegionView3D *rv3d, const EditBone *ebo)
static void WIDGETGROUP_xform_shear_message_subscribe(const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
struct GizmoGroup GizmoGroup
#define FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local)
#define GIZMO_NEW_PRIM(v, draw_style)
static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmGizmoGroupType *gzgt)
#define MAN_ROT_Y
static GizmoGroup * gizmogroup_init(wmGizmoGroup *gzgroup)
static void gizmo_prepare_mat(const bContext *C, RegionView3D *rv3d, const struct TransformBounds *tbounds)
#define MAN_ROT_C
static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *gzgroup)
#define MAN_ITER_AXES_END
static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
static void rotation_set_fn(const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, const void *value)
#define MAN_AXIS_RANGE_TRANS_END
static void gizmo_line_range(const int twtype, const short axis_type, float *r_start, float *r_len)
int ED_transform_calc_gizmo_stats(const bContext *C, const struct TransformCalcParams *params, struct TransformBounds *tbounds)
#define MAN_TRANS_X
static struct @609 g_tw_axis_range[2]
static void gizmo_get_axis_constraint(const int axis_idx, bool r_axis[3])
static bool gizmo_is_axis_visible(const RegionView3D *rv3d, const int twtype, const float idot[3], const int axis_type, const int axis_idx)
bool gimbal_axis_object(Object *ob, float gmat[3][3])
static void gizmo_3d_dial_matrixbasis_calc(const ARegion *region, float axis[3], float center_global[3], float mval_init[2], float r_mat_basis[4][4])
static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], const float angle)
#define GIZMO_NEW_ARROW(v, draw_style)
static void WIDGETGROUP_xform_cage_message_subscribe(const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
#define FOREACH_EDIT_OBJECT_END()
static void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup, struct wmMsgBus *mbus, Scene *scene, bScreen *screen, ScrArea *area, ARegion *region, const void *type_fn)
#define MAN_AXIS_RANGE_ROT_START
static bool WIDGETGROUP_xform_shear_poll(const bContext *C, wmGizmoGroupType *gzgt)
#define MAN_AXIS_SCALE_PLANE_SCALE
static void WIDGETGROUP_xform_shear_refresh(const bContext *C, wmGizmoGroup *gzgroup)
static uint gizmo_orientation_axis(const int axis_idx, bool *r_is_plane)
static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup)
#define MAN_AXIS_RANGE_SCALE_END
@ MAN_AXES_ROTATE
@ MAN_AXES_SCALE
@ MAN_AXES_TRANSLATE
@ MAN_AXES_ALL
static void WIDGETGROUP_gizmo_message_subscribe(const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
static void gizmo_refresh_from_matrix(wmGizmoGroup *gzgroup, const float twmat[4][4], const float scale[3])
#define MAN_ROT_Z
static short gizmo_get_axis_type(const int axis_idx)
static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
#define MAN_TRANS_Z
#define GIZMO_NEW_DIAL(v, draw_options)
static void calc_tw_center(struct TransformBounds *tbounds, const float co[3])
static wmGizmo * gizmo_get_axis_from_index(const GizmoGroup *ggd, const short axis_idx)
bool gimbal_axis_pose(Object *ob, const bPoseChannel *pchan, float gmat[3][3])
#define MAN_ITER_AXES_BEGIN(axis, axis_idx)
void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt)
#define MAN_SCALE_C
#define MAN_SCALE_Y
static bool WIDGETGROUP_gizmo_poll_tool(const struct bContext *C, struct wmGizmoGroupType *gzgt)
#define MAN_TRANS_Y
#define MAN_AXIS_RANGE_TRANS_START
float transform_snap_increment_get(const TransInfo *t)
wmOperator * WM_operator_find_modal_by_type(wmWindow *win, const wmOperatorType *ot)
@ TIMER
@ INBETWEEN_MOUSEMOVE
PointerRNA * ptr
Definition: wm_files.c:3480
void WM_gizmo_set_matrix_offset_location(wmGizmo *gz, const float offset[3])
Definition: wm_gizmo.c:299
void WM_gizmo_set_fn_custom_modal(struct wmGizmo *gz, wmGizmoFnModal fn)
Definition: wm_gizmo.c:348
PointerRNA * WM_gizmo_operator_set(wmGizmo *gz, int part_index, wmOperatorType *ot, IDProperty *properties)
Definition: wm_gizmo.c:203
void WM_gizmo_set_color_highlight(wmGizmo *gz, const float color_hi[4])
Definition: wm_gizmo.c:337
void WM_gizmo_set_line_width(wmGizmo *gz, const float line_width)
Definition: wm_gizmo.c:319
void WM_gizmo_set_matrix_rotation_from_yz_axis(wmGizmo *gz, const float y_axis[3], const float z_axis[3])
Definition: wm_gizmo.c:278
wmGizmo * WM_gizmo_new_ptr(const wmGizmoType *gzt, wmGizmoGroup *gzgroup, PointerRNA *properties)
Definition: wm_gizmo.c:81
void WM_gizmo_set_scale(wmGizmo *gz, const float scale)
Definition: wm_gizmo.c:314
void WM_gizmo_set_matrix_location(wmGizmo *gz, const float origin[3])
Definition: wm_gizmo.c:284
void WM_gizmo_set_flag(wmGizmo *gz, const int flag, const bool enable)
Definition: wm_gizmo.c:304
void WM_gizmo_set_matrix_rotation_from_z_axis(wmGizmo *gz, const float z_axis[3])
Definition: wm_gizmo.c:274
struct wmGizmoOpElem * WM_gizmo_operator_get(wmGizmo *gz, int part_index)
Definition: wm_gizmo.c:195
void WM_gizmo_set_color(wmGizmo *gz, const float color[4])
Definition: wm_gizmo.c:328
int WM_gizmo_cmp_temp_fl_reverse(const void *gz_a_ptr, const void *gz_b_ptr)
wmKeyMap * WM_gizmogroup_setup_keymap_generic_maybe_drag(const wmGizmoGroupType *UNUSED(gzgt), wmKeyConfig *kc)
wmGizmo * WM_gizmomap_get_modal(const wmGizmoMap *gzmap)
Definition: wm_gizmo_map.c:232
void WM_gizmo_do_msg_notify_tag_refresh(bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
const wmGizmoType * WM_gizmotype_find(const char *idname, bool quiet)
Definition: wm_gizmo_type.c:45
#define WM_msg_subscribe_rna_anon_prop(mbus, type_, prop_, value)
void WM_msg_subscribe_rna(struct wmMsgBus *mbus, PointerRNA *ptr, const PropertyRNA *prop, const wmMsgSubscribeValue *msg_val_params, const char *id_repr)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)