2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/editors/transform/transform_conversions.c
29 * \ingroup edtransform
36 #include "DNA_anim_types.h"
37 #include "DNA_brush_types.h"
38 #include "DNA_armature_types.h"
39 #include "DNA_lattice_types.h"
40 #include "DNA_mesh_types.h"
41 #include "DNA_meta_types.h"
42 #include "DNA_node_types.h"
43 #include "DNA_screen_types.h"
44 #include "DNA_space_types.h"
45 #include "DNA_sequence_types.h"
46 #include "DNA_view3d_types.h"
47 #include "DNA_constraint_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_meshdata_types.h"
50 #include "DNA_gpencil_types.h"
51 #include "DNA_movieclip_types.h"
52 #include "DNA_mask_types.h"
54 #include "MEM_guardedalloc.h"
57 #include "BLI_utildefines.h"
58 #include "BLI_listbase.h"
59 #include "BLI_linklist_stack.h"
60 #include "BLI_string.h"
61 #include "BLI_bitmap.h"
64 #include "BKE_DerivedMesh.h"
65 #include "BKE_action.h"
66 #include "BKE_armature.h"
67 #include "BKE_constraint.h"
68 #include "BKE_context.h"
69 #include "BKE_crazyspace.h"
70 #include "BKE_curve.h"
71 #include "BKE_depsgraph.h"
72 #include "BKE_fcurve.h"
73 #include "BKE_global.h"
74 #include "BKE_gpencil.h"
78 #include "BKE_mesh_mapping.h"
79 #include "BKE_modifier.h"
80 #include "BKE_movieclip.h"
83 #include "BKE_object.h"
84 #include "BKE_particle.h"
85 #include "BKE_paint.h"
86 #include "BKE_pointcache.h"
87 #include "BKE_report.h"
88 #include "BKE_rigidbody.h"
89 #include "BKE_scene.h"
90 #include "BKE_sequencer.h"
91 #include "BKE_editmesh.h"
92 #include "BKE_tracking.h"
97 #include "ED_anim_api.h"
98 #include "ED_armature.h"
99 #include "ED_particle.h"
100 #include "ED_image.h"
101 #include "ED_keyframing.h"
102 #include "ED_keyframes_edit.h"
103 #include "ED_object.h"
104 #include "ED_markers.h"
107 #include "ED_uvedit.h"
110 #include "ED_gpencil.h"
112 #include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
113 #include "WM_types.h"
115 #include "UI_view2d.h"
116 #include "UI_interface.h"
118 #include "RNA_access.h"
120 #include "DEG_depsgraph.h"
122 #include "transform.h"
126 * Transforming around ourselves is no use, fallback to individual origins,
127 * useful for curve/armatures.
129 static void transform_around_single_fallback(TransInfo *t)
131 if ((t->total == 1) &&
132 (ELEM(t->around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEAN, V3D_AROUND_ACTIVE)) &&
133 (ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL)))
135 t->around = V3D_AROUND_LOCAL_ORIGINS;
139 /* when transforming islands */
140 struct TransIslandData {
145 /* local function prototype - for Object/Bone Constraints */
146 static bool constraints_list_needinv(TransInfo *t, ListBase *list);
148 /* ************************** Functions *************************** */
150 static int trans_data_compare_dist(const void *a, const void *b)
152 const TransData *td_a = (const TransData *)a;
153 const TransData *td_b = (const TransData *)b;
155 if (td_a->dist < td_b->dist) return -1;
156 else if (td_a->dist > td_b->dist) return 1;
160 static int trans_data_compare_rdist(const void *a, const void *b)
162 const TransData *td_a = (const TransData *)a;
163 const TransData *td_b = (const TransData *)b;
165 if (td_a->rdist < td_b->rdist) return -1;
166 else if (td_a->rdist > td_b->rdist) return 1;
170 void sort_trans_data_dist(TransInfo *t)
172 TransData *start = t->data;
175 for (i = 0; i < t->total && start->flag & TD_SELECTED; i++)
179 if (t->flag & T_PROP_CONNECTED)
180 qsort(start, t->total - i, sizeof(TransData), trans_data_compare_dist);
182 qsort(start, t->total - i, sizeof(TransData), trans_data_compare_rdist);
186 static void sort_trans_data(TransInfo *t)
188 TransData *sel, *unsel;
193 while (sel > unsel) {
194 while (unsel->flag & TD_SELECTED) {
200 while (!(sel->flag & TD_SELECTED)) {
214 /* distance calculated from not-selected vertex to nearest selected vertex
215 * warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
216 static void set_prop_dist(TransInfo *t, const bool with_dist)
222 const float *proj_vec = NULL;
224 /* support for face-islands */
225 const bool use_island = transdata_check_local_islands(t, t->around);
227 if (t->flag & T_PROP_PROJECTED) {
228 if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
229 RegionView3D *rv3d = t->ar->regiondata;
230 normalize_v3_v3(_proj_vec, rv3d->viewinv[2]);
231 proj_vec = _proj_vec;
235 for (a = 0, tob = t->data; a < t->total; a++, tob++) {
237 tob->rdist = 0.0f; // init, it was mallocced
239 if ((tob->flag & TD_SELECTED) == 0) {
242 float dist_sq, vec[3];
244 tob->rdist = -1.0f; // signal for next loop
246 for (i = 0, td = t->data; i < t->total; i++, td++) {
247 if (td->flag & TD_SELECTED) {
249 sub_v3_v3v3(vec, tob->iloc, td->iloc);
252 sub_v3_v3v3(vec, tob->center, td->center);
254 mul_m3_v3(tob->mtx, vec);
258 project_v3_v3v3(vec_p, vec, proj_vec);
259 sub_v3_v3(vec, vec_p);
262 dist_sq = len_squared_v3(vec);
263 if ((tob->rdist == -1.0f) || (dist_sq < SQUARE(tob->rdist))) {
264 tob->rdist = sqrtf(dist_sq);
266 copy_v3_v3(tob->center, td->center);
267 copy_m3_m3(tob->axismtx, td->axismtx);
272 break; /* by definition transdata has selected items in beginning */
276 tob->dist = tob->rdist;
282 /* ************************** CONVERSIONS ************************* */
284 /* ********************* texture space ********* */
286 static void createTransTexspace(TransInfo *t)
288 Scene *scene = t->scene;
296 if (ob == NULL) { // Shouldn't logically happen, but still...
302 if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) {
303 BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform");
308 if (BKE_object_obdata_is_libdata(ob)) {
309 BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
315 td = t->data = MEM_callocN(sizeof(TransData), "TransTexspace");
316 td->ext = t->ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
318 td->flag = TD_SELECTED;
319 copy_v3_v3(td->center, ob->obmat[3]);
322 copy_m3_m4(td->mtx, ob->obmat);
323 copy_m3_m4(td->axismtx, ob->obmat);
324 normalize_m3(td->axismtx);
325 pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
327 if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
328 ob->dtx |= OB_TEXSPACE;
329 *texflag &= ~ME_AUTOSPACE;
332 copy_v3_v3(td->iloc, td->loc);
333 copy_v3_v3(td->ext->irot, td->ext->rot);
334 copy_v3_v3(td->ext->isize, td->ext->size);
337 /* ********************* edge (for crease) ***** */
339 static void createTransEdge(TransInfo *t)
341 BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
342 TransData *td = NULL;
345 float mtx[3][3], smtx[3][3];
346 int count = 0, countsel = 0;
347 const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
348 int cd_edge_float_offset;
350 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
351 if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
352 if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) countsel++;
353 if (is_prop_edit) count++;
367 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransCrease");
369 copy_m3_m4(mtx, t->obedit->obmat);
370 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
372 /* create data we need */
373 if (t->mode == TFM_BWEIGHT) {
374 BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_EDGE_BWEIGHT);
375 cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
377 else { //if (t->mode == TFM_CREASE) {
378 BLI_assert(t->mode == TFM_CREASE);
379 BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_EDGE_CREASE);
380 cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
383 BLI_assert(cd_edge_float_offset != -1);
385 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
386 if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || is_prop_edit)) {
388 /* need to set center for center calculations */
389 mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
392 if (BM_elem_flag_test(eed, BM_ELEM_SELECT))
393 td->flag = TD_SELECTED;
397 copy_m3_m3(td->smtx, smtx);
398 copy_m3_m3(td->mtx, mtx);
402 fl_ptr = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_float_offset);
411 /* ********************* pose mode ************* */
413 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
415 bConstraint *con = pchan->constraints.first;
417 for (; con; con = con->next) {
418 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
419 bKinematicConstraint *data = con->data;
421 if (data->tar == NULL)
423 if (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0)
430 static short apply_targetless_ik(Object *ob)
432 bPoseChannel *pchan, *parchan, *chanlist[256];
433 bKinematicConstraint *data;
434 int segcount, apply = 0;
436 /* now we got a difficult situation... we have to find the
437 * target-less IK pchans, and apply transformation to the all
438 * pchans that were in the chain */
440 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
441 data = has_targetless_ik(pchan);
442 if (data && (data->flag & CONSTRAINT_IK_AUTO)) {
444 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
447 /* exclude tip from chain? */
448 if (!(data->flag & CONSTRAINT_IK_TIP))
449 parchan = pchan->parent;
453 /* Find the chain's root & count the segments needed */
454 for (; parchan; parchan = parchan->parent) {
455 chanlist[segcount] = parchan;
458 if (segcount == data->rootbone || segcount > 255) break; // 255 is weak
460 for (; segcount; segcount--) {
462 float rmat[4][4] /*, tmat[4][4], imat[4][4]*/;
464 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
465 /* we put in channel the entire result of rmat = (channel * constraint * IK) */
466 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
467 /* rmat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone ) */
469 parchan = chanlist[segcount - 1];
470 bone = parchan->bone;
471 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
473 BKE_armature_mat_pose_to_bone(parchan, parchan->pose_mat, rmat);
475 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
477 float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3];
479 copy_m3_m4(rmat3, rmat);
482 /* [#22409] is partially caused by this, as slight numeric error introduced during
483 * the solving process leads to locked-axis values changing. However, we cannot modify
484 * the values here, or else there are huge discrepancies between IK-solver (interactive)
487 if (parchan->rotmode > 0)
488 mat3_to_eulO(parchan->eul, parchan->rotmode, rmat3);
489 else if (parchan->rotmode == ROT_MODE_AXISANGLE)
490 mat3_to_axis_angle(parchan->rotAxis, &parchan->rotAngle, rmat3);
492 mat3_to_quat(parchan->quat, rmat3);
494 /* for size, remove rotation */
495 /* causes problems with some constraints (so apply only if needed) */
496 if (data->flag & CONSTRAINT_IK_STRETCH) {
497 if (parchan->rotmode > 0)
498 eulO_to_mat3(qrmat, parchan->eul, parchan->rotmode);
499 else if (parchan->rotmode == ROT_MODE_AXISANGLE)
500 axis_angle_to_mat3(qrmat, parchan->rotAxis, parchan->rotAngle);
502 quat_to_mat3(qrmat, parchan->quat);
504 invert_m3_m3(imat3, qrmat);
505 mul_m3_m3m3(smat, rmat3, imat3);
506 mat3_to_size(parchan->size, smat);
509 /* causes problems with some constraints (e.g. childof), so disable this */
510 /* as it is IK shouldn't affect location directly */
511 /* copy_v3_v3(parchan->loc, rmat[3]); */
517 data->flag &= ~CONSTRAINT_IK_AUTO;
524 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
526 Bone *bone = pchan->bone;
527 float pmat[3][3], omat[3][3];
528 float cmat[3][3], tmat[3][3];
531 copy_v3_v3(vec, pchan->pose_mat[3]);
532 copy_v3_v3(td->center, vec);
535 td->flag = TD_SELECTED;
536 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
537 td->flag |= TD_NOCENTER;
540 if (bone->flag & BONE_TRANSFORM_CHILD) {
541 td->flag |= TD_NOCENTER;
542 td->flag |= TD_NO_LOC;
545 td->protectflag = pchan->protectflag;
547 td->loc = pchan->loc;
548 copy_v3_v3(td->iloc, pchan->loc);
550 td->ext->size = pchan->size;
551 copy_v3_v3(td->ext->isize, pchan->size);
553 if (pchan->rotmode > 0) {
554 td->ext->rot = pchan->eul;
555 td->ext->rotAxis = NULL;
556 td->ext->rotAngle = NULL;
557 td->ext->quat = NULL;
559 copy_v3_v3(td->ext->irot, pchan->eul);
561 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
563 td->ext->rotAxis = pchan->rotAxis;
564 td->ext->rotAngle = &pchan->rotAngle;
565 td->ext->quat = NULL;
567 td->ext->irotAngle = pchan->rotAngle;
568 copy_v3_v3(td->ext->irotAxis, pchan->rotAxis);
572 td->ext->rotAxis = NULL;
573 td->ext->rotAngle = NULL;
574 td->ext->quat = pchan->quat;
576 copy_qt_qt(td->ext->iquat, pchan->quat);
578 td->ext->rotOrder = pchan->rotmode;
581 /* proper way to get parent transform + own transform + constraints transform */
582 copy_m3_m4(omat, ob->obmat);
584 /* New code, using "generic" BKE_pchan_to_pose_mat(). */
586 float rotscale_mat[4][4], loc_mat[4][4];
589 BKE_pchan_to_pose_mat(pchan, rotscale_mat, loc_mat);
590 if (t->mode == TFM_TRANSLATION)
591 copy_m3_m4(pmat, loc_mat);
593 copy_m3_m4(pmat, rotscale_mat);
595 /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal,
596 * and want align snapping, we just need both loc_mat and rotscale_mat.
597 * So simply always store rotscale mat in td->ext, and always use it to apply rotations...
598 * Ugly to need such hacks! :/ */
599 copy_m3_m4(rpmat, rotscale_mat);
601 if (constraints_list_needinv(t, &pchan->constraints)) {
602 copy_m3_m4(tmat, pchan->constinv);
603 invert_m3_m3(cmat, tmat);
604 mul_m3_series(td->mtx, cmat, omat, pmat);
605 mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat);
608 mul_m3_series(td->mtx, omat, pmat);
609 mul_m3_series(td->ext->r_mtx, omat, rpmat);
611 invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx);
614 pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
616 /* exceptional case: rotate the pose bone which also applies transformation
617 * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */
618 if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) {
620 /* same as td->smtx but without pchan->bone->bone_mat */
621 td->flag |= TD_PBONE_LOCAL_MTX_C;
622 mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx);
625 td->flag |= TD_PBONE_LOCAL_MTX_P;
629 /* for axismat we use bone's own transform */
630 copy_m3_m4(pmat, pchan->pose_mat);
631 mul_m3_m3m3(td->axismtx, omat, pmat);
632 normalize_m3(td->axismtx);
634 if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
635 bArmature *arm = t->poseobj->data;
637 if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
639 td->val = &bone->dist;
640 td->ival = bone->dist;
643 // abusive storage of scale in the loc pointer :)
644 td->loc = &bone->xwidth;
645 copy_v3_v3(td->iloc, td->loc);
650 /* in this case we can do target-less IK grabbing */
651 if (t->mode == TFM_TRANSLATION) {
652 bKinematicConstraint *data = has_targetless_ik(pchan);
654 if (data->flag & CONSTRAINT_IK_TIP) {
655 copy_v3_v3(data->grabtarget, pchan->pose_tail);
658 copy_v3_v3(data->grabtarget, pchan->pose_head);
660 td->loc = data->grabtarget;
661 copy_v3_v3(td->iloc, td->loc);
662 data->flag |= CONSTRAINT_IK_AUTO;
664 /* only object matrix correction */
665 copy_m3_m3(td->mtx, omat);
666 pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
670 /* store reference to first constraint */
671 td->con = pchan->constraints.first;
674 static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
676 Bone *bone = lb->first;
678 for (; bone; bone = bone->next) {
679 if ((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED)) {
680 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
682 else if ((bone->flag & BONE_TRANSFORM) &&
683 (mode == TFM_ROTATION || mode == TFM_TRACKBALL) &&
684 (around == V3D_AROUND_LOCAL_ORIGINS))
686 bone->flag |= BONE_TRANSFORM_CHILD;
689 bone->flag &= ~BONE_TRANSFORM;
692 bone_children_clear_transflag(mode, around, &bone->childbase);
696 /* sets transform flags in the bones
697 * returns total number of bones with BONE_TRANSFORM */
698 int count_set_pose_transflags(int *out_mode, short around, Object *ob)
700 bArmature *arm = ob->data;
703 int mode = *out_mode;
706 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
708 if (PBONE_VISIBLE(arm, bone)) {
709 if ((bone->flag & BONE_SELECTED))
710 bone->flag |= BONE_TRANSFORM;
712 bone->flag &= ~BONE_TRANSFORM;
714 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
715 bone->flag &= ~BONE_TRANSFORM_CHILD;
718 bone->flag &= ~BONE_TRANSFORM;
721 /* make sure no bone can be transformed when a parent is transformed */
722 /* since pchans are depsgraph sorted, the parents are in beginning of list */
723 if (!ELEM(mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
724 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
726 if (bone->flag & BONE_TRANSFORM)
727 bone_children_clear_transflag(mode, around, &bone->childbase);
730 /* now count, and check if we have autoIK or have to switch from translate to rotate */
731 bool has_translation = false, has_rotation = false;
733 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
735 if (bone->flag & BONE_TRANSFORM) {
738 if (mode == TFM_TRANSLATION) {
739 if (has_targetless_ik(pchan) == NULL) {
740 if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
741 if (pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
742 has_translation = true;
745 if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC)
746 has_translation = true;
748 if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT)
752 has_translation = true;
757 /* if there are no translatable bones, do rotation */
758 if (mode == TFM_TRANSLATION && !has_translation) {
760 *out_mode = TFM_ROTATION;
763 *out_mode = TFM_RESIZE;
771 /* -------- Auto-IK ---------- */
773 /* adjust pose-channel's auto-ik chainlen */
774 static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
777 bool changed = false;
779 /* don't bother to search if no valid constraints */
780 if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) {
784 /* check if pchan has ik-constraint */
785 for (con = pchan->constraints.first; con; con = con->next) {
786 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
787 bKinematicConstraint *data = con->data;
789 /* only accept if a temporary one (for auto-ik) */
790 if (data->flag & CONSTRAINT_IK_TEMP) {
791 /* chainlen is new chainlen, but is limited by maximum chainlen */
792 const int old_rootbone = data->rootbone;
793 if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
794 data->rootbone = data->max_rootbone;
797 data->rootbone = chainlen;
799 changed |= (data->rootbone != old_rootbone);
807 /* change the chain-length of auto-ik */
808 void transform_autoik_update(TransInfo *t, short mode)
810 short *chainlen = &t->settings->autoik_chainlen;
813 /* mode determines what change to apply to chainlen */
815 /* mode=1 is from WHEELMOUSEDOWN... increases len */
818 else if (mode == -1) {
819 /* mode==-1 is from WHEELMOUSEUP... decreases len */
824 /* IK length did not change, skip updates. */
829 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
830 if (ELEM(NULL, t->poseobj, t->poseobj->pose))
833 /* apply to all pose-channels */
834 bool changed = false;
835 for (pchan = t->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
836 changed |= pchan_autoik_adjust(pchan, *chainlen);
839 #ifdef WITH_LEGACY_DEPSGRAPH
840 if (!DEG_depsgraph_use_legacy())
844 /* TODO(sergey): Consider doing partial update only. */
845 DAG_relations_tag_update(G.main);
850 /* frees temporal IKs */
851 static void pose_grab_with_ik_clear(Object *ob)
853 bKinematicConstraint *data;
855 bConstraint *con, *next;
856 #ifdef WITH_LEGACY_DEPSGRAPH
857 bool need_dependency_update = false;
860 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
861 /* clear all temporary lock flags */
862 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP | BONE_IK_NO_YDOF_TEMP | BONE_IK_NO_ZDOF_TEMP);
864 pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
866 /* remove all temporary IK-constraints added */
867 for (con = pchan->constraints.first; con; con = next) {
869 if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
871 if (data->flag & CONSTRAINT_IK_TEMP) {
872 /* iTaSC needs clear for removed constraints */
873 #ifdef WITH_LEGACY_DEPSGRAPH
874 need_dependency_update = true;
876 BIK_clear_data(ob->pose);
878 BLI_remlink(&pchan->constraints, con);
879 MEM_freeN(con->data);
883 pchan->constflag |= PCHAN_HAS_IK;
884 if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0))
885 pchan->constflag |= PCHAN_HAS_TARGET;
890 #ifdef WITH_LEGACY_DEPSGRAPH
891 if (!DEG_depsgraph_use_legacy() && need_dependency_update)
894 /* TODO(sergey): Consider doing partial update only. */
895 DAG_relations_tag_update(G.main);
899 /* adds the IK to pchan - returns if added */
900 static short pose_grab_with_ik_add(bPoseChannel *pchan)
902 bKinematicConstraint *targetless = NULL;
903 bKinematicConstraint *data;
910 /* Rule: not if there's already an IK on this channel */
911 for (con = pchan->constraints.first; con; con = con->next) {
912 if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
915 if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == '\0')) {
916 /* make reference to constraint to base things off later (if it's the last targetless constraint encountered) */
917 targetless = (bKinematicConstraint *)con->data;
919 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
920 if (con->enforce != 0.0f) {
921 data->flag |= CONSTRAINT_IK_AUTO;
923 /* if no chain length has been specified, just make things obey standard rotation locks too */
924 if (data->rootbone == 0) {
925 for (; pchan; pchan = pchan->parent) {
926 /* here, we set ik-settings for bone from pchan->protectflag */
927 // XXX: careful with quats/axis-angle rotations where we're locking 4d components
928 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
929 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
930 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
938 if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f))
943 con = BKE_constraint_add_for_pose(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
944 pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
947 /* if exists, use values from last targetless (but disabled) IK-constraint as base */
951 data->flag = CONSTRAINT_IK_TIP;
952 data->flag |= CONSTRAINT_IK_TEMP | CONSTRAINT_IK_AUTO | CONSTRAINT_IK_POS;
953 copy_v3_v3(data->grabtarget, pchan->pose_tail);
954 data->rootbone = 0; /* watch-it! has to be 0 here, since we're still on the same bone for the first time through the loop [#25885] */
956 /* we only include bones that are part of a continual connected chain */
958 /* here, we set ik-settings for bone from pchan->protectflag */
959 // XXX: careful with quats/axis-angle rotations where we're locking 4d components
960 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
961 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
962 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
964 /* now we count this pchan as being included */
967 /* continue to parent, but only if we're connected to it */
968 if (pchan->bone->flag & BONE_CONNECTED)
969 pchan = pchan->parent;
974 /* make a copy of maximum chain-length */
975 data->max_rootbone = data->rootbone;
980 /* bone is a candidate to get IK, but we don't do it if it has children connected */
981 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
984 short wentdeeper = 0, added = 0;
986 /* go deeper if children & children are connected */
987 for (bonec = bone->childbase.first; bonec; bonec = bonec->next) {
988 if (bonec->flag & BONE_CONNECTED) {
990 added += pose_grab_with_ik_children(pose, bonec);
993 if (wentdeeper == 0) {
994 bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
996 added += pose_grab_with_ik_add(pchan);
1002 /* main call which adds temporal IK chains */
1003 static short pose_grab_with_ik(Object *ob)
1006 bPoseChannel *pchan, *parent;
1010 if ((ob == NULL) || (ob->pose == NULL) || (ob->mode & OB_MODE_POSE) == 0)
1015 /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
1016 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1017 if (pchan->bone->layer & arm->layer) {
1018 if (pchan->bone->flag & BONE_SELECTED) {
1019 /* Rule: no IK for solitatry (unconnected) bones */
1020 for (bonec = pchan->bone->childbase.first; bonec; bonec = bonec->next) {
1021 if (bonec->flag & BONE_CONNECTED) {
1025 if ((pchan->bone->flag & BONE_CONNECTED) == 0 && (bonec == NULL))
1028 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
1029 if (pchan->parent) {
1030 /* only adds if there's no IK yet (and no parent bone was selected) */
1031 for (parent = pchan->parent; parent; parent = parent->parent) {
1032 if (parent->bone->flag & BONE_SELECTED)
1036 tot_ik += pose_grab_with_ik_add(pchan);
1039 /* rule: go over the children and add IK to the tips */
1040 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
1046 /* iTaSC needs clear for new IK constraints */
1048 BIK_clear_data(ob->pose);
1049 #ifdef WITH_LEGACY_DEPSGRAPH
1050 if (!DEG_depsgraph_use_legacy())
1053 /* TODO(sergey): Consuder doing partial update only. */
1054 DAG_relations_tag_update(G.main);
1058 return (tot_ik) ? 1 : 0;
1062 /* only called with pose mode active object now */
1063 static void createTransPose(TransInfo *t, Object *ob)
1066 bPoseChannel *pchan;
1068 TransDataExtension *tdx;
1074 /* check validity of state */
1075 arm = BKE_armature_from_object(ob);
1076 if ((arm == NULL) || (ob->pose == NULL)) return;
1078 if (arm->flag & ARM_RESTPOS) {
1079 if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) {
1080 BKE_report(t->reports, RPT_ERROR, "Cannot change Pose when 'Rest Position' is enabled");
1085 /* do we need to add temporal IK chains? */
1086 if ((arm->flag & ARM_AUTO_IK) && t->mode == TFM_TRANSLATION) {
1087 ik_on = pose_grab_with_ik(ob);
1088 if (ik_on) t->flag |= T_AUTOIK;
1091 /* set flags and count total (warning, can change transform to rotate) */
1092 t->total = count_set_pose_transflags(&t->mode, t->around, ob);
1094 if (t->total == 0) return;
1097 t->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */
1099 /* disable PET, its not usable in pose mode yet [#32444] */
1100 t->flag &= ~T_PROP_EDIT_ALL;
1102 /* init trans data */
1103 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransPoseBone");
1104 tdx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "TransPoseBoneExt");
1105 for (i = 0; i < t->total; i++, td++, tdx++) {
1110 /* use pose channels to fill trans data */
1112 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1113 if (pchan->bone->flag & BONE_TRANSFORM) {
1114 add_pose_transdata(t, pchan, ob, td);
1119 if (td != (t->data + t->total)) {
1120 BKE_report(t->reports, RPT_DEBUG, "Bone selection count error");
1123 /* initialize initial auto=ik chainlen's? */
1124 if (ik_on) transform_autoik_update(t, 0);
1127 void restoreBones(TransInfo *t)
1129 bArmature *arm = t->obedit->data;
1130 BoneInitData *bid = t->custom.type.data;
1136 ebo->dist = bid->dist;
1137 ebo->rad_tail = bid->rad_tail;
1138 ebo->roll = bid->roll;
1139 ebo->xwidth = bid->xwidth;
1140 ebo->zwidth = bid->zwidth;
1141 copy_v3_v3(ebo->head, bid->head);
1142 copy_v3_v3(ebo->tail, bid->tail);
1144 if (arm->flag & ARM_MIRROR_EDIT) {
1145 EditBone *ebo_child;
1147 /* Also move connected ebo_child, in case ebo_child's name aren't mirrored properly */
1148 for (ebo_child = arm->edbo->first; ebo_child; ebo_child = ebo_child->next) {
1149 if ((ebo_child->flag & BONE_CONNECTED) && (ebo_child->parent == ebo)) {
1150 copy_v3_v3(ebo_child->head, ebo->tail);
1151 ebo_child->rad_head = ebo->rad_tail;
1155 /* Also move connected parent, in case parent's name isn't mirrored properly */
1156 if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
1157 EditBone *parent = ebo->parent;
1158 copy_v3_v3(parent->tail, ebo->head);
1159 parent->rad_tail = ebo->rad_head;
1168 /* ********************* armature ************** */
1169 static void createTransArmatureVerts(TransInfo *t)
1171 EditBone *ebo, *eboflip;
1172 bArmature *arm = t->obedit->data;
1173 ListBase *edbo = arm->edbo;
1174 TransData *td, *td_old;
1175 float mtx[3][3], smtx[3][3], bonemat[3][3];
1176 bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
1177 int total_mirrored = 0, i;
1182 for (ebo = edbo->first; ebo; ebo = ebo->next) {
1185 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
1186 if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
1187 if (ebo->flag & BONE_SELECTED)
1190 else if (t->mode == TFM_BONE_ROLL) {
1191 if (ebo->flag & BONE_SELECTED)
1195 if (ebo->flag & BONE_TIPSEL)
1197 if (ebo->flag & BONE_ROOTSEL)
1202 if (mirror && (oldtot < t->total)) {
1203 eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
1209 if (!t->total) return;
1211 transform_around_single_fallback(t);
1213 copy_m3_m4(mtx, t->obedit->obmat);
1214 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
1216 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransEditBone");
1219 t->custom.type.data = bid = MEM_mallocN((total_mirrored + 1) * sizeof(BoneInitData), "BoneInitData");
1220 t->custom.type.use_free = true;
1225 for (ebo = edbo->first; ebo; ebo = ebo->next) {
1227 ebo->oldlength = ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
1229 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
1230 if (t->mode == TFM_BONE_ENVELOPE) {
1231 if (ebo->flag & BONE_ROOTSEL) {
1232 td->val = &ebo->rad_head;
1233 td->ival = *td->val;
1235 copy_v3_v3(td->center, ebo->head);
1236 td->flag = TD_SELECTED;
1238 copy_m3_m3(td->smtx, smtx);
1239 copy_m3_m3(td->mtx, mtx);
1247 if (ebo->flag & BONE_TIPSEL) {
1248 td->val = &ebo->rad_tail;
1249 td->ival = *td->val;
1250 copy_v3_v3(td->center, ebo->tail);
1251 td->flag = TD_SELECTED;
1253 copy_m3_m3(td->smtx, smtx);
1254 copy_m3_m3(td->mtx, mtx);
1264 else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
1265 if (ebo->flag & BONE_SELECTED) {
1266 if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
1268 td->val = &ebo->dist;
1269 td->ival = ebo->dist;
1272 // abusive storage of scale in the loc pointer :)
1273 td->loc = &ebo->xwidth;
1274 copy_v3_v3(td->iloc, td->loc);
1277 copy_v3_v3(td->center, ebo->head);
1278 td->flag = TD_SELECTED;
1280 /* use local bone matrix */
1281 ED_armature_ebone_to_mat3(ebo, bonemat);
1282 mul_m3_m3m3(td->mtx, mtx, bonemat);
1283 invert_m3_m3(td->smtx, td->mtx);
1285 copy_m3_m3(td->axismtx, td->mtx);
1286 normalize_m3(td->axismtx);
1294 else if (t->mode == TFM_BONE_ROLL) {
1295 if (ebo->flag & BONE_SELECTED) {
1297 td->val = &(ebo->roll);
1298 td->ival = ebo->roll;
1300 copy_v3_v3(td->center, ebo->head);
1301 td->flag = TD_SELECTED;
1310 if (ebo->flag & BONE_TIPSEL) {
1311 copy_v3_v3(td->iloc, ebo->tail);
1313 /* Don't allow single selected tips to have a modified center,
1314 * causes problem with snapping (see T45974).
1315 * However, in rotation mode, we want to keep that 'rotate bone around root with
1316 * only its tip selected' behavior (see T46325). */
1317 if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
1318 ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL)))
1320 copy_v3_v3(td->center, ebo->head);
1323 copy_v3_v3(td->center, td->iloc);
1326 td->loc = ebo->tail;
1327 td->flag = TD_SELECTED;
1328 if (ebo->flag & BONE_EDITMODE_LOCKED)
1329 td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
1331 copy_m3_m3(td->smtx, smtx);
1332 copy_m3_m3(td->mtx, mtx);
1334 ED_armature_ebone_to_mat3(ebo, td->axismtx);
1336 if ((ebo->flag & BONE_ROOTSEL) == 0) {
1338 td->ival = ebo->roll;
1347 if (ebo->flag & BONE_ROOTSEL) {
1348 copy_v3_v3(td->iloc, ebo->head);
1349 copy_v3_v3(td->center, td->iloc);
1350 td->loc = ebo->head;
1351 td->flag = TD_SELECTED;
1352 if (ebo->flag & BONE_EDITMODE_LOCKED)
1353 td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
1355 copy_m3_m3(td->smtx, smtx);
1356 copy_m3_m3(td->mtx, mtx);
1358 ED_armature_ebone_to_mat3(ebo, td->axismtx);
1360 td->extra = ebo; /* to fix roll */
1361 td->ival = ebo->roll;
1372 if (mirror && (td_old != td)) {
1373 eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
1375 bid[i].bone = eboflip;
1376 bid[i].dist = eboflip->dist;
1377 bid[i].rad_tail = eboflip->rad_tail;
1378 bid[i].roll = eboflip->roll;
1379 bid[i].xwidth = eboflip->xwidth;
1380 bid[i].zwidth = eboflip->zwidth;
1381 copy_v3_v3(bid[i].head, eboflip->head);
1382 copy_v3_v3(bid[i].tail, eboflip->tail);
1389 /* trick to terminate iteration */
1390 bid[total_mirrored].bone = NULL;
1394 /* ********************* meta elements ********* */
1396 static void createTransMBallVerts(TransInfo *t)
1398 MetaBall *mb = (MetaBall *)t->obedit->data;
1401 TransDataExtension *tx;
1402 float mtx[3][3], smtx[3][3];
1403 int count = 0, countsel = 0;
1404 const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
1407 for (ml = mb->editelems->first; ml; ml = ml->next) {
1408 if (ml->flag & SELECT) countsel++;
1409 if (is_prop_edit) count++;
1412 /* note: in prop mode we need at least 1 selected */
1413 if (countsel == 0) return;
1415 if (is_prop_edit) t->total = count;
1416 else t->total = countsel;
1418 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(MBall EditMode)");
1419 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "MetaElement_TransExtension");
1421 copy_m3_m4(mtx, t->obedit->obmat);
1422 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
1424 for (ml = mb->editelems->first; ml; ml = ml->next) {
1425 if (is_prop_edit || (ml->flag & SELECT)) {
1427 copy_v3_v3(td->iloc, td->loc);
1428 copy_v3_v3(td->center, td->loc);
1430 quat_to_mat3(td->axismtx, ml->quat);
1432 if (ml->flag & SELECT) td->flag = TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1433 else td->flag = TD_USEQUAT;
1435 copy_m3_m3(td->smtx, smtx);
1436 copy_m3_m3(td->mtx, mtx);
1440 /* Radius of MetaElem (mass of MetaElem influence) */
1441 if (ml->flag & MB_SCALE_RAD) {
1450 /* expx/expy/expz determine "shape" of some MetaElem types */
1451 tx->size = &ml->expx;
1452 tx->isize[0] = ml->expx;
1453 tx->isize[1] = ml->expy;
1454 tx->isize[2] = ml->expz;
1456 /* quat is used for rotation of MetaElem */
1457 tx->quat = ml->quat;
1458 copy_qt_qt(tx->iquat, ml->quat);
1468 /* ********************* curve/surface ********* */
1470 static void calc_distanceCurveVerts(TransData *head, TransData *tail)
1472 TransData *td, *td_near = NULL;
1473 for (td = head; td <= tail; td++) {
1474 if (td->flag & TD_SELECTED) {
1480 dist = len_v3v3(td_near->center, td->center);
1481 if (dist < (td - 1)->dist) {
1482 td->dist = (td - 1)->dist;
1490 td->flag |= TD_NOTCONNECTED;
1494 for (td = tail; td >= head; td--) {
1495 if (td->flag & TD_SELECTED) {
1501 dist = len_v3v3(td_near->center, td->center);
1502 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td + 1)->dist < td->dist) {
1503 td->flag &= ~TD_NOTCONNECTED;
1504 if (dist < (td + 1)->dist) {
1505 td->dist = (td + 1)->dist;
1515 /* Utility function for getting the handle data from bezier's */
1516 static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt)
1518 TransDataCurveHandleFlags *hdata;
1519 td->flag |= TD_BEZTRIPLE;
1520 hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1521 hdata->ih1 = bezt->h1;
1522 hdata->h1 = &bezt->h1;
1523 hdata->ih2 = bezt->h2; /* in case the second is not selected */
1524 hdata->h2 = &bezt->h2;
1529 * For the purpose of transform code we need to behave as if handles are selected,
1530 * even when they aren't (see special case below).
1532 static int bezt_select_to_transform_triple_flag(
1533 const BezTriple *bezt, const bool hide_handles)
1538 if (bezt->f2 & SELECT) {
1539 flag = (1 << 0) | (1 << 1) | (1 << 2);
1544 ((bezt->f1 & SELECT) ? (1 << 0) : 0) |
1545 ((bezt->f2 & SELECT) ? (1 << 1) : 0) |
1546 ((bezt->f3 & SELECT) ? (1 << 2) : 0)
1550 /* Special case for auto & aligned handles:
1551 * When a center point is being moved without the handles,
1552 * leaving the handles stationary makes no sense and only causes strange behavior,
1553 * where one handle is arbitrarily anchored, the other one is aligned and lengthened
1554 * based on where the center point is moved. Also a bug when cancelling, see: T52007.
1556 * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'.
1557 * However that doesn't resolve odd behavior, so best transform the handles in this case.
1559 if ((flag != ((1 << 0) | (1 << 1) | (1 << 2))) && (flag & (1 << 1))) {
1560 if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) &&
1561 ELEM(bezt->h2, HD_AUTO, HD_ALIGN))
1563 flag = (1 << 0) | (1 << 1) | (1 << 2);
1570 static void createTransCurveVerts(TransInfo *t)
1572 Curve *cu = t->obedit->data;
1573 TransData *td = NULL;
1577 float mtx[3][3], smtx[3][3];
1579 int count = 0, countsel = 0;
1580 const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
1581 short hide_handles = (cu->drawflag & CU_HIDE_HANDLES);
1585 if (cu->editnurb == NULL) return;
1587 #define SEL_F1 (1 << 0)
1588 #define SEL_F2 (1 << 1)
1589 #define SEL_F3 (1 << 2)
1591 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1592 nurbs = BKE_curve_editNurbs_get(cu);
1593 for (nu = nurbs->first; nu; nu = nu->next) {
1594 if (nu->type == CU_BEZIER) {
1595 for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
1596 if (bezt->hide == 0) {
1597 const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
1598 if (bezt_tx & SEL_F1) { countsel++; }
1599 if (bezt_tx & SEL_F2) { countsel++; }
1600 if (bezt_tx & SEL_F3) { countsel++; }
1601 if (is_prop_edit) count += 3;
1607 for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
1608 if (bp->hide == 0) {
1609 if (is_prop_edit) count++;
1610 if (bp->f1 & SELECT) countsel++;
1615 /* note: in prop mode we need at least 1 selected */
1616 if (countsel == 0) return;
1618 if (is_prop_edit) t->total = count;
1619 else t->total = countsel;
1620 t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)");
1622 transform_around_single_fallback(t);
1624 copy_m3_m4(mtx, t->obedit->obmat);
1625 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
1628 for (nu = nurbs->first; nu; nu = nu->next) {
1629 if (nu->type == CU_BEZIER) {
1630 TransData *head, *tail;
1632 for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
1633 if (bezt->hide == 0) {
1634 TransDataCurveHandleFlags *hdata = NULL;
1635 float axismtx[3][3];
1637 if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
1638 float normal[3], plane[3];
1640 BKE_nurb_bezt_calc_normal(nu, bezt, normal);
1641 BKE_nurb_bezt_calc_plane(nu, bezt, plane);
1643 if (createSpaceNormalTangent(axismtx, normal, plane)) {
1647 normalize_v3(normal);
1648 axis_dominant_v3_to_m3(axismtx, normal);
1653 /* Elements that will be transform (not always a match to selection). */
1654 const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
1656 if (is_prop_edit || bezt_tx & SEL_F1) {
1657 copy_v3_v3(td->iloc, bezt->vec[0]);
1658 td->loc = bezt->vec[0];
1659 copy_v3_v3(td->center, bezt->vec[(hide_handles ||
1660 (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
1661 (bezt->f2 & SELECT)) ? 1 : 0]);
1663 if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
1667 if (bezt->f1 & SELECT) td->flag = TD_SELECTED;
1673 hdata = initTransDataCurveHandles(td, bezt);
1675 copy_m3_m3(td->smtx, smtx);
1676 copy_m3_m3(td->mtx, mtx);
1677 if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
1678 copy_m3_m3(td->axismtx, axismtx);
1686 /* This is the Curve Point, the other two are handles */
1687 if (is_prop_edit || bezt_tx & SEL_F2) {
1688 copy_v3_v3(td->iloc, bezt->vec[1]);
1689 td->loc = bezt->vec[1];
1690 copy_v3_v3(td->center, td->loc);
1691 if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
1695 if (t->mode == TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1696 td->val = &(bezt->radius);
1697 td->ival = bezt->radius;
1699 else if (t->mode == TFM_TILT) {
1700 td->val = &(bezt->alfa);
1701 td->ival = bezt->alfa;
1707 copy_m3_m3(td->smtx, smtx);
1708 copy_m3_m3(td->mtx, mtx);
1709 if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
1710 copy_m3_m3(td->axismtx, axismtx);
1713 if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0)
1714 /* If the middle is selected but the sides arnt, this is needed */
1715 if (hdata == NULL) { /* if the handle was not saved by the previous handle */
1716 hdata = initTransDataCurveHandles(td, bezt);
1723 if (is_prop_edit || bezt_tx & SEL_F3) {
1724 copy_v3_v3(td->iloc, bezt->vec[2]);
1725 td->loc = bezt->vec[2];
1726 copy_v3_v3(td->center, bezt->vec[(hide_handles ||
1727 (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
1728 (bezt->f2 & SELECT)) ? 1 : 2]);
1730 if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
1734 if (bezt->f3 & SELECT) td->flag = TD_SELECTED;
1740 if (hdata == NULL) { /* if the handle was not saved by the previous handle */
1741 hdata = initTransDataCurveHandles(td, bezt);
1744 copy_m3_m3(td->smtx, smtx);
1745 copy_m3_m3(td->mtx, mtx);
1746 if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
1747 copy_m3_m3(td->axismtx, axismtx);
1755 (void)hdata; /* quiet warning */
1757 else if (is_prop_edit && head != tail) {
1758 calc_distanceCurveVerts(head, tail - 1);
1762 if (is_prop_edit && head != tail)
1763 calc_distanceCurveVerts(head, tail - 1);
1765 /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles
1766 * but for now just don't change handle types */
1767 if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) {
1768 /* sets the handles based on their selection, do this after the data is copied to the TransData */
1769 BKE_nurb_handles_test(nu, !hide_handles);
1773 TransData *head, *tail;
1775 for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
1776 if (bp->hide == 0) {
1777 if (is_prop_edit || (bp->f1 & SELECT)) {
1778 float axismtx[3][3];
1780 if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
1781 if (nu->pntsv == 1) {
1782 float normal[3], plane[3];
1784 BKE_nurb_bpoint_calc_normal(nu, bp, normal);
1785 BKE_nurb_bpoint_calc_plane(nu, bp, plane);
1787 if (createSpaceNormalTangent(axismtx, normal, plane)) {
1791 normalize_v3(normal);
1792 axis_dominant_v3_to_m3(axismtx, normal);
1798 copy_v3_v3(td->iloc, bp->vec);
1800 copy_v3_v3(td->center, td->loc);
1801 if (bp->f1 & SELECT) td->flag = TD_SELECTED;
1805 if (t->mode == TFM_CURVE_SHRINKFATTEN || t->mode == TFM_RESIZE) {
1806 td->val = &(bp->radius);
1807 td->ival = bp->radius;
1810 td->val = &(bp->alfa);
1811 td->ival = bp->alfa;
1814 copy_m3_m3(td->smtx, smtx);
1815 copy_m3_m3(td->mtx, mtx);
1816 if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
1817 if (nu->pntsv == 1) {
1818 copy_m3_m3(td->axismtx, axismtx);
1827 else if (is_prop_edit && head != tail) {
1828 calc_distanceCurveVerts(head, tail - 1);
1832 if (is_prop_edit && head != tail)
1833 calc_distanceCurveVerts(head, tail - 1);
1842 /* ********************* lattice *************** */
1844 static void createTransLatticeVerts(TransInfo *t)
1846 Lattice *latt = ((Lattice *)t->obedit->data)->editlatt->latt;
1847 TransData *td = NULL;
1849 float mtx[3][3], smtx[3][3];
1851 int count = 0, countsel = 0;
1852 const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
1855 a = latt->pntsu * latt->pntsv * latt->pntsw;
1857 if (bp->hide == 0) {
1858 if (bp->f1 & SELECT) countsel++;
1859 if (is_prop_edit) count++;
1864 /* note: in prop mode we need at least 1 selected */
1865 if (countsel == 0) return;
1867 if (is_prop_edit) t->total = count;
1868 else t->total = countsel;
1869 t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Lattice EditMode)");
1871 copy_m3_m4(mtx, t->obedit->obmat);
1872 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
1876 a = latt->pntsu * latt->pntsv * latt->pntsw;
1878 if (is_prop_edit || (bp->f1 & SELECT)) {
1879 if (bp->hide == 0) {
1880 copy_v3_v3(td->iloc, bp->vec);
1882 copy_v3_v3(td->center, td->loc);
1883 if (bp->f1 & SELECT) {
1884 td->flag = TD_SELECTED;
1889 copy_m3_m3(td->smtx, smtx);
1890 copy_m3_m3(td->mtx, mtx);
1903 /* ******************* particle edit **************** */
1904 static void createTransParticleVerts(bContext *C, TransInfo *t)
1906 TransData *td = NULL;
1907 TransDataExtension *tx;
1908 Object *ob = CTX_data_active_object(C);
1909 ParticleEditSettings *pset = PE_settings(t->scene);
1910 PTCacheEdit *edit = PE_get_current(t->scene, ob);
1911 ParticleSystem *psys = NULL;
1912 ParticleSystemModifierData *psmd = NULL;
1913 PTCacheEditPoint *point;
1914 PTCacheEditKey *key;
1916 int i, k, transformparticle;
1917 int count = 0, hasselected = 0;
1918 const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
1920 if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) return;
1925 psmd = psys_get_modifier(ob, psys);
1927 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
1928 point->flag &= ~PEP_TRANSFORM;
1929 transformparticle = 0;
1931 if ((point->flag & PEP_HIDE) == 0) {
1932 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
1933 if ((key->flag & PEK_HIDE) == 0) {
1934 if (key->flag & PEK_SELECT) {
1936 transformparticle = 1;
1938 else if (is_prop_edit)
1939 transformparticle = 1;
1944 if (transformparticle) {
1945 count += point->totkey;
1946 point->flag |= PEP_TRANSFORM;
1950 /* note: in prop mode we need at least 1 selected */
1951 if (hasselected == 0) return;
1954 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1956 if (t->mode == TFM_BAKE_TIME)
1957 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1963 invert_m4_m4(ob->imat, ob->obmat);
1965 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
1966 TransData *head, *tail;
1969 if (!(point->flag & PEP_TRANSFORM)) continue;
1971 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR))
1972 psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
1974 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
1975 if (key->flag & PEK_USE_WCO) {
1976 copy_v3_v3(key->world_co, key->co);
1977 mul_m4_v3(mat, key->world_co);
1978 td->loc = key->world_co;
1983 copy_v3_v3(td->iloc, td->loc);
1984 copy_v3_v3(td->center, td->loc);
1986 if (key->flag & PEK_SELECT)
1987 td->flag |= TD_SELECTED;
1988 else if (!is_prop_edit)
1989 td->flag |= TD_SKIP;
1994 /* don't allow moving roots */
1995 if (k == 0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR)))
1996 td->protectflag |= OB_LOCK_LOC;
2000 if (t->mode == TFM_BAKE_TIME) {
2001 td->val = key->time;
2002 td->ival = *(key->time);
2003 /* abuse size and quat for min/max values */
2004 td->flag |= TD_NO_EXT;
2005 if (k == 0) tx->size = NULL;
2006 else tx->size = (key - 1)->time;
2008 if (k == point->totkey - 1) tx->quat = NULL;
2009 else tx->quat = (key + 1)->time;
2017 if (is_prop_edit && head != tail)
2018 calc_distanceCurveVerts(head, tail - 1);
2022 void flushTransParticles(TransInfo *t)
2024 Scene *scene = t->scene;
2026 PTCacheEdit *edit = PE_get_current(scene, ob);
2027 ParticleSystem *psys = edit->psys;
2028 ParticleSystemModifierData *psmd = NULL;
2029 PTCacheEditPoint *point;
2030 PTCacheEditKey *key;
2032 float mat[4][4], imat[4][4], co[3];
2034 const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
2037 psmd = psys_get_modifier(ob, psys);
2039 /* we do transform in world space, so flush world space position
2040 * back to particle local space (only for hair particles) */
2042 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++, td++) {
2043 if (!(point->flag & PEP_TRANSFORM)) continue;
2045 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
2046 psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
2047 invert_m4_m4(imat, mat);
2049 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
2050 copy_v3_v3(co, key->world_co);
2051 mul_m4_v3(imat, co);
2054 /* optimization for proportional edit */
2055 if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
2056 copy_v3_v3(key->co, co);
2057 point->flag |= PEP_EDIT_RECALC;
2062 point->flag |= PEP_EDIT_RECALC;
2065 PE_update_object(scene, OBACT, 1);
2068 /* ********************* mesh ****************** */
2070 static bool bmesh_test_dist_add(
2071 BMVert *v, BMVert *v_other,
2072 float *dists, const float *dists_prev,
2073 /* optionally track original index */
2074 int *index, const int *index_prev,
2077 if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) &&
2078 (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0))
2080 const int i = BM_elem_index_get(v);
2081 const int i_other = BM_elem_index_get(v_other);
2084 sub_v3_v3v3(vec, v->co, v_other->co);
2085 mul_m3_v3(mtx, vec);
2087 dist_other = dists_prev[i] + len_v3(vec);
2088 if (dist_other < dists[i_other]) {
2089 dists[i_other] = dist_other;
2090 if (index != NULL) {
2091 index[i_other] = index_prev[i];
2101 * \param mtx: Measure disatnce in this space.
2102 * \param dists: Store the closest connected distance to selected vertices.
2103 * \param index: Optionally store the original index we're measuring the distance to (can be NULL).
2105 static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists, int *index)
2107 BLI_LINKSTACK_DECLARE(queue, BMVert *);
2109 /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */
2110 BLI_LINKSTACK_DECLARE(queue_next, BMVert *);
2112 BLI_LINKSTACK_INIT(queue);
2113 BLI_LINKSTACK_INIT(queue_next);
2120 BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
2122 BM_elem_index_set(v, i); /* set_inline */
2123 BM_elem_flag_disable(v, BM_ELEM_TAG);
2125 if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
2127 if (index != NULL) {
2132 BLI_LINKSTACK_PUSH(queue, v);
2134 if (index != NULL) {
2141 bm->elem_index_dirty &= ~BM_VERT;
2144 /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
2145 float *dists_prev = MEM_dupallocN(dists);
2146 int *index_prev = MEM_dupallocN(index); /* may be NULL */
2152 /* this is correct but slow to do each iteration,
2153 * instead sync the dist's while clearing BM_ELEM_TAG (below) */
2155 memcpy(dists_prev, dists, sizeof(float) * bm->totvert);
2158 while ((v = BLI_LINKSTACK_POP(queue))) {
2159 BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX);
2161 /* connected edge-verts */
2163 BMEdge *e_iter, *e_first;
2165 e_iter = e_first = v->e;
2167 /* would normally use BM_EDGES_OF_VERT, but this runs so often,
2168 * its faster to iterate on the data directly */
2171 if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == 0) {
2175 BMVert *v_other = BM_edge_other_vert(e_iter, v);
2176 if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
2177 if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
2178 BM_elem_flag_enable(v_other, BM_ELEM_TAG);
2179 BLI_LINKSTACK_PUSH(queue_next, v_other);
2186 BMLoop *l_iter_radial, *l_first_radial;
2188 * imaginary edge diagonally across quad,
2189 * \note, this takes advantage of the rules of winding that we
2190 * know 2 or more of a verts edges wont reference the same face twice.
2191 * Also, if the edge is hidden, the face will be hidden too.
2193 l_iter_radial = l_first_radial = e_iter->l;
2196 if ((l_iter_radial->v == v) &&
2197 (l_iter_radial->f->len == 4) &&
2198 (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0))
2200 BMVert *v_other = l_iter_radial->next->next->v;
2201 if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
2202 if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
2203 BM_elem_flag_enable(v_other, BM_ELEM_TAG);
2204 BLI_LINKSTACK_PUSH(queue_next, v_other);
2208 } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial);
2211 } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
2216 /* clear for the next loop */
2217 for (lnk = queue_next; lnk; lnk = lnk->next) {
2218 BMVert *v_link = lnk->link;
2219 const int i = BM_elem_index_get(v_link);
2221 BM_elem_flag_disable(v_link, BM_ELEM_TAG);
2223 /* keep in sync, avoid having to do full memcpy each iteration */
2224 dists_prev[i] = dists[i];
2225 if (index != NULL) {
2226 index_prev[i] = index[i];
2230 BLI_LINKSTACK_SWAP(queue, queue_next);
2232 /* none should be tagged now since 'queue_next' is empty */
2233 BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0);
2235 } while (BLI_LINKSTACK_SIZE(queue));
2237 BLI_LINKSTACK_FREE(queue);
2238 BLI_LINKSTACK_FREE(queue_next);
2240 MEM_freeN(dists_prev);
2241 if (index_prev != NULL) {
2242 MEM_freeN(index_prev);
2246 static struct TransIslandData *editmesh_islands_info_calc(
2247 BMEditMesh *em, int *r_island_tot, int **r_island_vert_map,
2248 bool calc_single_islands)
2251 struct TransIslandData *trans_islands;
2258 int (*group_index)[2];
2264 if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
2265 groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__);
2266 group_tot = BM_mesh_calc_edge_groups(bm, groups_array, &group_index,
2271 itype = BM_VERTS_OF_EDGE;
2274 else { /* (bm->selectmode & SCE_SELECT_FACE) */
2275 groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
2276 group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index,
2278 BM_ELEM_SELECT, BM_VERT);
2281 itype = BM_VERTS_OF_FACE;
2285 trans_islands = MEM_mallocN(sizeof(*trans_islands) * group_tot, __func__);
2287 vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__);
2288 /* we shouldn't need this, but with incorrect selection flushing
2289 * its possible we have a selected vertex thats not in a face, for now best not crash in that case. */
2290 copy_vn_i(vert_map, bm->totvert, -1);
2292 BM_mesh_elem_table_ensure(bm, htype);
2293 ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable;
2295 BM_mesh_elem_index_ensure(bm, BM_VERT);
2297 /* may be an edge OR a face array */
2298 for (i = 0; i < group_tot; i++) {
2299 BMEditSelection ese = {NULL};
2301 const int fg_sta = group_index[i][0];
2302 const int fg_len = group_index[i][1];
2303 float co[3], no[3], tangent[3];
2312 /* loop on each face in this group:
2313 * - assign r_vert_map
2314 * - calculate (co, no)
2316 for (j = 0; j < fg_len; j++) {
2317 float tmp_co[3], tmp_no[3], tmp_tangent[3];
2319 ese.ele = ele_array[groups_array[fg_sta + j]];
2321 BM_editselection_center(&ese, tmp_co);
2322 BM_editselection_normal(&ese, tmp_no);
2323 BM_editselection_plane(&ese, tmp_tangent);
2325 add_v3_v3(co, tmp_co);
2326 add_v3_v3(no, tmp_no);
2327 add_v3_v3(tangent, tmp_tangent);
2330 /* setup vertex map */
2334 /* connected edge-verts */
2335 BM_ITER_ELEM (v, &iter, ese.ele, itype) {
2336 vert_map[BM_elem_index_get(v)] = i;
2341 mul_v3_v3fl(trans_islands[i].co, co, 1.0f / (float)fg_len);
2343 if (createSpaceNormalTangent(trans_islands[i].axismtx, no, tangent)) {
2347 if (normalize_v3(no) != 0.0f) {
2348 axis_dominant_v3_to_m3(trans_islands[i].axismtx, no);
2349 invert_m3(trans_islands[i].axismtx);
2352 unit_m3(trans_islands[i].axismtx);
2357 MEM_freeN(groups_array);
2358 MEM_freeN(group_index);
2360 /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */
2361 if (calc_single_islands) {
2364 int group_tot_single = 0;
2366 BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
2367 if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
2368 group_tot_single += 1;
2372 if (group_tot_single != 0) {
2373 trans_islands = MEM_reallocN(trans_islands, sizeof(*trans_islands) * (group_tot + group_tot_single));
2375 BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
2376 if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
2377 struct TransIslandData *v_island = &trans_islands[group_tot];
2378 vert_map[i] = group_tot;
2380 copy_v3_v3(v_island->co, v->co);
2382 if (is_zero_v3(v->no) != 0.0f) {
2383 axis_dominant_v3_to_m3(v_island->axismtx, v->no);
2384 invert_m3(v_island->axismtx);
2387 unit_m3(v_island->axismtx);
2396 *r_island_tot = group_tot;
2397 *r_island_vert_map = vert_map;
2399 return trans_islands;
2402 /* way to overwrite what data is edited with transform */
2403 static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx,
2404 BMEditMesh *em, BMVert *eve, float *bweight,
2405 struct TransIslandData *v_island)
2408 BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
2412 // td->loc = key->co;
2415 copy_v3_v3(td->iloc, td->loc);
2417 if ((t->mode == TFM_SHRINKFATTEN) &&
2418 (em->selectmode & SCE_SELECT_FACE) &&
2419 BM_elem_flag_test(eve, BM_ELEM_SELECT) &&
2420 (BM_vert_calc_normal_ex(eve, BM_ELEM_SELECT, _no)))
2429 copy_v3_v3(td->center, v_island->co);
2430 copy_m3_m3(td->axismtx, v_island->axismtx);
2432 else if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
2433 copy_v3_v3(td->center, td->loc);
2434 createSpaceNormal(td->axismtx, no);
2437 copy_v3_v3(td->center, td->loc);
2439 /* Setting normals */
2440 copy_v3_v3(td->axismtx[2], no);
2446 td->axismtx[1][2] = 0.0f;
2453 if (t->mode == TFM_BWEIGHT) {
2455 td->ival = *bweight;
2457 else if (t->mode == TFM_SKIN_RESIZE) {
2458 MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata,
2461 /* skin node size */
2463 copy_v3_v3(tx->isize, vs->radius);
2464 tx->size = vs->radius;
2465 td->val = vs->radius;
2467 else if (t->mode == TFM_SHRINKFATTEN) {
2469 tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, no, BM_ELEM_SELECT);
2473 static void createTransEditVerts(TransInfo *t)
2475 TransData *tob = NULL;
2476 TransDataExtension *tx = NULL;
2477 BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
2478 Mesh *me = t->obedit->data;
2482 float (*mappedcos)[3] = NULL, (*quats)[4] = NULL;
2483 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2484 float *dists = NULL;
2486 const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
2488 int cd_vert_bweight_offset = -1;
2489 bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
2491 struct TransIslandData *island_info = NULL;
2492 int island_info_tot;
2493 int *island_vert_map = NULL;
2495 /* Even for translation this is needed because of island-orientation, see: T51651. */
2496 const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
2497 /* Original index of our connected vertex when connected distances are calculated.
2498 * Optional, allocate if needed. */
2499 int *dists_index = NULL;
2501 if (t->flag & T_MIRROR) {
2502 EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
2507 * Quick check if we can transform.
2509 * \note ignore modes here, even in edge/face modes, transform data is created by selected vertices.
2510 * \note in prop mode we need at least 1 selected.
2512 if (bm->totvertsel == 0) {
2516 if (t->mode == TFM_BWEIGHT) {
2517 BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_VERT_BWEIGHT);
2518 cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
2522 unsigned int count = 0;
2523 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
2524 if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2531 /* allocating scratch arrays */
2532 if (prop_mode & T_PROP_CONNECTED) {
2533 dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__);
2534 if (is_island_center) {
2535 dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__);
2540 t->total = bm->totvertsel;
2543 tob = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mesh EditMode)");
2544 if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
2545 /* warning, this is overkill, we only need 2 extra floats,
2546 * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
2547 * since we may not use the 'alt' transform mode to maintain shell thickness,
2548 * but with generic transform code its hard to lazy init vars */
2549 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension),
2553 copy_m3_m4(mtx, t->obedit->obmat);
2554 /* we use a pseudoinverse so that when one of the axes is scaled to 0,
2555 * matrix inversion still works and we can still moving along the other */
2556 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
2558 if (prop_mode & T_PROP_CONNECTED) {
2559 editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
2562 if (is_island_center) {
2563 /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */
2564 const bool calc_single_islands = (
2565 (prop_mode & T_PROP_CONNECTED) &&
2566 (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
2567 (em->selectmode & SCE_SELECT_VERTEX));
2569 island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map, calc_single_islands);
2572 /* detect CrazySpace [tm] */
2573 if (modifiers_getCageIndex(t->scene, t->obedit, NULL, 1) != -1) {
2575 if (modifiers_isCorrectableDeformed(t->scene, t->obedit)) {
2576 /* check if we can use deform matrices for modifier from the
2577 * start up to stack, they are more accurate than quats */
2578 totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(t->scene, t->obedit, em, &defmats, &defcos);
2581 /* if we still have more modifiers, also do crazyspace
2582 * correction with quats, relative to the coordinates after
2583 * the modifiers that support deform matrices (defcos) */
2585 #if 0 /* TODO, fix crazyspace+extrude so it can be enabled for general use - campbell */
2586 if ((totleft > 0) || (totleft == -1))
2591 mappedcos = BKE_crazyspace_get_mapped_editverts(t->scene, t->obedit);
2592 quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
2593 BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
2595 MEM_freeN(mappedcos);
2603 /* find out which half we do */
2605 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
2606 if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve->co[0] != 0.0f) {
2607 if (eve->co[0] < 0.0f) {
2616 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
2617 if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2618 if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
2619 struct TransIslandData *v_island = NULL;
2620 float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL;
2623 const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
2624 v_island = (island_vert_map[connected_index] != -1) ?
2625 &island_info[island_vert_map[connected_index]] : NULL;
2629 VertsToTransData(t, tob, tx, em, eve, bweight, v_island);
2634 if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
2635 tob->flag |= TD_SELECTED;
2638 if (prop_mode & T_PROP_CONNECTED) {
2639 tob->dist = dists[a];
2642 tob->flag |= TD_NOTCONNECTED;
2643 tob->dist = FLT_MAX;
2648 if (defmats || (quats && BM_elem_flag_test(eve, BM_ELEM_TAG))) {
2649 float mat[3][3], qmat[3][3], imat[3][3];
2651 /* use both or either quat and defmat correction */
2652 if (quats && BM_elem_flag_test(eve, BM_ELEM_TAG)) {
2653 quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
2656 mul_m3_series(mat, defmats[a], qmat, mtx);
2658 mul_m3_m3m3(mat, mtx, qmat);
2661 mul_m3_m3m3(mat, mtx, defmats[a]);
2663 invert_m3_m3(imat, mat);
2665 copy_m3_m3(tob->smtx, imat);
2666 copy_m3_m3(tob->mtx, mat);
2669 copy_m3_m3(tob->smtx, smtx);
2670 copy_m3_m3(tob->mtx, mtx);
2674 if ((mirror > 0 && tob->iloc[0] > 0.0f) || (mirror < 0 && tob->iloc[0] < 0.0f)) {
2675 BMVert *vmir = EDBM_verts_mirror_get(em, eve); //t->obedit, em, eve, tob->iloc, a);
2676 if (vmir && vmir != eve) {
2686 MEM_freeN(island_info);
2687 MEM_freeN(island_vert_map);
2692 for (a = 0; a < t->total; a++, tob++) {
2693 if (ABS(tob->loc[0]) <= 0.00001f) {
2694 tob->flag |= TD_MIRROR_EDGE;
2700 /* crazy space free */
2708 MEM_freeN(dists_index);
2710 if (t->flag & T_MIRROR) {
2711 EDBM_verts_mirror_cache_end(em);
2715 /* *** NODE EDITOR *** */
2716 void flushTransNodes(TransInfo *t)
2718 const float dpi_fac = UI_DPI_FAC;
2723 applyGridAbsolute(t);
2725 /* flush to 2d vector from internally used 3d vector */
2726 for (a = 0, td = t->data, td2d = t->data2d; a < t->total; a++, td++, td2d++) {
2727 bNode *node = td->extra;
2730 /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
2731 #ifdef USE_NODE_CENTER
2732 locx = (td2d->loc[0] - (BLI_rctf_size_x(&node->totr)) * +0.5f) / dpi_fac;
2733 locy = (td2d->loc[1] - (BLI_rctf_size_y(&node->totr)) * -0.5f) / dpi_fac;
2735 locx = td2d->loc[0] / dpi_fac;
2736 locy = td2d->loc[1] / dpi_fac;
2739 /* account for parents (nested nodes) */
2741 nodeFromView(node->parent, locx, locy, &node->locx, &node->locy);
2749 /* handle intersection with noodles */
2750 if (t->total == 1) {
2751 ED_node_link_intersect_test(t->sa, 1);
2755 /* *** SEQUENCE EDITOR *** */
2757 /* commented _only_ because the meta may have animation data which
2758 * needs moving too [#28158] */
2760 #define SEQ_TX_NESTED_METAS
2762 BLI_INLINE void trans_update_seq(Scene *sce, Sequence *seq, int old_start, int sel_flag)
2764 if (seq->depth == 0) {
2765 /* Calculate this strip and all nested strips.
2766 * Children are ALWAYS transformed first so we don't need to do this in another loop.
2768 BKE_sequence_calc(sce, seq);
2771 BKE_sequence_calc_disp(sce, seq);
2774 if (sel_flag == SELECT)
2775 BKE_sequencer_offset_animdata(sce, seq, seq->start - old_start);
2778 void flushTransSeq(TransInfo *t)
2780 ListBase *seqbasep = BKE_sequencer_editing_get(t->scene, false)->seqbasep; /* Editing null check already done */
2782 TransData *td = NULL;
2783 TransData2D *td2d = NULL;
2784 TransDataSeq *tdsq = NULL;
2789 /* prevent updating the same seq twice
2790 * if the transdata order is changed this will mess up
2791 * but so will TransDataSeq */
2792 Sequence *seq_prev = NULL;