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