Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / transform / transform_orientations.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Martin Poirier
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/editors/transform/transform_orientations.c
24  *  \ingroup edtransform
25  */
26
27 #include <string.h>
28 #include <stddef.h>
29 #include <ctype.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_armature_types.h"
34 #include "DNA_curve_types.h"
35 #include "DNA_meta_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_screen_types.h"
39 #include "DNA_space_types.h"
40 #include "DNA_view3d_types.h"
41 #include "DNA_workspace_types.h"
42
43 #include "BLI_math.h"
44 #include "BLI_listbase.h"
45 #include "BLI_string.h"
46 #include "BLI_string_utils.h"
47 #include "BLI_utildefines.h"
48
49 #include "BKE_action.h"
50 #include "BKE_curve.h"
51 #include "BKE_context.h"
52 #include "BKE_editmesh.h"
53 #include "BKE_report.h"
54 #include "BKE_main.h"
55 #include "BKE_screen.h"
56 #include "BKE_workspace.h"
57
58 #include "BLT_translation.h"
59
60 #include "ED_armature.h"
61
62 #include "transform.h"
63
64 /* *********************** TransSpace ************************** */
65
66 void BIF_clearTransformOrientation(bContext *C)
67 {
68         WorkSpace *workspace = CTX_wm_workspace(C);
69         ListBase *transform_orientations = BKE_workspace_transform_orientations_get(workspace);
70         View3D *v3d = CTX_wm_view3d(C);
71
72         BLI_freelistN(transform_orientations);
73         
74         // Need to loop over all view3d
75         if (v3d && v3d->twmode == V3D_MANIP_CUSTOM) {
76                 v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
77                 v3d->custom_orientation_index = -1;
78         }
79 }
80
81 static TransformOrientation *findOrientationName(ListBase *lb, const char *name)
82 {
83         return BLI_findstring(lb, name, offsetof(TransformOrientation, name));
84 }
85
86 static bool uniqueOrientationNameCheck(void *arg, const char *name)
87 {
88         return findOrientationName((ListBase *)arg, name) != NULL;
89 }
90
91 static void uniqueOrientationName(ListBase *lb, char *name)
92 {
93         BLI_uniquename_cb(uniqueOrientationNameCheck, lb, CTX_DATA_(BLT_I18NCONTEXT_ID_SCENE, "Space"), '.', name,
94                           sizeof(((TransformOrientation *)NULL)->name));
95 }
96
97 static TransformOrientation *createViewSpace(bContext *C, ReportList *UNUSED(reports),
98                                              const char *name, const bool overwrite)
99 {
100         RegionView3D *rv3d = CTX_wm_region_view3d(C);
101         float mat[3][3];
102
103         if (!rv3d)
104                 return NULL;
105
106         copy_m3_m4(mat, rv3d->viewinv);
107         normalize_m3(mat);
108
109         if (name[0] == 0) {
110                 View3D *v3d = CTX_wm_view3d(C);
111                 if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
112                         /* If an object is used as camera, then this space is the same as object space! */
113                         name = v3d->camera->id.name + 2;
114                 }
115                 else {
116                         name = "Custom View";
117                 }
118         }
119
120         return addMatrixSpace(C, mat, name, overwrite);
121 }
122
123 static TransformOrientation *createObjectSpace(bContext *C, ReportList *UNUSED(reports),
124                                                const char *name, const bool overwrite)
125 {
126         Base *base = CTX_data_active_base(C);
127         Object *ob;
128         float mat[3][3];
129
130         if (base == NULL)
131                 return NULL;
132
133         ob = base->object;
134
135         copy_m3_m4(mat, ob->obmat);
136         normalize_m3(mat);
137
138         /* use object name if no name is given */
139         if (name[0] == 0) {
140                 name = ob->id.name + 2;
141         }
142
143         return addMatrixSpace(C, mat, name, overwrite);
144 }
145
146 static TransformOrientation *createBoneSpace(bContext *C, ReportList *reports,
147                                              const char *name, const bool overwrite)
148 {
149         float mat[3][3];
150         float normal[3], plane[3];
151
152         getTransformOrientation(C, normal, plane);
153
154         if (createSpaceNormalTangent(mat, normal, plane) == 0) {
155                 BKE_reports_prepend(reports, "Cannot use zero-length bone");
156                 return NULL;
157         }
158
159         if (name[0] == 0) {
160                 name = "Bone";
161         }
162
163         return addMatrixSpace(C, mat, name, overwrite);
164 }
165
166 static TransformOrientation *createCurveSpace(bContext *C, ReportList *reports,
167                                               const char *name, const bool overwrite)
168 {
169         float mat[3][3];
170         float normal[3], plane[3];
171
172         getTransformOrientation(C, normal, plane);
173
174         if (createSpaceNormalTangent(mat, normal, plane) == 0) {
175                 BKE_reports_prepend(reports, "Cannot use zero-length curve");
176                 return NULL;
177         }
178
179         if (name[0] == 0) {
180                 name = "Curve";
181         }
182
183         return addMatrixSpace(C, mat, name, overwrite);
184 }
185
186
187 static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports,
188                                              const char *name, const bool overwrite)
189 {
190         float mat[3][3];
191         float normal[3], plane[3];
192         int type;
193
194         type = getTransformOrientation(C, normal, plane);
195         
196         switch (type) {
197                 case ORIENTATION_VERT:
198                         if (createSpaceNormal(mat, normal) == 0) {
199                                 BKE_reports_prepend(reports, "Cannot use vertex with zero-length normal");
200                                 return NULL;
201                         }
202         
203                         if (name[0] == 0) {
204                                 name = "Vertex";
205                         }
206                         break;
207                 case ORIENTATION_EDGE:
208                         if (createSpaceNormalTangent(mat, normal, plane) == 0) {
209                                 BKE_reports_prepend(reports, "Cannot use zero-length edge");
210                                 return NULL;
211                         }
212         
213                         if (name[0] == 0) {
214                                 name = "Edge";
215                         }
216                         break;
217                 case ORIENTATION_FACE:
218                         if (createSpaceNormalTangent(mat, normal, plane) == 0) {
219                                 BKE_reports_prepend(reports, "Cannot use zero-area face");
220                                 return NULL;
221                         }
222         
223                         if (name[0] == 0) {
224                                 name = "Face";
225                         }
226                         break;
227                 default:
228                         return NULL;
229         }
230
231         return addMatrixSpace(C, mat, name, overwrite);
232 }
233
234 bool createSpaceNormal(float mat[3][3], const float normal[3])
235 {
236         float tangent[3] = {0.0f, 0.0f, 1.0f};
237         
238         copy_v3_v3(mat[2], normal);
239         if (normalize_v3(mat[2]) == 0.0f) {
240                 return false;  /* error return */
241         }
242
243         cross_v3_v3v3(mat[0], mat[2], tangent);
244         if (is_zero_v3(mat[0])) {
245                 tangent[0] = 1.0f;
246                 tangent[1] = tangent[2] = 0.0f;
247                 cross_v3_v3v3(mat[0], tangent, mat[2]);
248         }
249
250         cross_v3_v3v3(mat[1], mat[2], mat[0]);
251
252         normalize_m3(mat);
253         
254         return true;
255 }
256
257 /**
258  * \note To recreate an orientation from the matrix:
259  * - (plane  == mat[1])
260  * - (normal == mat[2])
261  */
262 bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3])
263 {
264         if (normalize_v3_v3(mat[2], normal) == 0.0f) {
265                 return false;  /* error return */
266         }
267
268         /* negate so we can use values from the matrix as input */
269         negate_v3_v3(mat[1], tangent);
270         /* preempt zero length tangent from causing trouble */
271         if (is_zero_v3(mat[1])) {
272                 mat[1][2] = 1.0f;
273         }
274
275         cross_v3_v3v3(mat[0], mat[2], mat[1]);
276         if (normalize_v3(mat[0]) == 0.0f) {
277                 return false;  /* error return */
278         }
279         
280         cross_v3_v3v3(mat[1], mat[2], mat[0]);
281         normalize_v3(mat[1]);
282
283         /* final matrix must be normalized, do inline */
284         // normalize_m3(mat);
285         
286         return true;
287 }
288
289 void BIF_createTransformOrientation(bContext *C, ReportList *reports,
290                                     const char *name, const bool use_view,
291                                     const bool activate, const bool overwrite)
292 {
293         TransformOrientation *ts = NULL;
294
295         if (use_view) {
296                 ts = createViewSpace(C, reports, name, overwrite);
297         }
298         else {
299                 Object *obedit = CTX_data_edit_object(C);
300                 Object *ob = CTX_data_active_object(C);
301                 if (obedit) {
302                         if (obedit->type == OB_MESH)
303                                 ts = createMeshSpace(C, reports, name, overwrite);
304                         else if (obedit->type == OB_ARMATURE)
305                                 ts = createBoneSpace(C, reports, name, overwrite);
306                         else if (obedit->type == OB_CURVE)
307                                 ts = createCurveSpace(C, reports, name, overwrite);
308                 }
309                 else if (ob && (ob->mode & OB_MODE_POSE)) {
310                         ts = createBoneSpace(C, reports, name, overwrite);
311                 }
312                 else {
313                         ts = createObjectSpace(C, reports, name, overwrite);
314                 }
315         }
316
317         if (activate && ts != NULL) {
318                 BIF_selectTransformOrientation(C, ts);
319         }
320 }
321
322 TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3],
323                                      const char *name, const bool overwrite)
324 {
325         TransformOrientation *ts = NULL;
326         WorkSpace *workspace = CTX_wm_workspace(C);
327         ListBase *transform_orientations = BKE_workspace_transform_orientations_get(workspace);
328         char name_unique[sizeof(ts->name)];
329
330         if (overwrite) {
331                 ts = findOrientationName(transform_orientations, name);
332         }
333         else {
334                 BLI_strncpy(name_unique, name, sizeof(name_unique));
335                 uniqueOrientationName(transform_orientations, name_unique);
336                 name = name_unique;
337         }
338
339         /* if not, create a new one */
340         if (ts == NULL) {
341                 ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix");
342                 BLI_addtail(transform_orientations, ts);
343                 BLI_strncpy(ts->name, name, sizeof(ts->name));
344         }
345
346         /* copy matrix into transform space */
347         copy_m3_m3(ts->mat, mat);
348
349         return ts;
350 }
351
352 void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target)
353 {
354         BKE_workspace_transform_orientation_remove(CTX_wm_workspace(C), target);
355 }
356
357 void BIF_removeTransformOrientationIndex(bContext *C, int index)
358 {
359         TransformOrientation *target = BKE_workspace_transform_orientation_find(CTX_wm_workspace(C), index);
360         BIF_removeTransformOrientation(C, target);
361 }
362
363 void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target)
364 {
365         int index = BKE_workspace_transform_orientation_get_index(CTX_wm_workspace(C), target);
366         View3D *v3d = CTX_wm_view3d(C);
367
368         BLI_assert(index != -1);
369
370         v3d->twmode = V3D_MANIP_CUSTOM;
371         v3d->custom_orientation_index = index;
372 }
373
374 /**
375  * Activate a transform orientation in a 3D view based on an enum value.
376  *
377  * \param orientation: If this is #V3D_MANIP_CUSTOM or greater, the custom transform orientation
378  *                     with index \a orientation - #V3D_MANIP_CUSTOM gets activated.
379  */
380 void BIF_selectTransformOrientationValue(View3D *v3d, int orientation)
381 {
382         const bool is_custom = orientation >= V3D_MANIP_CUSTOM;
383
384         v3d->twmode = is_custom ? V3D_MANIP_CUSTOM : orientation;
385         v3d->custom_orientation_index = is_custom ? (orientation - V3D_MANIP_CUSTOM) : -1;
386 }
387
388 int BIF_countTransformOrientation(const bContext *C)
389 {
390         WorkSpace *workspace = CTX_wm_workspace(C);
391         ListBase *transform_orientations = BKE_workspace_transform_orientations_get(workspace);
392         return BLI_listbase_count(transform_orientations);
393 }
394
395 bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name)
396 {
397         if (r_name) {
398                 BLI_strncpy(r_name, ts->name, MAX_NAME);
399         }
400         copy_m3_m3(r_mat, ts->mat);
401
402         return true;
403 }
404
405 static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it)
406 {
407         Bone *bone;
408         bool do_next;
409         int total = 0;
410         
411         for (bone = lb->first; bone; bone = bone->next) {
412                 bone->flag &= ~BONE_TRANSFORM;
413                 do_next = do_it;
414                 if (do_it) {
415                         if (bone->layer & arm->layer) {
416                                 if (bone->flag & BONE_SELECTED) {
417                                         bone->flag |= BONE_TRANSFORM;
418                                         total++;
419
420                                         /* no transform on children if one parent bone is selected */
421                                         do_next = false;
422                                 }
423                         }
424                 }
425                 total += count_bone_select(arm, &bone->childbase, do_next);
426         }
427         
428         return total;
429 }
430
431 void initTransformOrientation(bContext *C, TransInfo *t)
432 {
433         Object *ob = CTX_data_active_object(C);
434         Object *obedit = CTX_data_active_object(C);
435
436         switch (t->current_orientation) {
437                 case V3D_MANIP_GLOBAL:
438                         unit_m3(t->spacemtx);
439                         BLI_strncpy(t->spacename, IFACE_("global"), sizeof(t->spacename));
440                         break;
441
442                 case V3D_MANIP_GIMBAL:
443                         unit_m3(t->spacemtx);
444                         if (ob && gimbal_axis(ob, t->spacemtx)) {
445                                 BLI_strncpy(t->spacename, IFACE_("gimbal"), sizeof(t->spacename));
446                                 break;
447                         }
448                         ATTR_FALLTHROUGH;  /* no gimbal fallthrough to normal */
449                 case V3D_MANIP_NORMAL:
450                         if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
451                                 BLI_strncpy(t->spacename, IFACE_("normal"), sizeof(t->spacename));
452                                 ED_getTransformOrientationMatrix(C, t->spacemtx, t->around);
453                                 break;
454                         }
455                         ATTR_FALLTHROUGH;  /* we define 'normal' as 'local' in Object mode */
456                 case V3D_MANIP_LOCAL:
457                         BLI_strncpy(t->spacename, IFACE_("local"), sizeof(t->spacename));
458                 
459                         if (ob) {
460                                 copy_m3_m4(t->spacemtx, ob->obmat);
461                                 normalize_m3(t->spacemtx);
462                         }
463                         else {
464                                 unit_m3(t->spacemtx);
465                         }
466                 
467                         break;
468                 
469                 case V3D_MANIP_VIEW:
470                         if ((t->spacetype == SPACE_VIEW3D) &&
471                             (t->ar->regiontype == RGN_TYPE_WINDOW))
472                         {
473                                 RegionView3D *rv3d = t->ar->regiondata;
474                                 float mat[3][3];
475
476                                 BLI_strncpy(t->spacename, IFACE_("view"), sizeof(t->spacename));
477                                 copy_m3_m4(mat, rv3d->viewinv);
478                                 normalize_m3(mat);
479                                 copy_m3_m3(t->spacemtx, mat);
480                         }
481                         else {
482                                 unit_m3(t->spacemtx);
483                         }
484                         break;
485                 case V3D_MANIP_CUSTOM:
486                         BLI_strncpy(t->spacename, t->custom_orientation->name, sizeof(t->spacename));
487
488                         if (applyTransformOrientation(t->custom_orientation, t->spacemtx, t->spacename)) {
489                                 /* pass */
490                         }
491                         else {
492                                 unit_m3(t->spacemtx);
493                         }
494                         break;
495         }
496 }
497
498 /**
499  * utility function - get first n, selected vert/edge/faces
500  */
501 static unsigned int bm_mesh_elems_select_get_n__internal(
502         BMesh *bm, BMElem **elems, const unsigned int n,
503         const BMIterType itype, const char htype)
504 {
505         BMIter iter;
506         BMElem *ele;
507         unsigned int i;
508
509         BLI_assert(ELEM(htype, BM_VERT, BM_EDGE, BM_FACE));
510         BLI_assert(ELEM(itype, BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH));
511
512         if (!BLI_listbase_is_empty(&bm->selected)) {
513                 /* quick check */
514                 BMEditSelection *ese;
515                 i = 0;
516                 for (ese = bm->selected.last; ese; ese = ese->prev) {
517                         /* shouldn't need this check */
518                         if (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) {
519
520                                 /* only use contiguous selection */
521                                 if (ese->htype != htype) {
522                                         i = 0;
523                                         break;
524                                 }
525
526                                 elems[i++] = ese->ele;
527                                 if (n == i) {
528                                         break;
529                                 }
530                         }
531                         else {
532                                 BLI_assert(0);
533                         }
534                 }
535
536                 if (i == 0) {
537                         /* pass */
538                 }
539                 else if (i == n) {
540                         return i;
541                 }
542         }
543
544         i = 0;
545         BM_ITER_MESH (ele, &iter, bm, itype) {
546                 BLI_assert(ele->head.htype == htype);
547                 if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
548                         elems[i++] = ele;
549                         if (n == i) {
550                                 break;
551                         }
552                 }
553         }
554
555         return i;
556 }
557
558 static unsigned int bm_mesh_verts_select_get_n(BMesh *bm, BMVert **elems, const unsigned int n)
559 {
560         return bm_mesh_elems_select_get_n__internal(
561                 bm, (BMElem **)elems, min_ii(n, bm->totvertsel),
562                 BM_VERTS_OF_MESH, BM_VERT);
563 }
564 static unsigned int bm_mesh_edges_select_get_n(BMesh *bm, BMEdge **elems, const unsigned int n)
565 {
566         return bm_mesh_elems_select_get_n__internal(
567                 bm, (BMElem **)elems, min_ii(n, bm->totedgesel),
568                 BM_EDGES_OF_MESH, BM_EDGE);
569 }
570 #if 0
571 static unsigned int bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const unsigned int n)
572 {
573         return bm_mesh_elems_select_get_n__internal(
574                 bm, (BMElem **)elems, min_ii(n, bm->totfacesel),
575                 BM_FACES_OF_MESH, BM_FACE);
576 }
577 #endif
578
579 int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3], const short around)
580 {
581         ViewLayer *view_layer = CTX_data_view_layer(C);
582         Object *obedit = CTX_data_edit_object(C);
583         Base *base;
584         Object *ob = OBACT(view_layer);
585         int result = ORIENTATION_NONE;
586         const bool activeOnly = (around == V3D_AROUND_ACTIVE);
587
588         zero_v3(normal);
589         zero_v3(plane);
590
591         if (obedit) {
592                 float imat[3][3], mat[3][3];
593                 
594                 /* we need the transpose of the inverse for a normal... */
595                 copy_m3_m4(imat, ob->obmat);
596                 
597                 invert_m3_m3(mat, imat);
598                 transpose_m3(mat);
599
600                 ob = obedit;
601
602                 if (ob->type == OB_MESH) {
603                         BMEditMesh *em = BKE_editmesh_from_object(ob);
604                         BMEditSelection ese;
605                         float vec[3] = {0, 0, 0};
606                         
607                         /* USE LAST SELECTED WITH ACTIVE */
608                         if (activeOnly && BM_select_history_active_get(em->bm, &ese)) {
609                                 BM_editselection_normal(&ese, normal);
610                                 BM_editselection_plane(&ese, plane);
611                                 
612                                 switch (ese.htype) {
613                                         case BM_VERT:
614                                                 result = ORIENTATION_VERT;
615                                                 break;
616                                         case BM_EDGE:
617                                                 result = ORIENTATION_EDGE;
618                                                 break;
619                                         case BM_FACE:
620                                                 result = ORIENTATION_FACE;
621                                                 break;
622                                 }
623                         }
624                         else {
625                                 if (em->bm->totfacesel >= 1) {
626                                         BMFace *efa;
627                                         BMIter iter;
628
629                                         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
630                                                 if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
631                                                         BM_face_calc_tangent_auto(efa, vec);
632                                                         add_v3_v3(normal, efa->no);
633                                                         add_v3_v3(plane, vec);
634                                                 }
635                                         }
636                                         
637                                         result = ORIENTATION_FACE;
638                                 }
639                                 else if (em->bm->totvertsel == 3) {
640                                         BMVert *v_tri[3];
641
642                                         if (bm_mesh_verts_select_get_n(em->bm, v_tri, 3) == 3) {
643                                                 BMEdge *e = NULL;
644                                                 float no_test[3];
645
646                                                 normal_tri_v3(normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
647
648                                                 /* check if the normal is pointing opposite to vert normals */
649                                                 no_test[0] = v_tri[0]->no[0] + v_tri[1]->no[0] + v_tri[2]->no[0];
650                                                 no_test[1] = v_tri[0]->no[1] + v_tri[1]->no[1] + v_tri[2]->no[1];
651                                                 no_test[2] = v_tri[0]->no[2] + v_tri[1]->no[2] + v_tri[2]->no[2];
652                                                 if (dot_v3v3(no_test, normal) < 0.0f) {
653                                                         negate_v3(normal);
654                                                 }
655
656                                                 if (em->bm->totedgesel >= 1) {
657                                                         /* find an edge thats apart of v_tri (no need to search all edges) */
658                                                         float e_length;
659                                                         int j;
660
661                                                         for (j = 0; j < 3; j++) {
662                                                                 BMEdge *e_test = BM_edge_exists(v_tri[j], v_tri[(j + 1) % 3]);
663                                                                 if (e_test && BM_elem_flag_test(e_test, BM_ELEM_SELECT)) {
664                                                                         const float e_test_length = BM_edge_calc_length_squared(e_test);
665                                                                         if ((e == NULL) || (e_length < e_test_length)) {
666                                                                                 e = e_test;
667                                                                                 e_length = e_test_length;
668                                                                         }
669                                                                 }
670                                                         }
671                                                 }
672
673                                                 if (e) {
674                                                         BMVert *v_pair[2];
675                                                         if (BM_edge_is_boundary(e)) {
676                                                                 BM_edge_ordered_verts(e, &v_pair[0], &v_pair[1]);
677                                                         }
678                                                         else {
679                                                                 v_pair[0] = e->v1;
680                                                                 v_pair[1] = e->v2;
681                                                         }
682                                                         sub_v3_v3v3(plane, v_pair[0]->co, v_pair[1]->co);
683                                                 }
684                                                 else {
685                                                         BM_vert_tri_calc_tangent_edge(v_tri, plane);
686                                                 }
687                                         }
688                                         else {
689                                                 BLI_assert(0);
690                                         }
691
692                                         result = ORIENTATION_FACE;
693                                 }
694                                 else if (em->bm->totedgesel == 1 || em->bm->totvertsel == 2) {
695                                         BMVert *v_pair[2] = {NULL, NULL};
696                                         BMEdge *eed = NULL;
697                                         
698                                         if (em->bm->totedgesel == 1) {
699                                                 if (bm_mesh_edges_select_get_n(em->bm, &eed, 1) == 1) {
700                                                         v_pair[0] = eed->v1;
701                                                         v_pair[1] = eed->v2;
702                                                 }
703                                         }
704                                         else {
705                                                 BLI_assert(em->bm->totvertsel == 2);
706                                                 bm_mesh_verts_select_get_n(em->bm, v_pair, 2);
707                                         }
708
709                                         /* should never fail */
710                                         if (LIKELY(v_pair[0] && v_pair[1])) {
711                                                 bool v_pair_swap = false;
712                                                 /**
713                                                  * Logic explained:
714                                                  *
715                                                  * - Edges and vert-pairs treated the same way.
716                                                  * - Point the Y axis along the edge vector (towards the active vertex).
717                                                  * - Point the Z axis outwards (the same direction as the normals).
718                                                  *
719                                                  * \note Z points outwards - along the normal.
720                                                  * take care making changes here, see: T38592, T43708
721                                                  */
722
723                                                 /* be deterministic where possible and ensure v_pair[0] is active */
724                                                 if (BM_mesh_active_vert_get(em->bm) == v_pair[1]) {
725                                                         v_pair_swap = true;
726                                                 }
727                                                 else if (eed && BM_edge_is_boundary(eed)) {
728                                                         /* predictable direction for boundary edges */
729                                                         if (eed->l->v != v_pair[0]) {
730                                                                 v_pair_swap = true;
731                                                         }
732                                                 }
733
734                                                 if (v_pair_swap) {
735                                                         SWAP(BMVert *, v_pair[0], v_pair[1]);
736                                                 }
737
738                                                 add_v3_v3v3(normal, v_pair[1]->no, v_pair[0]->no);
739                                                 sub_v3_v3v3(plane, v_pair[1]->co, v_pair[0]->co);
740
741                                                 if (normalize_v3(plane) != 0.0f) {
742                                                         /* For edges it'd important the resulting matrix can rotate around the edge,
743                                                          * project onto the plane so we can use a fallback value. */
744                                                         project_plane_normalized_v3_v3v3(normal, normal, plane);
745                                                         if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
746                                                                 /* in the case the normal and plane are aligned,
747                                                                  * use a fallback normal which is orthogonal to the plane. */
748                                                                 ortho_v3_v3(normal, plane);
749                                                         }
750                                                 }
751                                         }
752
753                                         result = ORIENTATION_EDGE;
754                                 }
755                                 else if (em->bm->totvertsel == 1) {
756                                         BMVert *v = NULL;
757
758                                         if (bm_mesh_verts_select_get_n(em->bm, &v, 1) == 1) {
759                                                 copy_v3_v3(normal, v->no);
760                                                 BMEdge *e_pair[2];
761
762                                                 if (BM_vert_edge_pair(v, &e_pair[0], &e_pair[1])) {
763                                                         bool v_pair_swap = false;
764                                                         BMVert *v_pair[2] = {BM_edge_other_vert(e_pair[0], v), BM_edge_other_vert(e_pair[1], v)};
765                                                         float dir_pair[2][3];
766
767                                                         if (BM_edge_is_boundary(e_pair[0])) {
768                                                                 if (e_pair[0]->l->v != v) {
769                                                                         v_pair_swap = true;
770                                                                 }
771                                                         }
772                                                         else {
773                                                                 if (BM_edge_calc_length_squared(e_pair[0]) < BM_edge_calc_length_squared(e_pair[1])) {
774                                                                         v_pair_swap = true;
775                                                                 }
776                                                         }
777
778                                                         if (v_pair_swap) {
779                                                                 SWAP(BMVert *, v_pair[0], v_pair[1]);
780                                                         }
781
782                                                         sub_v3_v3v3(dir_pair[0], v->co, v_pair[0]->co);
783                                                         sub_v3_v3v3(dir_pair[1], v_pair[1]->co, v->co);
784                                                         normalize_v3(dir_pair[0]);
785                                                         normalize_v3(dir_pair[1]);
786
787                                                         add_v3_v3v3(plane, dir_pair[0], dir_pair[1]);
788                                                 }
789                                         }
790
791                                         if (is_zero_v3(plane)) {
792                                                 result = ORIENTATION_VERT;
793                                         }
794                                         else {
795                                                 result = ORIENTATION_EDGE;
796                                         }
797                                 }
798                                 else if (em->bm->totvertsel > 3) {
799                                         BMIter iter;
800                                         BMVert *v;
801
802                                         zero_v3(normal);
803
804                                         BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
805                                                 if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
806                                                         add_v3_v3(normal, v->no);
807                                                 }
808                                         }
809                                         normalize_v3(normal);
810                                         result = ORIENTATION_VERT;
811                                 }
812                         }
813
814                         /* not needed but this matches 2.68 and older behavior */
815                         negate_v3(plane);
816
817                 } /* end editmesh */
818                 else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
819                         Curve *cu = obedit->data;
820                         Nurb *nu = NULL;
821                         int a;
822                         ListBase *nurbs = BKE_curve_editNurbs_get(cu);
823
824                         void *vert_act = NULL;
825                         if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, &vert_act)) {
826                                 if (nu->type == CU_BEZIER) {
827                                         BezTriple *bezt = vert_act;
828                                         BKE_nurb_bezt_calc_normal(nu, bezt, normal);
829                                         BKE_nurb_bezt_calc_plane(nu, bezt, plane);
830                                 }
831                                 else {
832                                         BPoint *bp = vert_act;
833                                         BKE_nurb_bpoint_calc_normal(nu, bp, normal);
834                                         BKE_nurb_bpoint_calc_plane(nu, bp, plane);
835                                 }
836                         }
837                         else {
838                                 const bool use_handle = (cu->drawflag & CU_HIDE_HANDLES) == 0;
839
840                                 for (nu = nurbs->first; nu; nu = nu->next) {
841                                         /* only bezier has a normal */
842                                         if (nu->type == CU_BEZIER) {
843                                                 BezTriple *bezt = nu->bezt;
844                                                 a = nu->pntsu;
845                                                 while (a--) {
846                                                         short flag = 0;
847
848 #define SEL_F1 (1 << 0)
849 #define SEL_F2 (1 << 1)
850 #define SEL_F3 (1 << 2)
851
852                                                         if (use_handle) {
853                                                                 if (bezt->f1 & SELECT) flag |= SEL_F1;
854                                                                 if (bezt->f2 & SELECT) flag |= SEL_F2;
855                                                                 if (bezt->f3 & SELECT) flag |= SEL_F3;
856                                                         }
857                                                         else {
858                                                                 flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
859                                                         }
860
861                                                         /* exception */
862                                                         if (flag) {
863                                                                 float tvec[3];
864                                                                 if ((around == V3D_AROUND_LOCAL_ORIGINS) ||
865                                                                     ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
866                                                                 {
867                                                                         BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
868                                                                         add_v3_v3(normal, tvec);
869                                                                 }
870                                                                 else {
871                                                                         /* ignore bezt->f2 in this case */
872                                                                         if (flag & SEL_F1) {
873                                                                                 sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[1]);
874                                                                                 normalize_v3(tvec);
875                                                                                 add_v3_v3(normal, tvec);
876                                                                         }
877                                                                         if (flag & SEL_F3) {
878                                                                                 sub_v3_v3v3(tvec, bezt->vec[1], bezt->vec[2]);
879                                                                                 normalize_v3(tvec);
880                                                                                 add_v3_v3(normal, tvec);
881                                                                         }
882                                                                 }
883
884                                                                 BKE_nurb_bezt_calc_plane(nu, bezt, tvec);
885                                                                 add_v3_v3(plane, tvec);
886                                                         }
887
888 #undef SEL_F1
889 #undef SEL_F2
890 #undef SEL_F3
891
892                                                         bezt++;
893                                                 }
894                                         }
895                                         else if (nu->bp && (nu->pntsv == 1)) {
896                                                 BPoint *bp = nu->bp;
897                                                 a = nu->pntsu;
898                                                 while (a--) {
899                                                         if (bp->f1 & SELECT) {
900                                                                 float tvec[3];
901
902                                                                 BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
903                                                                 BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
904
905                                                                 const bool is_prev_sel = bp_prev && (bp_prev->f1 & SELECT);
906                                                                 const bool is_next_sel = bp_next && (bp_next->f1 & SELECT);
907                                                                 if (is_prev_sel == false && is_next_sel == false) {
908                                                                         /* Isolated, add based on surrounding */
909                                                                         BKE_nurb_bpoint_calc_normal(nu, bp, tvec);
910                                                                         add_v3_v3(normal, tvec);
911                                                                 }
912                                                                 else if (is_next_sel) {
913                                                                         /* A segment, add the edge normal */
914                                                                         sub_v3_v3v3(tvec, bp->vec, bp_next->vec );
915                                                                         normalize_v3(tvec);
916                                                                         add_v3_v3(normal, tvec);
917                                                                 }
918
919                                                                 BKE_nurb_bpoint_calc_plane(nu, bp, tvec);
920                                                                 add_v3_v3(plane, tvec);
921                                                         }
922                                                         bp++;
923                                                 }
924                                         }
925                                 }
926                         }
927                         
928                         if (!is_zero_v3(normal)) {
929                                 result = ORIENTATION_FACE;
930                         }
931                 }
932                 else if (obedit->type == OB_MBALL) {
933                         MetaBall *mb = obedit->data;
934                         MetaElem *ml;
935                         bool ok = false;
936                         float tmat[3][3];
937                         
938                         if (activeOnly && (ml = mb->lastelem)) {
939                                 quat_to_mat3(tmat, ml->quat);
940                                 add_v3_v3(normal, tmat[2]);
941                                 add_v3_v3(plane, tmat[1]);
942                                 ok = true;
943                         }
944                         else {
945                                 for (ml = mb->editelems->first; ml; ml = ml->next) {
946                                         if (ml->flag & SELECT) {
947                                                 quat_to_mat3(tmat, ml->quat);
948                                                 add_v3_v3(normal, tmat[2]);
949                                                 add_v3_v3(plane, tmat[1]);
950                                                 ok = true;
951                                         }
952                                 }
953                         }
954
955                         if (ok) {
956                                 if (!is_zero_v3(plane)) {
957                                         result = ORIENTATION_FACE;
958                                 }
959                         }
960                 }
961                 else if (obedit->type == OB_ARMATURE) {
962                         bArmature *arm = obedit->data;
963                         EditBone *ebone;
964                         bool ok = false;
965                         float tmat[3][3];
966
967                         if (activeOnly && (ebone = arm->act_edbone)) {
968                                 ED_armature_ebone_to_mat3(ebone, tmat);
969                                 add_v3_v3(normal, tmat[2]);
970                                 add_v3_v3(plane, tmat[1]);
971                                 ok = true;
972                         }
973                         else {
974                                 for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
975                                         if (arm->layer & ebone->layer) {
976                                                 if (ebone->flag & BONE_SELECTED) {
977                                                         ED_armature_ebone_to_mat3(ebone, tmat);
978                                                         add_v3_v3(normal, tmat[2]);
979                                                         add_v3_v3(plane, tmat[1]);
980                                                         ok = true;
981                                                 }
982                                         }
983                                 }
984                         }
985                         
986                         if (ok) {
987                                 if (!is_zero_v3(plane)) {
988                                         result = ORIENTATION_EDGE;
989                                 }
990                         }
991                 }
992
993                 /* Vectors from edges don't need the special transpose inverse multiplication */
994                 if (result == ORIENTATION_EDGE) {
995                         float tvec[3];
996
997                         mul_mat3_m4_v3(ob->obmat, normal);
998                         mul_mat3_m4_v3(ob->obmat, plane);
999
1000                         /* align normal to edge direction (so normal is perpendicular to the plane).
1001                          * 'ORIENTATION_EDGE' will do the other way around.
1002                          * This has to be done **after** applying obmat, see T45775! */
1003                         project_v3_v3v3(tvec, normal, plane);
1004                         sub_v3_v3(normal, tvec);
1005                 }
1006                 else {
1007                         mul_m3_v3(mat, normal);
1008                         mul_m3_v3(mat, plane);
1009                 }
1010         }
1011         else if (ob && (ob->mode & OB_MODE_POSE)) {
1012                 bArmature *arm = ob->data;
1013                 bPoseChannel *pchan;
1014                 float imat[3][3], mat[3][3];
1015                 bool ok = false;
1016
1017                 if (activeOnly && (pchan = BKE_pose_channel_active(ob))) {
1018                         add_v3_v3(normal, pchan->pose_mat[2]);
1019                         add_v3_v3(plane, pchan->pose_mat[1]);
1020                         ok = true;
1021                 }
1022                 else {
1023                         int totsel;
1024
1025                         totsel = count_bone_select(arm, &arm->bonebase, true);
1026                         if (totsel) {
1027                                 /* use channels to get stats */
1028                                 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1029                                         if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
1030                                                 add_v3_v3(normal, pchan->pose_mat[2]);
1031                                                 add_v3_v3(plane, pchan->pose_mat[1]);
1032                                         }
1033                                 }
1034                                 ok = true;
1035                         }
1036                 }
1037
1038                 /* use for both active & all */
1039                 if (ok) {
1040                         /* we need the transpose of the inverse for a normal... */
1041                         copy_m3_m4(imat, ob->obmat);
1042                         
1043                         invert_m3_m3(mat, imat);
1044                         transpose_m3(mat);
1045                         mul_m3_v3(mat, normal);
1046                         mul_m3_v3(mat, plane);
1047                         
1048                         result = ORIENTATION_EDGE;
1049                 }
1050         }
1051         else if (ob && (ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_PARTICLE_EDIT))) {
1052                 /* pass */
1053         }
1054         else {
1055                 /* we need the one selected object, if its not active */
1056                 base = BASACT(view_layer);
1057                 ob = OBACT(view_layer);
1058                 if (base && ((base->flag & BASE_SELECTED) != 0)) {
1059                         /* pass */
1060                 }
1061                 else {
1062                         /* first selected */
1063                         ob = NULL;
1064                         for (base = view_layer->object_bases.first; base; base = base->next) {
1065                                 if (TESTBASELIB(base)) {
1066                                         ob = base->object;
1067                                         break;
1068                                 }
1069                         }
1070                 }
1071                 
1072                 if (ob) {
1073                         copy_v3_v3(normal, ob->obmat[2]);
1074                         copy_v3_v3(plane, ob->obmat[1]);
1075                 }
1076                 result = ORIENTATION_NORMAL;
1077         }
1078         
1079         return result;
1080 }
1081
1082 int getTransformOrientation(const bContext *C, float normal[3], float plane[3])
1083 {
1084         /* dummy value, not V3D_AROUND_ACTIVE and not V3D_AROUND_LOCAL_ORIGINS */
1085         short around = V3D_AROUND_CENTER_BOUNDS;
1086
1087         return getTransformOrientation_ex(C, normal, plane, around);
1088 }
1089
1090 void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], const short around)
1091 {
1092         float normal[3] = {0.0, 0.0, 0.0};
1093         float plane[3] = {0.0, 0.0, 0.0};
1094
1095         int type;
1096
1097         type = getTransformOrientation_ex(C, normal, plane, around);
1098
1099         switch (type) {
1100                 case ORIENTATION_NORMAL:
1101                         if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
1102                                 type = ORIENTATION_NONE;
1103                         }
1104                         break;
1105                 case ORIENTATION_VERT:
1106                         if (createSpaceNormal(orientation_mat, normal) == 0) {
1107                                 type = ORIENTATION_NONE;
1108                         }
1109                         break;
1110                 case ORIENTATION_EDGE:
1111                         if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
1112                                 type = ORIENTATION_NONE;
1113                         }
1114                         break;
1115                 case ORIENTATION_FACE:
1116                         if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
1117                                 type = ORIENTATION_NONE;
1118                         }
1119                         break;
1120         }
1121
1122         if (type == ORIENTATION_NONE) {
1123                 unit_m3(orientation_mat);
1124         }
1125 }