Blender  V3.3
transform_orientations.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <ctype.h>
8 #include <stddef.h>
9 #include <string.h>
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "DNA_armature_types.h"
14 #include "DNA_curve_types.h"
15 #include "DNA_meta_types.h"
16 #include "DNA_object_types.h"
17 #include "DNA_scene_types.h"
18 #include "DNA_screen_types.h"
19 #include "DNA_sequence_types.h"
20 #include "DNA_space_types.h"
21 #include "DNA_view3d_types.h"
22 
23 #include "BLI_listbase.h"
24 #include "BLI_math.h"
25 #include "BLI_string.h"
26 #include "BLI_string_utils.h"
27 #include "BLI_utildefines.h"
28 
29 #include "BKE_action.h"
30 #include "BKE_armature.h"
31 #include "BKE_context.h"
32 #include "BKE_curve.h"
33 #include "BKE_editmesh.h"
34 #include "BKE_layer.h"
35 #include "BKE_report.h"
36 #include "BKE_scene.h"
37 
38 #include "BLT_translation.h"
39 
40 #include "ED_armature.h"
41 
42 #include "SEQ_select.h"
43 
44 #include "transform.h"
45 #include "transform_orientations.h"
46 
47 /* *********************** TransSpace ************************** */
48 
50 {
52  ListBase *transform_orientations = &scene->transform_spaces;
53 
54  BLI_freelistN(transform_orientations);
55 
56  for (int i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
58  if (orient_slot->type == V3D_ORIENT_CUSTOM) {
59  orient_slot->type = V3D_ORIENT_GLOBAL; /* fallback to global */
60  orient_slot->index_custom = -1;
61  }
62  }
63 }
64 
65 static TransformOrientation *findOrientationName(ListBase *lb, const char *name)
66 {
67  return BLI_findstring(lb, name, offsetof(TransformOrientation, name));
68 }
69 
70 static bool uniqueOrientationNameCheck(void *arg, const char *name)
71 {
72  return findOrientationName((ListBase *)arg, name) != NULL;
73 }
74 
75 static void uniqueOrientationName(ListBase *lb, char *name)
76 {
78  lb,
80  '.',
81  name,
82  sizeof(((TransformOrientation *)NULL)->name));
83 }
84 
86  ReportList *UNUSED(reports),
87  const char *name,
88  const bool overwrite)
89 {
91  float mat[3][3];
92 
93  if (!rv3d) {
94  return NULL;
95  }
96 
97  copy_m3_m4(mat, rv3d->viewinv);
98  normalize_m3(mat);
99 
100  if (name[0] == 0) {
101  View3D *v3d = CTX_wm_view3d(C);
102  if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
103  /* If an object is used as camera, then this space is the same as object space! */
104  name = v3d->camera->id.name + 2;
105  }
106  else {
107  name = "Custom View";
108  }
109  }
110 
111  return addMatrixSpace(C, mat, name, overwrite);
112 }
113 
115  ReportList *UNUSED(reports),
116  const char *name,
117  const bool overwrite)
118 {
119  Base *base = CTX_data_active_base(C);
120  Object *ob;
121  float mat[3][3];
122 
123  if (base == NULL) {
124  return NULL;
125  }
126 
127  ob = base->object;
128 
129  copy_m3_m4(mat, ob->obmat);
130  normalize_m3(mat);
131 
132  /* use object name if no name is given */
133  if (name[0] == 0) {
134  name = ob->id.name + 2;
135  }
136 
137  return addMatrixSpace(C, mat, name, overwrite);
138 }
139 
141  ReportList *reports,
142  const char *name,
143  const bool overwrite)
144 {
145  float mat[3][3];
146  float normal[3], plane[3];
147 
149 
150  if (createSpaceNormalTangent(mat, normal, plane) == 0) {
151  BKE_reports_prepend(reports, "Cannot use zero-length bone");
152  return NULL;
153  }
154 
155  if (name[0] == 0) {
156  name = "Bone";
157  }
158 
159  return addMatrixSpace(C, mat, name, overwrite);
160 }
161 
163  ReportList *reports,
164  const char *name,
165  const bool overwrite)
166 {
167  float mat[3][3];
168  float normal[3], plane[3];
169 
171 
172  if (createSpaceNormalTangent(mat, normal, plane) == 0) {
173  BKE_reports_prepend(reports, "Cannot use zero-length curve");
174  return NULL;
175  }
176 
177  if (name[0] == 0) {
178  name = "Curve";
179  }
180 
181  return addMatrixSpace(C, mat, name, overwrite);
182 }
183 
185  ReportList *reports,
186  const char *name,
187  const bool overwrite)
188 {
189  float mat[3][3];
190  float normal[3], plane[3];
191  int type;
192 
194 
195  switch (type) {
196  case ORIENTATION_VERT:
197  if (createSpaceNormal(mat, normal) == 0) {
198  BKE_reports_prepend(reports, "Cannot use vertex with zero-length normal");
199  return NULL;
200  }
201 
202  if (name[0] == 0) {
203  name = "Vertex";
204  }
205  break;
206  case ORIENTATION_EDGE:
207  if (createSpaceNormalTangent(mat, normal, plane) == 0) {
208  BKE_reports_prepend(reports, "Cannot use zero-length edge");
209  return NULL;
210  }
211 
212  if (name[0] == 0) {
213  name = "Edge";
214  }
215  break;
216  case ORIENTATION_FACE:
217  if (createSpaceNormalTangent(mat, normal, plane) == 0) {
218  BKE_reports_prepend(reports, "Cannot use zero-area face");
219  return NULL;
220  }
221 
222  if (name[0] == 0) {
223  name = "Face";
224  }
225  break;
226  default:
227  return NULL;
228  }
229 
230  return addMatrixSpace(C, mat, name, overwrite);
231 }
232 
234  const float x[3],
235  const float y[3],
236  const float z[3])
237 {
238  bool is_zero[3] = {true, true, true};
239  zero_m3(mat);
240  if (x) {
241  is_zero[0] = normalize_v3_v3(mat[0], x) == 0.0f;
242  }
243  if (y) {
244  is_zero[1] = normalize_v3_v3(mat[1], y) == 0.0f;
245  }
246  if (z) {
247  is_zero[2] = normalize_v3_v3(mat[2], z) == 0.0f;
248  }
249 
250  int zero_axis = is_zero[0] + is_zero[1] + is_zero[2];
251  if (zero_axis == 0) {
252  return true;
253  }
254 
255  if (zero_axis == 1) {
256  int axis = is_zero[0] ? 0 : is_zero[1] ? 1 : 2;
257  cross_v3_v3v3(mat[axis], mat[(axis + 1) % 3], mat[(axis + 2) % 3]);
258  if (normalize_v3(mat[axis]) != 0.0f) {
259  return true;
260  }
261  }
262  else if (zero_axis == 2) {
263  int axis, a, b;
264  axis = !is_zero[0] ? 0 : !is_zero[1] ? 1 : 2;
265  a = (axis + 1) % 3;
266  b = (axis + 2) % 3;
267 
268  mat[a][a] = 1.0f;
269  mat[b][b] = 1.0f;
270  project_plane_v3_v3v3(mat[a], mat[a], mat[axis]);
271  project_plane_v3_v3v3(mat[b], mat[b], mat[axis]);
272  if ((normalize_v3(mat[a]) != 0.0f) && (normalize_v3(mat[b]) != 0.0f)) {
273  return true;
274  }
275  }
276 
277  unit_m3(mat);
278  return false;
279 }
280 
281 bool createSpaceNormal(float mat[3][3], const float normal[3])
282 {
283  float tangent[3] = {0.0f, 0.0f, 1.0f};
284 
285  copy_v3_v3(mat[2], normal);
286  if (normalize_v3(mat[2]) == 0.0f) {
287  return false; /* error return */
288  }
289 
290  cross_v3_v3v3(mat[0], mat[2], tangent);
291  if (is_zero_v3(mat[0])) {
292  tangent[0] = 1.0f;
293  tangent[1] = tangent[2] = 0.0f;
294  cross_v3_v3v3(mat[0], tangent, mat[2]);
295  }
296 
297  cross_v3_v3v3(mat[1], mat[2], mat[0]);
298 
299  normalize_m3(mat);
300 
301  return true;
302 }
303 
304 bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3])
305 {
306  if (normalize_v3_v3(mat[2], normal) == 0.0f) {
307  return false; /* error return */
308  }
309 
310  /* negate so we can use values from the matrix as input */
311  negate_v3_v3(mat[1], tangent);
312  /* preempt zero length tangent from causing trouble */
313  if (is_zero_v3(mat[1])) {
314  mat[1][2] = 1.0f;
315  }
316 
317  cross_v3_v3v3(mat[0], mat[2], mat[1]);
318  if (normalize_v3(mat[0]) == 0.0f) {
319  return false; /* error return */
320  }
321 
322  cross_v3_v3v3(mat[1], mat[2], mat[0]);
323  normalize_v3(mat[1]);
324 
325  /* final matrix must be normalized, do inline */
326  // normalize_m3(mat);
327 
328  return true;
329 }
330 
332  ReportList *reports,
333  const char *name,
334  const bool use_view,
335  const bool activate,
336  const bool overwrite)
337 {
339 
340  if (use_view) {
341  ts = createViewSpace(C, reports, name, overwrite);
342  }
343  else {
344  Object *obedit = CTX_data_edit_object(C);
346  if (obedit) {
347  if (obedit->type == OB_MESH) {
348  ts = createMeshSpace(C, reports, name, overwrite);
349  }
350  else if (obedit->type == OB_ARMATURE) {
351  ts = createBoneSpace(C, reports, name, overwrite);
352  }
353  else if (obedit->type == OB_CURVES_LEGACY) {
354  ts = createCurveSpace(C, reports, name, overwrite);
355  }
356  }
357  else if (ob && (ob->mode & OB_MODE_POSE)) {
358  ts = createBoneSpace(C, reports, name, overwrite);
359  }
360  else {
361  ts = createObjectSpace(C, reports, name, overwrite);
362  }
363  }
364 
365  if (activate && ts != NULL) {
367  }
368  return (ts != NULL);
369 }
370 
372  float mat[3][3],
373  const char *name,
374  const bool overwrite)
375 {
378  ListBase *transform_orientations = &scene->transform_spaces;
379  char name_unique[sizeof(ts->name)];
380 
381  if (overwrite) {
382  ts = findOrientationName(transform_orientations, name);
383  }
384  else {
385  BLI_strncpy(name_unique, name, sizeof(name_unique));
386  uniqueOrientationName(transform_orientations, name_unique);
387  name = name_unique;
388  }
389 
390  /* if not, create a new one */
391  if (ts == NULL) {
392  ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix");
393  BLI_addtail(transform_orientations, ts);
394  BLI_strncpy(ts->name, name, sizeof(ts->name));
395  }
396 
397  /* copy matrix into transform space */
398  copy_m3_m3(ts->mat, mat);
399 
400  return ts;
401 }
402 
404 {
406 }
407 
409 {
412 }
413 
415 {
418 
419  BLI_assert(index != -1);
420 
423 }
424 
426 {
428  ListBase *transform_orientations = &scene->transform_spaces;
429  return BLI_listbase_count(transform_orientations);
430 }
431 
432 void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char r_name[64])
433 {
434  if (r_name) {
435  BLI_strncpy(r_name, ts->name, MAX_NAME);
436  }
437  copy_m3_m3(r_mat, ts->mat);
438 }
439 
440 /* Updates all `BONE_TRANSFORM` flags.
441  * Returns total number of bones with `BONE_TRANSFORM`.
442  * NOTE: `transform_convert_pose_transflags_update` has a similar logic. */
444  ListBase *lb,
445  const bool do_it)
446 {
447  Bone *bone;
448  bool do_next;
449  int total = 0;
450 
451  for (bone = lb->first; bone; bone = bone->next) {
452  bone->flag &= ~BONE_TRANSFORM;
453  do_next = do_it;
454  if (do_it) {
455  if (bone->layer & arm->layer) {
456  if (bone->flag & BONE_SELECTED) {
457  bone->flag |= BONE_TRANSFORM;
458  total++;
459 
460  /* no transform on children if one parent bone is selected */
461  do_next = false;
462  }
463  }
464  }
465  total += armature_bone_transflags_update_recursive(arm, &bone->childbase, do_next);
466  }
467 
468  return total;
469 }
470 
471 void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3])
472 {
473  ARegion *region = CTX_wm_region(C);
475  ViewLayer *view_layer = CTX_data_view_layer(C);
476  Object *obedit = CTX_data_edit_object(C);
477  View3D *v3d = CTX_wm_view3d(C);
478  RegionView3D *rv3d = region->regiondata;
479  Object *ob = OBACT(view_layer);
480  const short orient_index = BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT);
481  const int pivot_point = scene->toolsettings->transform_pivot_point;
482 
484  scene, view_layer, v3d, rv3d, ob, obedit, orient_index, pivot_point, r_mat);
485 }
486 
488  ViewLayer *view_layer,
489  const View3D *v3d,
490  const RegionView3D *rv3d,
491  Object *ob,
492  Object *obedit,
493  const short orientation_index,
494  const int pivot_point,
495  float r_mat[3][3])
496 {
497  switch (orientation_index) {
498  case V3D_ORIENT_GIMBAL: {
499 
500  if (ob) {
501  if (ob->mode & OB_MODE_POSE) {
503  if (pchan && gimbal_axis_pose(ob, pchan, r_mat)) {
504  break;
505  }
506  }
507  else {
508  if (gimbal_axis_object(ob, r_mat)) {
509  break;
510  }
511  }
512  }
513  /* If not gimbal, fall through to normal. */
515  }
516  case V3D_ORIENT_NORMAL: {
517  if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
518  ED_getTransformOrientationMatrix(view_layer, v3d, ob, obedit, pivot_point, r_mat);
519  break;
520  }
521  /* No break we define 'normal' as 'local' in Object mode. */
523  }
524  case V3D_ORIENT_LOCAL: {
525  if (ob) {
526  if (ob->mode & OB_MODE_POSE) {
527  /* Each bone moves on its own local axis, but to avoid confusion,
528  * use the active pones axis for display T33575, this works as expected on a single
529  * bone and users who select many bones will understand what's going on and what local
530  * means when they start transforming. */
531  ED_getTransformOrientationMatrix(view_layer, v3d, ob, obedit, pivot_point, r_mat);
532  }
533  else {
535  }
536  break;
537  }
538  /* If not local, fall through to global. */
540  }
541  case V3D_ORIENT_GLOBAL: {
542  unit_m3(r_mat);
543  break;
544  }
545  case V3D_ORIENT_VIEW: {
546  if (rv3d != NULL) {
547  copy_m3_m4(r_mat, rv3d->viewinv);
548  normalize_m3(r_mat);
549  }
550  else {
551  unit_m3(r_mat);
552  }
553  break;
554  }
555  case V3D_ORIENT_CURSOR: {
557  break;
558  }
560  /* Do nothing. */;
561  break;
562  }
563  case V3D_ORIENT_CUSTOM:
564  default: {
565  BLI_assert(orientation_index >= V3D_ORIENT_CUSTOM);
566  int orientation_index_custom = orientation_index - V3D_ORIENT_CUSTOM;
568  scene, orientation_index_custom);
569  applyTransformOrientation(custom_orientation, r_mat, NULL);
570  break;
571  }
572  }
573 
574  return orientation_index;
575 }
576 
578  TransInfo *t,
579  short orient_index,
580  const float custom[3][3],
581  float r_spacemtx[3][3])
582 {
583  if (orient_index == V3D_ORIENT_CUSTOM_MATRIX) {
584  copy_m3_m3(r_spacemtx, custom);
586  }
587 
588  if (t->spacetype == SPACE_SEQ && t->options & CTX_SEQUENCER_IMAGE) {
589  Scene *scene = t->scene;
591  if (seq && seq->strip->transform && orient_index == V3D_ORIENT_LOCAL) {
592  axis_angle_to_mat3_single(r_spacemtx, 'Z', seq->strip->transform->rotation);
593  return orient_index;
594  }
595  }
596 
598  Object *obedit = CTX_data_edit_object(C);
599  Scene *scene = t->scene;
600  View3D *v3d = NULL;
601  RegionView3D *rv3d = NULL;
602 
603  if ((t->spacetype == SPACE_VIEW3D) && t->region && (t->region->regiontype == RGN_TYPE_WINDOW)) {
604  v3d = t->view;
605  rv3d = t->region->regiondata;
606 
607  if (ob && (ob->mode & OB_MODE_ALL_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) {
609  if (ob_armature) {
610  /* The armature matrix is used for GIMBAL, NORMAL and LOCAL orientations. */
611  ob = ob_armature;
612  }
613  }
614  }
615 
616  short r_orient_index = ED_transform_calc_orientation_from_type_ex(
617  scene, t->view_layer, v3d, rv3d, ob, obedit, orient_index, t->around, r_spacemtx);
618 
619  if (rv3d && (t->options & CTX_PAINT_CURVE)) {
620  /* Screen space in the 3d region. */
621  if (r_orient_index == V3D_ORIENT_VIEW) {
622  unit_m3(r_spacemtx);
623  }
624  else {
625  mul_m3_m4m3(r_spacemtx, rv3d->viewmat, r_spacemtx);
626  normalize_m3(r_spacemtx);
627  }
628  }
629 
630  return r_orient_index;
631 }
632 
633 const char *transform_orientations_spacename_get(TransInfo *t, const short orient_type)
634 {
635  switch (orient_type) {
636  case V3D_ORIENT_GLOBAL:
637  return TIP_("global");
638  case V3D_ORIENT_GIMBAL:
639  return TIP_("gimbal");
640  case V3D_ORIENT_NORMAL:
641  return TIP_("normal");
642  case V3D_ORIENT_LOCAL:
643  return TIP_("local");
644  case V3D_ORIENT_VIEW:
645  return TIP_("view");
646  case V3D_ORIENT_CURSOR:
647  return TIP_("cursor");
649  return TIP_("custom");
650  case V3D_ORIENT_CUSTOM:
651  default:
652  BLI_assert(orient_type >= V3D_ORIENT_CUSTOM);
654  t->scene, orient_type - V3D_ORIENT_CUSTOM);
655  return ts->name;
656  }
657 }
658 
659 void transform_orientations_current_set(TransInfo *t, const short orient_index)
660 {
661  const short orientation = t->orient[orient_index].type;
662  const char *spacename = transform_orientations_spacename_get(t, orientation);
663 
664  BLI_strncpy(t->spacename, spacename, sizeof(t->spacename));
665  copy_m3_m3(t->spacemtx, t->orient[orient_index].matrix);
666  invert_m3_m3_safe_ortho(t->spacemtx_inv, t->spacemtx);
667  t->orient_curr = orient_index;
668 }
669 
674  BMesh *bm, BMElem **elems, const uint n, const BMIterType itype, const char htype)
675 {
676  BMIter iter;
677  BMElem *ele;
678  uint i;
679 
682 
684  /* quick check */
685  BMEditSelection *ese;
686  i = 0;
687  for (ese = bm->selected.last; ese; ese = ese->prev) {
688  /* shouldn't need this check */
689  if (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) {
690 
691  /* only use contiguous selection */
692  if (ese->htype != htype) {
693  i = 0;
694  break;
695  }
696 
697  elems[i++] = ese->ele;
698  if (n == i) {
699  break;
700  }
701  }
702  else {
703  BLI_assert(0);
704  }
705  }
706 
707  if (i == 0) {
708  /* pass */
709  }
710  else if (i == n) {
711  return i;
712  }
713  }
714 
715  i = 0;
716  BM_ITER_MESH (ele, &iter, bm, itype) {
717  BLI_assert(ele->head.htype == htype);
718  if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
719  elems[i++] = ele;
720  if (n == i) {
721  break;
722  }
723  }
724  }
725 
726  return i;
727 }
728 
729 static uint bm_mesh_verts_select_get_n(BMesh *bm, BMVert **elems, const uint n)
730 {
732  bm, (BMElem **)elems, min_ii(n, bm->totvertsel), BM_VERTS_OF_MESH, BM_VERT);
733 }
734 static uint bm_mesh_edges_select_get_n(BMesh *bm, BMEdge **elems, const uint n)
735 {
737  bm, (BMElem **)elems, min_ii(n, bm->totedgesel), BM_EDGES_OF_MESH, BM_EDGE);
738 }
739 #if 0
740 static uint bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const uint n)
741 {
743  bm, (BMElem **)elems, min_ii(n, bm->totfacesel), BM_FACES_OF_MESH, BM_FACE);
744 }
745 #endif
746 
748  const View3D *v3d,
749  struct Object *ob,
750  struct Object *obedit,
751  float normal[3],
752  float plane[3],
753  const short around)
754 {
755  int result = ORIENTATION_NONE;
756  const bool activeOnly = (around == V3D_AROUND_ACTIVE);
757 
758  zero_v3(normal);
759  zero_v3(plane);
760 
761  if (obedit) {
762  float imat[3][3], mat[3][3];
763 
764  /* we need the transpose of the inverse for a normal... */
765  copy_m3_m4(imat, ob->obmat);
766 
767  invert_m3_m3(mat, imat);
768  transpose_m3(mat);
769 
770  ob = obedit;
771 
772  if (ob->type == OB_MESH) {
774  BMEditSelection ese;
775  float vec[3] = {0, 0, 0};
776 
777  /* USE LAST SELECTED WITH ACTIVE */
778  if (activeOnly && BM_select_history_active_get(em->bm, &ese)) {
780  BM_editselection_plane(&ese, plane);
781 
782  switch (ese.htype) {
783  case BM_VERT:
785  break;
786  case BM_EDGE:
788  break;
789  case BM_FACE:
791  break;
792  }
793  }
794  else {
795  if (em->bm->totfacesel >= 1) {
796  BMFace *efa;
797  BMIter iter;
798 
799  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
800  if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
801  BM_face_calc_tangent_auto(efa, vec);
802  add_v3_v3(normal, efa->no);
803  add_v3_v3(plane, vec);
804  }
805  }
806 
808  }
809  else if (em->bm->totvertsel == 3) {
810  BMVert *v_tri[3];
811 
812  if (bm_mesh_verts_select_get_n(em->bm, v_tri, 3) == 3) {
813  BMEdge *e = NULL;
814  float no_test[3];
815 
816  normal_tri_v3(normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
817 
818  /* check if the normal is pointing opposite to vert normals */
819  no_test[0] = v_tri[0]->no[0] + v_tri[1]->no[0] + v_tri[2]->no[0];
820  no_test[1] = v_tri[0]->no[1] + v_tri[1]->no[1] + v_tri[2]->no[1];
821  no_test[2] = v_tri[0]->no[2] + v_tri[1]->no[2] + v_tri[2]->no[2];
822  if (dot_v3v3(no_test, normal) < 0.0f) {
823  negate_v3(normal);
824  }
825 
826  if (em->bm->totedgesel >= 1) {
827  /* find an edge that's a part of v_tri (no need to search all edges) */
828  float e_length;
829  int j;
830 
831  for (j = 0; j < 3; j++) {
832  BMEdge *e_test = BM_edge_exists(v_tri[j], v_tri[(j + 1) % 3]);
833  if (e_test && BM_elem_flag_test(e_test, BM_ELEM_SELECT)) {
834  const float e_test_length = BM_edge_calc_length_squared(e_test);
835  if ((e == NULL) || (e_length < e_test_length)) {
836  e = e_test;
837  e_length = e_test_length;
838  }
839  }
840  }
841  }
842 
843  if (e) {
844  BMVert *v_pair[2];
845  if (BM_edge_is_boundary(e)) {
846  BM_edge_ordered_verts(e, &v_pair[0], &v_pair[1]);
847  }
848  else {
849  v_pair[0] = e->v1;
850  v_pair[1] = e->v2;
851  }
852  sub_v3_v3v3(plane, v_pair[0]->co, v_pair[1]->co);
853  }
854  else {
855  BM_vert_tri_calc_tangent_edge(v_tri, plane);
856  }
857  }
858  else {
859  BLI_assert(0);
860  }
861 
863  }
864  else if (em->bm->totedgesel == 1 || em->bm->totvertsel == 2) {
865  BMVert *v_pair[2] = {NULL, NULL};
866  BMEdge *eed = NULL;
867 
868  if (em->bm->totedgesel == 1) {
869  if (bm_mesh_edges_select_get_n(em->bm, &eed, 1) == 1) {
870  v_pair[0] = eed->v1;
871  v_pair[1] = eed->v2;
872  }
873  }
874  else {
875  BLI_assert(em->bm->totvertsel == 2);
876  bm_mesh_verts_select_get_n(em->bm, v_pair, 2);
877  }
878 
879  /* should never fail */
880  if (LIKELY(v_pair[0] && v_pair[1])) {
881  bool v_pair_swap = false;
893  /* be deterministic where possible and ensure v_pair[0] is active */
894  if (BM_mesh_active_vert_get(em->bm) == v_pair[1]) {
895  v_pair_swap = true;
896  }
897  else if (eed && BM_edge_is_boundary(eed)) {
898  /* predictable direction for boundary edges */
899  if (eed->l->v != v_pair[0]) {
900  v_pair_swap = true;
901  }
902  }
903 
904  if (v_pair_swap) {
905  SWAP(BMVert *, v_pair[0], v_pair[1]);
906  }
907 
908  add_v3_v3v3(normal, v_pair[1]->no, v_pair[0]->no);
909  sub_v3_v3v3(plane, v_pair[1]->co, v_pair[0]->co);
910 
911  if (normalize_v3(plane) != 0.0f) {
912  /* For edges it'd important the resulting matrix can rotate around the edge,
913  * project onto the plane so we can use a fallback value. */
915  if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
916  /* in the case the normal and plane are aligned,
917  * use a fallback normal which is orthogonal to the plane. */
918  ortho_v3_v3(normal, plane);
919  }
920  }
921  }
922 
924  }
925  else if (em->bm->totvertsel == 1) {
926  BMVert *v = NULL;
927 
928  if (bm_mesh_verts_select_get_n(em->bm, &v, 1) == 1) {
929  copy_v3_v3(normal, v->no);
930  BMEdge *e_pair[2];
931 
932  if (BM_vert_edge_pair(v, &e_pair[0], &e_pair[1])) {
933  bool v_pair_swap = false;
934  BMVert *v_pair[2] = {
935  BM_edge_other_vert(e_pair[0], v),
936  BM_edge_other_vert(e_pair[1], v),
937  };
938  float dir_pair[2][3];
939 
940  if (BM_edge_is_boundary(e_pair[0])) {
941  if (e_pair[0]->l->v != v) {
942  v_pair_swap = true;
943  }
944  }
945  else {
946  if (BM_edge_calc_length_squared(e_pair[0]) <
947  BM_edge_calc_length_squared(e_pair[1])) {
948  v_pair_swap = true;
949  }
950  }
951 
952  if (v_pair_swap) {
953  SWAP(BMVert *, v_pair[0], v_pair[1]);
954  }
955 
956  sub_v3_v3v3(dir_pair[0], v->co, v_pair[0]->co);
957  sub_v3_v3v3(dir_pair[1], v_pair[1]->co, v->co);
958  normalize_v3(dir_pair[0]);
959  normalize_v3(dir_pair[1]);
960 
961  add_v3_v3v3(plane, dir_pair[0], dir_pair[1]);
962  }
963  }
964 
966  }
967  else if (em->bm->totvertsel > 3) {
968  BMIter iter;
969  BMVert *v;
970 
971  zero_v3(normal);
972 
973  BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
975  add_v3_v3(normal, v->no);
976  }
977  }
980  }
981  }
982 
983  /* not needed but this matches 2.68 and older behavior */
984  negate_v3(plane);
985 
986  } /* end editmesh */
987  else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) {
988  Curve *cu = obedit->data;
989  Nurb *nu = NULL;
990  int a;
991  ListBase *nurbs = BKE_curve_editNurbs_get(cu);
992 
993  void *vert_act = NULL;
994  if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, &vert_act)) {
995  if (nu->type == CU_BEZIER) {
996  BezTriple *bezt = vert_act;
998  BKE_nurb_bezt_calc_plane(nu, bezt, plane);
999  }
1000  else {
1001  BPoint *bp = vert_act;
1003  BKE_nurb_bpoint_calc_plane(nu, bp, plane);
1004  }
1005  }
1006  else {
1007  const bool use_handle = v3d->overlay.handle_display != CURVE_HANDLE_NONE;
1008 
1009  for (nu = nurbs->first; nu; nu = nu->next) {
1010  /* only bezier has a normal */
1011  if (nu->type == CU_BEZIER) {
1012  BezTriple *bezt = nu->bezt;
1013  a = nu->pntsu;
1014  while (a--) {
1015  short flag = 0;
1016 
1017 #define SEL_F1 (1 << 0)
1018 #define SEL_F2 (1 << 1)
1019 #define SEL_F3 (1 << 2)
1020 
1021  if (use_handle) {
1022  if (bezt->f1 & SELECT) {
1023  flag |= SEL_F1;
1024  }
1025  if (bezt->f2 & SELECT) {
1026  flag |= SEL_F2;
1027  }
1028  if (bezt->f3 & SELECT) {
1029  flag |= SEL_F3;
1030  }
1031  }
1032  else {
1033  flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
1034  }
1035 
1036  /* exception */
1037  if (flag) {
1038  float tvec[3];
1039  if ((around == V3D_AROUND_LOCAL_ORIGINS) ||
1040  ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3)) {
1041  BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
1042  add_v3_v3(normal, tvec);
1043  }
1044  else {
1045  /* ignore bezt->f2 in this case */
1046  if (flag & SEL_F1) {
1047  sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[1]);
1048  normalize_v3(tvec);
1049  add_v3_v3(normal, tvec);
1050  }
1051  if (flag & SEL_F3) {
1052  sub_v3_v3v3(tvec, bezt->vec[1], bezt->vec[2]);
1053  normalize_v3(tvec);
1054  add_v3_v3(normal, tvec);
1055  }
1056  }
1057 
1058  BKE_nurb_bezt_calc_plane(nu, bezt, tvec);
1059  add_v3_v3(plane, tvec);
1060  }
1061 
1062 #undef SEL_F1
1063 #undef SEL_F2
1064 #undef SEL_F3
1065 
1066  bezt++;
1067  }
1068  }
1069  else if (nu->bp && (nu->pntsv == 1)) {
1070  BPoint *bp = nu->bp;
1071  a = nu->pntsu;
1072  while (a--) {
1073  if (bp->f1 & SELECT) {
1074  float tvec[3];
1075 
1076  BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
1077  BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
1078 
1079  const bool is_prev_sel = bp_prev && (bp_prev->f1 & SELECT);
1080  const bool is_next_sel = bp_next && (bp_next->f1 & SELECT);
1081  if (is_prev_sel == false && is_next_sel == false) {
1082  /* Isolated, add based on surrounding */
1083  BKE_nurb_bpoint_calc_normal(nu, bp, tvec);
1084  add_v3_v3(normal, tvec);
1085  }
1086  else if (is_next_sel) {
1087  /* A segment, add the edge normal */
1088  sub_v3_v3v3(tvec, bp->vec, bp_next->vec);
1089  normalize_v3(tvec);
1090  add_v3_v3(normal, tvec);
1091  }
1092 
1093  BKE_nurb_bpoint_calc_plane(nu, bp, tvec);
1094  add_v3_v3(plane, tvec);
1095  }
1096  bp++;
1097  }
1098  }
1099  }
1100  }
1101 
1102  if (!is_zero_v3(normal)) {
1104  }
1105  }
1106  else if (obedit->type == OB_MBALL) {
1107  MetaBall *mb = obedit->data;
1108  MetaElem *ml;
1109  bool ok = false;
1110  float tmat[3][3];
1111 
1112  if (activeOnly && (ml = mb->lastelem)) {
1113  quat_to_mat3(tmat, ml->quat);
1114  add_v3_v3(normal, tmat[2]);
1115  add_v3_v3(plane, tmat[1]);
1116  ok = true;
1117  }
1118  else {
1119  for (ml = mb->editelems->first; ml; ml = ml->next) {
1120  if (ml->flag & SELECT) {
1121  quat_to_mat3(tmat, ml->quat);
1122  add_v3_v3(normal, tmat[2]);
1123  add_v3_v3(plane, tmat[1]);
1124  ok = true;
1125  }
1126  }
1127  }
1128 
1129  if (ok) {
1130  if (!is_zero_v3(plane)) {
1132  }
1133  }
1134  }
1135  else if (obedit->type == OB_ARMATURE) {
1136  bArmature *arm = obedit->data;
1137  EditBone *ebone;
1138  bool ok = false;
1139  float tmat[3][3];
1140 
1141  if (activeOnly && (ebone = arm->act_edbone)) {
1142  ED_armature_ebone_to_mat3(ebone, tmat);
1143  add_v3_v3(normal, tmat[2]);
1144  add_v3_v3(plane, tmat[1]);
1145  ok = true;
1146  }
1147  else {
1148  /* When we only have the root/tip are selected. */
1149  bool fallback_ok = false;
1150  float fallback_normal[3];
1151  float fallback_plane[3];
1152 
1153  zero_v3(fallback_normal);
1154  zero_v3(fallback_plane);
1155 
1156  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1157  if (arm->layer & ebone->layer) {
1158  if (ebone->flag & BONE_SELECTED) {
1159  ED_armature_ebone_to_mat3(ebone, tmat);
1160  add_v3_v3(normal, tmat[2]);
1161  add_v3_v3(plane, tmat[1]);
1162  ok = true;
1163  }
1164  else if ((ok == false) &&
1165  ((ebone->flag & BONE_TIPSEL) ||
1166  ((ebone->flag & BONE_ROOTSEL) &&
1167  (ebone->parent && ebone->flag & BONE_CONNECTED) == false))) {
1168  ED_armature_ebone_to_mat3(ebone, tmat);
1169  add_v3_v3(fallback_normal, tmat[2]);
1170  add_v3_v3(fallback_plane, tmat[1]);
1171  fallback_ok = true;
1172  }
1173  }
1174  }
1175  if ((ok == false) && fallback_ok) {
1176  ok = true;
1177  copy_v3_v3(normal, fallback_normal);
1178  copy_v3_v3(plane, fallback_plane);
1179  }
1180  }
1181 
1182  if (ok) {
1183  if (!is_zero_v3(plane)) {
1185  }
1186  }
1187  }
1188 
1189  /* Vectors from edges don't need the special transpose inverse multiplication */
1190  if (result == ORIENTATION_EDGE) {
1191  float tvec[3];
1192 
1193  mul_mat3_m4_v3(ob->obmat, normal);
1194  mul_mat3_m4_v3(ob->obmat, plane);
1195 
1196  /* align normal to edge direction (so normal is perpendicular to the plane).
1197  * 'ORIENTATION_EDGE' will do the other way around.
1198  * This has to be done **after** applying obmat, see T45775! */
1199  project_v3_v3v3(tvec, normal, plane);
1200  sub_v3_v3(normal, tvec);
1201  }
1202  else {
1203  mul_m3_v3(mat, normal);
1204  mul_m3_v3(mat, plane);
1205  }
1206  }
1207  else if (ob && (ob->mode & OB_MODE_POSE)) {
1208  bArmature *arm = ob->data;
1209  bPoseChannel *pchan;
1210  float imat[3][3], mat[3][3];
1211  bool ok = false;
1212 
1213  if (activeOnly && (pchan = BKE_pose_channel_active_if_layer_visible(ob))) {
1214  add_v3_v3(normal, pchan->pose_mat[2]);
1215  add_v3_v3(plane, pchan->pose_mat[1]);
1216  ok = true;
1217  }
1218  else {
1219  int transformed_len;
1220  transformed_len = armature_bone_transflags_update_recursive(arm, &arm->bonebase, true);
1221  if (transformed_len) {
1222  /* use channels to get stats */
1223  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1224  if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
1225  add_v3_v3(normal, pchan->pose_mat[2]);
1226  add_v3_v3(plane, pchan->pose_mat[1]);
1227  }
1228  }
1229  ok = true;
1230  }
1231  }
1232 
1233  /* use for both active & all */
1234  if (ok) {
1235  /* we need the transpose of the inverse for a normal... */
1236  copy_m3_m4(imat, ob->obmat);
1237 
1238  invert_m3_m3(mat, imat);
1239  transpose_m3(mat);
1240  mul_m3_v3(mat, normal);
1241  mul_m3_v3(mat, plane);
1242 
1244  }
1245  }
1246  else {
1247  /* we need the one selected object, if its not active */
1248  if (ob != NULL) {
1249  bool ok = false;
1250  if (activeOnly || (ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_PARTICLE_EDIT))) {
1251  /* Ignore selection state. */
1252  ok = true;
1253  }
1254  else {
1255  Base *base = BKE_view_layer_base_find(view_layer, ob);
1256  if (UNLIKELY(base == NULL)) {
1257  /* This is very unlikely, if it happens allow the value to be set since the caller
1258  * may have taken the object from outside this view-layer. */
1259  ok = true;
1260  }
1261  else if (BASE_SELECTED(v3d, base)) {
1262  ok = true;
1263  }
1264  }
1265 
1266  if (ok) {
1267  copy_v3_v3(normal, ob->obmat[2]);
1268  copy_v3_v3(plane, ob->obmat[1]);
1269  }
1270  }
1272  }
1273 
1274  return result;
1275 }
1276 
1277 int getTransformOrientation(const bContext *C, float normal[3], float plane[3])
1278 {
1279  Object *obact = CTX_data_active_object(C);
1280  Object *obedit = CTX_data_edit_object(C);
1281 
1282  /* dummy value, not V3D_AROUND_ACTIVE and not V3D_AROUND_LOCAL_ORIGINS */
1283  short around = V3D_AROUND_CENTER_BOUNDS;
1284 
1285  ViewLayer *view_layer = CTX_data_view_layer(C);
1286  View3D *v3d = CTX_wm_view3d(C);
1287 
1288  return getTransformOrientation_ex(view_layer, v3d, obact, obedit, normal, plane, around);
1289 }
1290 
1292  const View3D *v3d,
1293  Object *ob,
1294  Object *obedit,
1295  const short around,
1296  float r_orientation_mat[3][3])
1297 {
1298  float normal[3] = {0.0, 0.0, 0.0};
1299  float plane[3] = {0.0, 0.0, 0.0};
1300 
1301  int type;
1302 
1303  type = getTransformOrientation_ex(view_layer, v3d, ob, obedit, normal, plane, around);
1304 
1305  /* Fallback, when the plane can't be calculated. */
1306  if (ORIENTATION_USE_PLANE(type) && is_zero_v3(plane)) {
1308  }
1309 
1310  switch (type) {
1311  case ORIENTATION_NORMAL:
1312  if (createSpaceNormalTangent(r_orientation_mat, normal, plane) == 0) {
1314  }
1315  break;
1316  case ORIENTATION_VERT:
1317  if (createSpaceNormal(r_orientation_mat, normal) == 0) {
1319  }
1320  break;
1321  case ORIENTATION_EDGE:
1322  if (createSpaceNormalTangent(r_orientation_mat, normal, plane) == 0) {
1324  }
1325  break;
1326  case ORIENTATION_FACE:
1327  if (createSpaceNormalTangent(r_orientation_mat, normal, plane) == 0) {
1329  }
1330  break;
1331  default:
1333  break;
1334  }
1335 
1336  if (type == ORIENTATION_NONE) {
1337  unit_m3(r_orientation_mat);
1338  }
1339 }
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_active_if_layer_visible(struct Object *ob)
Definition: action.c:720
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1370
struct Base * CTX_data_active_base(const bContext *C)
Definition: context.c:1358
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
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
bool BKE_curve_nurb_vert_active_get(struct Curve *cu, struct Nurb **r_nu, void **r_vert)
Definition: curve.cc:5049
void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_plane[3])
Definition: curve.cc:1074
struct ListBase * BKE_curve_editNurbs_get(struct Curve *cu)
Definition: curve.cc:426
struct BPoint * BKE_nurb_bpoint_get_next(struct Nurb *nu, struct BPoint *bp)
Definition: curve.cc:994
void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_normal[3])
Definition: curve.cc:1111
void BKE_nurb_bezt_calc_normal(struct Nurb *nu, struct BezTriple *bezt, float r_normal[3])
struct BPoint * BKE_nurb_bpoint_get_prev(struct Nurb *nu, struct BPoint *bp)
Definition: curve.cc:1037
void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, struct BPoint *bp, float r_plane[3])
Definition: curve.cc:1134
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:58
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:379
void void BKE_reports_prepend(ReportList *reports, const char *prepend)
Definition: report.c:144
int BKE_scene_orientation_get_index(struct Scene *scene, int slot_index)
Definition: scene.cc:2470
void BKE_scene_transform_orientation_remove(struct Scene *scene, struct TransformOrientation *orientation)
Definition: scene.cc:3545
void BKE_scene_cursor_rot_to_mat3(const struct View3DCursor *cursor, float mat[3][3])
int BKE_scene_transform_orientation_get_index(const struct Scene *scene, const struct TransformOrientation *orientation)
struct TransformOrientation * BKE_scene_transform_orientation_find(const struct Scene *scene, int index)
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define ATTR_FALLTHROUGH
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:33
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
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 mul_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:790
void invert_m3_m3_safe_ortho(float Ainv[3][3], const float A[3][3])
Definition: math_matrix.c:3199
void zero_m3(float m[3][3])
Definition: math_matrix.c:23
void normalize_m3(float R[3][3]) ATTR_NONNULL()
Definition: math_matrix.c:1912
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1180
void transpose_m3(float R[3][3])
Definition: math_matrix.c:1332
void mul_m3_m4m3(float R[3][3], const float A[4][4], const float B[3][3])
Definition: math_matrix.c:477
void axis_angle_to_mat3_single(float R[3][3], char axis, float angle)
void quat_to_mat3(float mat[3][3], const float q[4])
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 copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
Definition: math_vector.c:600
void project_plane_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
Definition: math_vector.c:638
void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
Definition: math_vector.c:652
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
void ortho_v3_v3(float out[3], const float v[3])
Definition: math_vector.c:732
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
bool BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_len)
Definition: string_utils.c:233
unsigned int uint
Definition: BLI_sys_types.h:67
#define ARRAY_SIZE(arr)
#define SWAP(type, a, b)
#define UNUSED(x)
#define UNPACK3(a)
#define UNLIKELY(x)
#define ELEM(...)
#define LIKELY(x)
#define TIP_(msgid)
#define CTX_DATA_(context, msgid)
#define BLT_I18NCONTEXT_ID_SCENE
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_TRANSFORM
@ BONE_TIPSEL
@ BONE_CONNECTED
@ CU_BEZIER
#define MAX_NAME
Definition: DNA_defs.h:48
@ BASE_SELECTED
#define OB_MODE_ALL_PAINT
#define OB_MODE_ALL_WEIGHT_PAINT
@ OB_MODE_PARTICLE_EDIT
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
@ OB_MBALL
@ OB_SURF
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVES_LEGACY
#define OBACT(_view_layer)
@ SCE_ORIENT_DEFAULT
@ RGN_TYPE_WINDOW
@ SPACE_SEQ
@ SPACE_VIEW3D
@ V3D_AROUND_ACTIVE
@ V3D_AROUND_CENTER_BOUNDS
@ V3D_AROUND_LOCAL_ORIGINS
@ V3D_ORIENT_NORMAL
@ V3D_ORIENT_CUSTOM
@ V3D_ORIENT_GLOBAL
@ V3D_ORIENT_CUSTOM_MATRIX
@ V3D_ORIENT_LOCAL
@ V3D_ORIENT_VIEW
@ V3D_ORIENT_CURSOR
@ V3D_ORIENT_GIMBAL
#define RV3D_CAMOB
@ CURVE_HANDLE_NONE
_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
_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 type
_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 GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:25
void ED_armature_ebone_to_mat3(EditBone *ebone, float r_mat[3][3])
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ 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)
BMIterType
BMesh Iterators.
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
ATTR_WARN_UNUSED_RESULT BMesh const char itype
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
void BM_editselection_normal(BMEditSelection *ese, float r_normal[3])
BMVert * BM_mesh_active_vert_get(BMesh *bm)
bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3])
void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3])
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1553
void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
Definition: bmesh_query.c:1141
float BM_edge_calc_length_squared(const BMEdge *e)
Definition: bmesh_query.c:533
bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b)
Definition: bmesh_query.c:590
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
void activate(bool forceActivation=false) const
#define SELECT
Scene scene
IconTextureDrawCall normal
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static unsigned a[3]
Definition: RandGen.cpp:78
bool is_zero(const T &a)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
struct Object * transform_object_deform_pose_armature_get(const TransInfo *t, struct Object *ob)
bool gimbal_axis_object(struct Object *ob, float gmat[3][3])
bool gimbal_axis_pose(struct Object *ob, const struct bPoseChannel *pchan, float gmat[3][3])
Sequence * SEQ_select_active_get(Scene *scene)
Definition: strip_select.c:18
void * regiondata
BMVert * v1
Definition: bmesh_class.h:122
BMVert * v2
Definition: bmesh_class.h:122
struct BMLoop * l
Definition: bmesh_class.h:128
struct BMesh * bm
Definition: BKE_editmesh.h:40
struct BMEditSelection * prev
Definition: bmesh_marking.h:10
BMHeader head
Definition: bmesh_class.h:243
float no[3]
Definition: bmesh_class.h:271
char htype
Definition: bmesh_class.h:64
struct BMVert * v
Definition: bmesh_class.h:153
float co[3]
Definition: bmesh_class.h:87
float no[3]
Definition: bmesh_class.h:88
int totfacesel
Definition: bmesh_class.h:298
ListBase selected
Definition: bmesh_class.h:356
int totvertsel
Definition: bmesh_class.h:298
int totedgesel
Definition: bmesh_class.h:298
uint8_t f1
float vec[4]
struct Object * object
uint8_t f3
float vec[3][3]
uint8_t f1
uint8_t f2
struct Bone * next
ListBase childbase
struct EditBone * next
Definition: BKE_armature.h:33
struct EditBone * parent
Definition: BKE_armature.h:41
char name[66]
Definition: DNA_ID.h:378
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
MetaElem * lastelem
ListBase * editelems
struct MetaElem * next
float quat[4]
short flag
struct Nurb * next
short type
BezTriple * bezt
BPoint * bp
struct bPose * pose
float obmat[4][4]
void * data
float viewmat[4][4]
float viewinv[4][4]
struct ToolSettings * toolsettings
View3DCursor cursor
TransformOrientationSlot orientation_slots[4]
ListBase transform_spaces
StripTransform * transform
char transform_pivot_point
View3DOverlay overlay
struct Object * camera
ListBase bonebase
struct EditBone * act_edbone
unsigned int layer
ListBase * edbo
struct Bone * bone
struct bPoseChannel * next
float pose_mat[4][4]
ListBase chanbase
bool transform_orientations_create_from_axis(float mat[3][3], const float x[3], const float y[3], const float z[3])
static TransformOrientation * createCurveSpace(bContext *C, ReportList *reports, const char *name, const bool overwrite)
void ED_getTransformOrientationMatrix(ViewLayer *view_layer, const View3D *v3d, Object *ob, Object *obedit, const short around, float r_orientation_mat[3][3])
bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3])
const char * transform_orientations_spacename_get(TransInfo *t, const short orient_type)
void transform_orientations_current_set(TransInfo *t, const short orient_index)
void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char r_name[64])
bool createSpaceNormal(float mat[3][3], const float normal[3])
static uint bm_mesh_verts_select_get_n(BMesh *bm, BMVert **elems, const uint n)
static uint bm_mesh_elems_select_get_n__internal(BMesh *bm, BMElem **elems, const uint n, const BMIterType itype, const char htype)
void BIF_clearTransformOrientation(bContext *C)
int getTransformOrientation(const bContext *C, float normal[3], float plane[3])
static TransformOrientation * createBoneSpace(bContext *C, ReportList *reports, const char *name, const bool overwrite)
TransformOrientation * addMatrixSpace(bContext *C, float mat[3][3], const char *name, const bool overwrite)
void BIF_removeTransformOrientationIndex(bContext *C, int index)
int getTransformOrientation_ex(ViewLayer *view_layer, const View3D *v3d, struct Object *ob, struct Object *obedit, float normal[3], float plane[3], const short around)
void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3])
static bool uniqueOrientationNameCheck(void *arg, const char *name)
void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target)
#define SEL_F1
#define SEL_F2
static TransformOrientation * createObjectSpace(bContext *C, ReportList *UNUSED(reports), const char *name, const bool overwrite)
int BIF_countTransformOrientation(const bContext *C)
static TransformOrientation * createViewSpace(bContext *C, ReportList *UNUSED(reports), const char *name, const bool overwrite)
bool BIF_createTransformOrientation(bContext *C, ReportList *reports, const char *name, const bool use_view, const bool activate, const bool overwrite)
void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target)
static void uniqueOrientationName(ListBase *lb, char *name)
static TransformOrientation * findOrientationName(ListBase *lb, const char *name)
#define SEL_F3
static int armature_bone_transflags_update_recursive(bArmature *arm, ListBase *lb, const bool do_it)
static TransformOrientation * createMeshSpace(bContext *C, ReportList *reports, const char *name, const bool overwrite)
short transform_orientation_matrix_get(bContext *C, TransInfo *t, short orient_index, const float custom[3][3], float r_spacemtx[3][3])
static uint bm_mesh_edges_select_get_n(BMesh *bm, BMEdge **elems, const uint n)
short ED_transform_calc_orientation_from_type_ex(const Scene *scene, ViewLayer *view_layer, const View3D *v3d, const RegionView3D *rv3d, Object *ob, Object *obedit, const short orientation_index, const int pivot_point, float r_mat[3][3])
@ ORIENTATION_FACE
@ ORIENTATION_EDGE
@ ORIENTATION_VERT
@ ORIENTATION_NONE
@ ORIENTATION_NORMAL
#define ORIENTATION_USE_PLANE(ty)