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
35 #include "DNA_anim_types.h"
36 #include "DNA_armature_types.h"
37 #include "DNA_lattice_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_meta_types.h"
40 #include "DNA_node_types.h"
41 #include "DNA_screen_types.h"
42 #include "DNA_space_types.h"
43 #include "DNA_sequence_types.h"
44 #include "DNA_view3d_types.h"
45 #include "DNA_constraint_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_meshdata_types.h"
48 #include "DNA_gpencil_types.h"
49 #include "DNA_movieclip_types.h"
50 #include "DNA_mask_types.h"
52 #include "MEM_guardedalloc.h"
55 #include "BLI_utildefines.h"
56 #include "BLI_smallhash.h"
57 #include "BLI_listbase.h"
58 #include "BLI_linklist_stack.h"
59 #include "BLI_string.h"
60 #include "BLI_bitmap.h"
62 #include "BKE_DerivedMesh.h"
63 #include "BKE_action.h"
64 #include "BKE_armature.h"
65 #include "BKE_constraint.h"
66 #include "BKE_context.h"
67 #include "BKE_crazyspace.h"
68 #include "BKE_curve.h"
69 #include "BKE_depsgraph.h"
70 #include "BKE_fcurve.h"
71 #include "BKE_global.h"
72 #include "BKE_gpencil.h"
76 #include "BKE_mesh_mapping.h"
77 #include "BKE_modifier.h"
78 #include "BKE_movieclip.h"
81 #include "BKE_object.h"
82 #include "BKE_particle.h"
83 #include "BKE_pointcache.h"
84 #include "BKE_report.h"
85 #include "BKE_rigidbody.h"
86 #include "BKE_scene.h"
87 #include "BKE_sequencer.h"
88 #include "BKE_editmesh.h"
89 #include "BKE_tracking.h"
91 #include "BKE_lattice.h"
95 #include "ED_anim_api.h"
96 #include "ED_armature.h"
97 #include "ED_particle.h"
99 #include "ED_keyframing.h"
100 #include "ED_keyframes_edit.h"
101 #include "ED_object.h"
102 #include "ED_markers.h"
105 #include "ED_uvedit.h"
109 #include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
110 #include "WM_types.h"
112 #include "UI_view2d.h"
113 #include "UI_interface.h"
115 #include "RNA_access.h"
117 #include "transform.h"
121 * Transforming around ourselves is no use, fallback to individual origins,
122 * useful for curve/armatures.
124 static void transform_around_single_fallback(TransInfo *t)
126 if ((t->total == 1) &&
127 (ELEM(t->around, V3D_CENTER, V3D_CENTROID, V3D_ACTIVE)) &&
128 (ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL)))
130 t->around = V3D_LOCAL;
134 /* when transforming islands */
135 struct TransIslandData {
140 /* local function prototype - for Object/Bone Constraints */
141 static bool constraints_list_needinv(TransInfo *t, ListBase *list);
143 /* ************************** Functions *************************** */
145 static int trans_data_compare_dist(const void *a, const void *b)
147 const TransData *td_a = (const TransData *)a;
148 const TransData *td_b = (const TransData *)b;
150 if (td_a->dist < td_b->dist) return -1;
151 else if (td_a->dist > td_b->dist) return 1;
155 static int trans_data_compare_rdist(const void *a, const void *b)
157 const TransData *td_a = (const TransData *)a;
158 const TransData *td_b = (const TransData *)b;
160 if (td_a->rdist < td_b->rdist) return -1;
161 else if (td_a->rdist > td_b->rdist) return 1;
165 void sort_trans_data_dist(TransInfo *t)
167 TransData *start = t->data;
170 for (i = 0; i < t->total && start->flag & TD_SELECTED; i++)
174 if (t->flag & T_PROP_CONNECTED)
175 qsort(start, t->total - i, sizeof(TransData), trans_data_compare_dist);
177 qsort(start, t->total - i, sizeof(TransData), trans_data_compare_rdist);
181 static void sort_trans_data(TransInfo *t)
183 TransData *sel, *unsel;
188 while (sel > unsel) {
189 while (unsel->flag & TD_SELECTED) {
195 while (!(sel->flag & TD_SELECTED)) {
209 /* distance calculated from not-selected vertex to nearest selected vertex
210 * warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
211 static void set_prop_dist(TransInfo *t, const bool with_dist)
217 const float *proj_vec = NULL;
219 if (t->flag & T_PROP_PROJECTED) {
220 if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
221 RegionView3D *rv3d = t->ar->regiondata;
222 normalize_v3_v3(_proj_vec, rv3d->viewinv[2]);
223 proj_vec = _proj_vec;
227 for (a = 0, tob = t->data; a < t->total; a++, tob++) {
229 tob->rdist = 0.0f; // init, it was mallocced
231 if ((tob->flag & TD_SELECTED) == 0) {
234 float dist_sq, vec[3];
236 tob->rdist = -1.0f; // signal for next loop
238 for (i = 0, td = t->data; i < t->total; i++, td++) {
239 if (td->flag & TD_SELECTED) {
240 sub_v3_v3v3(vec, tob->center, td->center);
241 mul_m3_v3(tob->mtx, vec);
245 project_v3_v3v3(vec_p, vec, proj_vec);
246 sub_v3_v3(vec, vec_p);
249 dist_sq = len_squared_v3(vec);
250 if ((tob->rdist == -1.0f) || (dist_sq < (tob->rdist * tob->rdist))) {
251 tob->rdist = sqrtf(dist_sq);
255 break; /* by definition transdata has selected items in beginning */
259 tob->dist = tob->rdist;
265 /* ************************** CONVERSIONS ************************* */
267 /* ********************* texture space ********* */
269 static void createTransTexspace(TransInfo *t)
271 Scene *scene = t->scene;
279 if (ob == NULL) { // Shouldn't logically happen, but still...
285 if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) {
286 BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform");
291 if (BKE_object_obdata_is_libdata(ob)) {
292 BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
298 td = t->data = MEM_callocN(sizeof(TransData), "TransTexspace");
299 td->ext = t->ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
301 td->flag = TD_SELECTED;
302 copy_v3_v3(td->center, ob->obmat[3]);
305 copy_m3_m4(td->mtx, ob->obmat);
306 copy_m3_m4(td->axismtx, ob->obmat);
307 normalize_m3(td->axismtx);
308 pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
310 if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
311 ob->dtx |= OB_TEXSPACE;
312 *texflag &= ~ME_AUTOSPACE;
315 copy_v3_v3(td->iloc, td->loc);
316 copy_v3_v3(td->ext->irot, td->ext->rot);
317 copy_v3_v3(td->ext->isize, td->ext->size);
320 /* ********************* edge (for crease) ***** */
322 static void createTransEdge(TransInfo *t)
324 BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
325 TransData *td = NULL;
328 float mtx[3][3], smtx[3][3];
329 int count = 0, countsel = 0;
330 int propmode = t->flag & T_PROP_EDIT;
331 int cd_edge_float_offset;
333 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
334 if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
335 if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) countsel++;
336 if (propmode) count++;
350 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransCrease");
352 copy_m3_m4(mtx, t->obedit->obmat);
353 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
355 /* create data we need */
356 if (t->mode == TFM_BWEIGHT) {
357 BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_EDGE_BWEIGHT);
358 cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
360 else { //if (t->mode == TFM_CREASE) {
361 BLI_assert(t->mode == TFM_CREASE);
362 BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_EDGE_CREASE);
363 cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
366 BLI_assert(cd_edge_float_offset != -1);
368 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
369 if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || propmode)) {
371 /* need to set center for center calculations */
372 mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
375 if (BM_elem_flag_test(eed, BM_ELEM_SELECT))
376 td->flag = TD_SELECTED;
380 copy_m3_m3(td->smtx, smtx);
381 copy_m3_m3(td->mtx, mtx);
385 fl_ptr = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_float_offset);
394 /* ********************* pose mode ************* */
396 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
398 bConstraint *con = pchan->constraints.first;
400 for (; con; con = con->next) {
401 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
402 bKinematicConstraint *data = con->data;
404 if (data->tar == NULL)
406 if (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0)
413 static short apply_targetless_ik(Object *ob)
415 bPoseChannel *pchan, *parchan, *chanlist[256];
416 bKinematicConstraint *data;
417 int segcount, apply = 0;
419 /* now we got a difficult situation... we have to find the
420 * target-less IK pchans, and apply transformation to the all
421 * pchans that were in the chain */
423 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
424 data = has_targetless_ik(pchan);
425 if (data && (data->flag & CONSTRAINT_IK_AUTO)) {
427 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
430 /* exclude tip from chain? */
431 if (!(data->flag & CONSTRAINT_IK_TIP))
432 parchan = pchan->parent;
436 /* Find the chain's root & count the segments needed */
437 for (; parchan; parchan = parchan->parent) {
438 chanlist[segcount] = parchan;
441 if (segcount == data->rootbone || segcount > 255) break; // 255 is weak
443 for (; segcount; segcount--) {
445 float rmat[4][4] /*, tmat[4][4], imat[4][4]*/;
447 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
448 /* we put in channel the entire result of rmat = (channel * constraint * IK) */
449 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
450 /* rmat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone ) */
452 parchan = chanlist[segcount - 1];
453 bone = parchan->bone;
454 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
456 BKE_armature_mat_pose_to_bone(parchan, parchan->pose_mat, rmat);
458 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
460 float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3];
462 copy_m3_m4(rmat3, rmat);
465 /* [#22409] is partially caused by this, as slight numeric error introduced during
466 * the solving process leads to locked-axis values changing. However, we cannot modify
467 * the values here, or else there are huge discrepancies between IK-solver (interactive)
470 if (parchan->rotmode > 0)
471 mat3_to_eulO(parchan->eul, parchan->rotmode, rmat3);
472 else if (parchan->rotmode == ROT_MODE_AXISANGLE)
473 mat3_to_axis_angle(parchan->rotAxis, &parchan->rotAngle, rmat3);
475 mat3_to_quat(parchan->quat, rmat3);
477 /* for size, remove rotation */
478 /* causes problems with some constraints (so apply only if needed) */
479 if (data->flag & CONSTRAINT_IK_STRETCH) {
480 if (parchan->rotmode > 0)
481 eulO_to_mat3(qrmat, parchan->eul, parchan->rotmode);
482 else if (parchan->rotmode == ROT_MODE_AXISANGLE)
483 axis_angle_to_mat3(qrmat, parchan->rotAxis, parchan->rotAngle);
485 quat_to_mat3(qrmat, parchan->quat);
487 invert_m3_m3(imat3, qrmat);
488 mul_m3_m3m3(smat, rmat3, imat3);
489 mat3_to_size(parchan->size, smat);
492 /* causes problems with some constraints (e.g. childof), so disable this */
493 /* as it is IK shouldn't affect location directly */
494 /* copy_v3_v3(parchan->loc, rmat[3]); */
500 data->flag &= ~CONSTRAINT_IK_AUTO;
507 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
509 Bone *bone = pchan->bone;
510 float pmat[3][3], omat[3][3];
511 float cmat[3][3], tmat[3][3];
514 copy_v3_v3(vec, pchan->pose_mat[3]);
515 copy_v3_v3(td->center, vec);
518 td->flag = TD_SELECTED;
519 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
520 td->flag |= TD_NOCENTER;
523 if (bone->flag & BONE_TRANSFORM_CHILD) {
524 td->flag |= TD_NOCENTER;
525 td->flag |= TD_NO_LOC;
528 td->protectflag = pchan->protectflag;
530 td->loc = pchan->loc;
531 copy_v3_v3(td->iloc, pchan->loc);
533 td->ext->size = pchan->size;
534 copy_v3_v3(td->ext->isize, pchan->size);
536 if (pchan->rotmode > 0) {
537 td->ext->rot = pchan->eul;
538 td->ext->rotAxis = NULL;
539 td->ext->rotAngle = NULL;
540 td->ext->quat = NULL;
542 copy_v3_v3(td->ext->irot, pchan->eul);
544 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
546 td->ext->rotAxis = pchan->rotAxis;
547 td->ext->rotAngle = &pchan->rotAngle;
548 td->ext->quat = NULL;
550 td->ext->irotAngle = pchan->rotAngle;
551 copy_v3_v3(td->ext->irotAxis, pchan->rotAxis);
555 td->ext->rotAxis = NULL;
556 td->ext->rotAngle = NULL;
557 td->ext->quat = pchan->quat;
559 copy_qt_qt(td->ext->iquat, pchan->quat);
561 td->ext->rotOrder = pchan->rotmode;
564 /* proper way to get parent transform + own transform + constraints transform */
565 copy_m3_m4(omat, ob->obmat);
567 /* New code, using "generic" BKE_pchan_to_pose_mat(). */
569 float rotscale_mat[4][4], loc_mat[4][4];
572 BKE_pchan_to_pose_mat(pchan, rotscale_mat, loc_mat);
573 if (t->mode == TFM_TRANSLATION)
574 copy_m3_m4(pmat, loc_mat);
576 copy_m3_m4(pmat, rotscale_mat);
578 /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal,
579 * and want align snapping, we just need both loc_mat and rotscale_mat.
580 * So simply always store rotscale mat in td->ext, and always use it to apply rotations...
581 * Ugly to need such hacks! :/ */
582 copy_m3_m4(rpmat, rotscale_mat);
584 if (constraints_list_needinv(t, &pchan->constraints)) {
585 copy_m3_m4(tmat, pchan->constinv);
586 invert_m3_m3(cmat, tmat);
587 mul_m3_series(td->mtx, cmat, omat, pmat);
588 mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat);
591 mul_m3_series(td->mtx, omat, pmat);
592 mul_m3_series(td->ext->r_mtx, omat, rpmat);
594 invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx);
597 pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
599 /* exceptional case: rotate the pose bone which also applies transformation
600 * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */
601 if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) {
603 /* same as td->smtx but without pchan->bone->bone_mat */
604 td->flag |= TD_PBONE_LOCAL_MTX_C;
605 mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx);
608 td->flag |= TD_PBONE_LOCAL_MTX_P;
612 /* for axismat we use bone's own transform */
613 copy_m3_m4(pmat, pchan->pose_mat);
614 mul_m3_m3m3(td->axismtx, omat, pmat);
615 normalize_m3(td->axismtx);
617 if (t->mode == TFM_BONESIZE) {
618 bArmature *arm = t->poseobj->data;
620 if (arm->drawtype == ARM_ENVELOPE) {
622 td->val = &bone->dist;
623 td->ival = bone->dist;
626 // abusive storage of scale in the loc pointer :)
627 td->loc = &bone->xwidth;
628 copy_v3_v3(td->iloc, td->loc);
633 /* in this case we can do target-less IK grabbing */
634 if (t->mode == TFM_TRANSLATION) {
635 bKinematicConstraint *data = has_targetless_ik(pchan);
637 if (data->flag & CONSTRAINT_IK_TIP) {
638 copy_v3_v3(data->grabtarget, pchan->pose_tail);
641 copy_v3_v3(data->grabtarget, pchan->pose_head);
643 td->loc = data->grabtarget;
644 copy_v3_v3(td->iloc, td->loc);
645 data->flag |= CONSTRAINT_IK_AUTO;
647 /* only object matrix correction */
648 copy_m3_m3(td->mtx, omat);
649 pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
653 /* store reference to first constraint */
654 td->con = pchan->constraints.first;
657 static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
659 Bone *bone = lb->first;
661 for (; bone; bone = bone->next) {
662 if ((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED)) {
663 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
665 else if ((bone->flag & BONE_TRANSFORM) &&
666 (mode == TFM_ROTATION || mode == TFM_TRACKBALL) &&
667 (around == V3D_LOCAL))
669 bone->flag |= BONE_TRANSFORM_CHILD;
672 bone->flag &= ~BONE_TRANSFORM;
675 bone_children_clear_transflag(mode, around, &bone->childbase);
679 /* sets transform flags in the bones
680 * returns total number of bones with BONE_TRANSFORM */
681 int count_set_pose_transflags(int *out_mode, short around, Object *ob)
683 bArmature *arm = ob->data;
686 int mode = *out_mode;
687 int hastranslation = 0;
690 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
692 if (PBONE_VISIBLE(arm, bone)) {
693 if ((bone->flag & BONE_SELECTED))
694 bone->flag |= BONE_TRANSFORM;
696 bone->flag &= ~BONE_TRANSFORM;
698 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
699 bone->flag &= ~BONE_TRANSFORM_CHILD;
702 bone->flag &= ~BONE_TRANSFORM;
705 /* make sure no bone can be transformed when a parent is transformed */
706 /* since pchans are depsgraph sorted, the parents are in beginning of list */
707 if (mode != TFM_BONESIZE) {
708 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
710 if (bone->flag & BONE_TRANSFORM)
711 bone_children_clear_transflag(mode, around, &bone->childbase);
714 /* now count, and check if we have autoIK or have to switch from translate to rotate */
717 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
719 if (bone->flag & BONE_TRANSFORM) {
722 if (mode == TFM_TRANSLATION) {
723 if (has_targetless_ik(pchan) == NULL) {
724 if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
725 if (pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
728 else if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC)
737 /* if there are no translatable bones, do rotation */
738 if (mode == TFM_TRANSLATION && !hastranslation) {
739 *out_mode = TFM_ROTATION;
746 /* -------- Auto-IK ---------- */
748 /* adjust pose-channel's auto-ik chainlen */
749 static void pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
753 /* don't bother to search if no valid constraints */
754 if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0)
757 /* check if pchan has ik-constraint */
758 for (con = pchan->constraints.first; con; con = con->next) {
759 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
760 bKinematicConstraint *data = con->data;
762 /* only accept if a temporary one (for auto-ik) */
763 if (data->flag & CONSTRAINT_IK_TEMP) {
764 /* chainlen is new chainlen, but is limited by maximum chainlen */
765 if ((chainlen == 0) || (chainlen > data->max_rootbone))
766 data->rootbone = data->max_rootbone;
768 data->rootbone = chainlen;
774 /* change the chain-length of auto-ik */
775 void transform_autoik_update(TransInfo *t, short mode)
777 short *chainlen = &t->settings->autoik_chainlen;
780 /* mode determines what change to apply to chainlen */
782 /* mode=1 is from WHEELMOUSEDOWN... increases len */
785 else if (mode == -1) {
786 /* mode==-1 is from WHEELMOUSEUP... decreases len */
787 if (*chainlen > 0) (*chainlen)--;
790 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
791 if (ELEM(NULL, t->poseobj, t->poseobj->pose))
794 /* apply to all pose-channels */
795 for (pchan = t->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
796 pchan_autoik_adjust(pchan, *chainlen);
800 /* frees temporal IKs */
801 static void pose_grab_with_ik_clear(Object *ob)
803 bKinematicConstraint *data;
805 bConstraint *con, *next;
807 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
808 /* clear all temporary lock flags */
809 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP | BONE_IK_NO_YDOF_TEMP | BONE_IK_NO_ZDOF_TEMP);
811 pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
813 /* remove all temporary IK-constraints added */
814 for (con = pchan->constraints.first; con; con = next) {
816 if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
818 if (data->flag & CONSTRAINT_IK_TEMP) {
819 /* iTaSC needs clear for removed constraints */
820 BIK_clear_data(ob->pose);
822 BLI_remlink(&pchan->constraints, con);
823 MEM_freeN(con->data);
827 pchan->constflag |= PCHAN_HAS_IK;
828 if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0))
829 pchan->constflag |= PCHAN_HAS_TARGET;
835 /* adds the IK to pchan - returns if added */
836 static short pose_grab_with_ik_add(bPoseChannel *pchan)
838 bKinematicConstraint *targetless = NULL;
839 bKinematicConstraint *data;
846 /* Rule: not if there's already an IK on this channel */
847 for (con = pchan->constraints.first; con; con = con->next) {
848 if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
851 if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == '\0')) {
852 /* make reference to constraint to base things off later (if it's the last targetless constraint encountered) */
853 targetless = (bKinematicConstraint *)con->data;
855 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
856 if (con->enforce != 0.0f) {
857 data->flag |= CONSTRAINT_IK_AUTO;
859 /* if no chain length has been specified, just make things obey standard rotation locks too */
860 if (data->rootbone == 0) {
861 for (; pchan; pchan = pchan->parent) {
862 /* here, we set ik-settings for bone from pchan->protectflag */
863 // XXX: careful with quats/axis-angle rotations where we're locking 4d components
864 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
865 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
866 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
874 if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f))
879 con = BKE_constraint_add_for_pose(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
880 pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
883 /* if exists, use values from last targetless (but disabled) IK-constraint as base */
887 data->flag = CONSTRAINT_IK_TIP;
888 data->flag |= CONSTRAINT_IK_TEMP | CONSTRAINT_IK_AUTO | CONSTRAINT_IK_POS;
889 copy_v3_v3(data->grabtarget, pchan->pose_tail);
890 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] */
892 /* we only include bones that are part of a continual connected chain */
894 /* here, we set ik-settings for bone from pchan->protectflag */
895 // XXX: careful with quats/axis-angle rotations where we're locking 4d components
896 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
897 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
898 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
900 /* now we count this pchan as being included */
903 /* continue to parent, but only if we're connected to it */
904 if (pchan->bone->flag & BONE_CONNECTED)
905 pchan = pchan->parent;
910 /* make a copy of maximum chain-length */
911 data->max_rootbone = data->rootbone;
916 /* bone is a candidate to get IK, but we don't do it if it has children connected */
917 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
920 short wentdeeper = 0, added = 0;
922 /* go deeper if children & children are connected */
923 for (bonec = bone->childbase.first; bonec; bonec = bonec->next) {
924 if (bonec->flag & BONE_CONNECTED) {
926 added += pose_grab_with_ik_children(pose, bonec);
929 if (wentdeeper == 0) {
930 bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
932 added += pose_grab_with_ik_add(pchan);
938 /* main call which adds temporal IK chains */
939 static short pose_grab_with_ik(Object *ob)
942 bPoseChannel *pchan, *parent;
946 if ((ob == NULL) || (ob->pose == NULL) || (ob->mode & OB_MODE_POSE) == 0)
951 /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
952 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
953 if (pchan->bone->layer & arm->layer) {
954 if (pchan->bone->flag & BONE_SELECTED) {
955 /* Rule: no IK for solitatry (unconnected) bones */
956 for (bonec = pchan->bone->childbase.first; bonec; bonec = bonec->next) {
957 if (bonec->flag & BONE_CONNECTED) {
961 if ((pchan->bone->flag & BONE_CONNECTED) == 0 && (bonec == NULL))
964 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
966 /* only adds if there's no IK yet (and no parent bone was selected) */
967 for (parent = pchan->parent; parent; parent = parent->parent) {
968 if (parent->bone->flag & BONE_SELECTED)
972 tot_ik += pose_grab_with_ik_add(pchan);
975 /* rule: go over the children and add IK to the tips */
976 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
982 /* iTaSC needs clear for new IK constraints */
984 BIK_clear_data(ob->pose);
986 return (tot_ik) ? 1 : 0;
990 /* only called with pose mode active object now */
991 static void createTransPose(TransInfo *t, Object *ob)
996 TransDataExtension *tdx;
1002 /* check validity of state */
1003 arm = BKE_armature_from_object(ob);
1004 if ((arm == NULL) || (ob->pose == NULL)) return;
1006 if (arm->flag & ARM_RESTPOS) {
1007 if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) {
1008 BKE_report(t->reports, RPT_ERROR, "Cannot change Pose when 'Rest Position' is enabled");
1013 /* do we need to add temporal IK chains? */
1014 if ((arm->flag & ARM_AUTO_IK) && t->mode == TFM_TRANSLATION) {
1015 ik_on = pose_grab_with_ik(ob);
1016 if (ik_on) t->flag |= T_AUTOIK;
1019 /* set flags and count total (warning, can change transform to rotate) */
1020 t->total = count_set_pose_transflags(&t->mode, t->around, ob);
1022 if (t->total == 0) return;
1025 t->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */
1027 /* disable PET, its not usable in pose mode yet [#32444] */
1028 t->flag &= ~T_PROP_EDIT_ALL;
1030 /* init trans data */
1031 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransPoseBone");
1032 tdx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "TransPoseBoneExt");
1033 for (i = 0; i < t->total; i++, td++, tdx++) {
1038 /* use pose channels to fill trans data */
1040 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1041 if (pchan->bone->flag & BONE_TRANSFORM) {
1042 add_pose_transdata(t, pchan, ob, td);
1047 if (td != (t->data + t->total)) {
1048 BKE_report(t->reports, RPT_DEBUG, "Bone selection count error");
1051 /* initialize initial auto=ik chainlen's? */
1052 if (ik_on) transform_autoik_update(t, 0);
1055 void restoreBones(TransInfo *t)
1057 BoneInitData *bid = t->customData;
1062 ebo->dist = bid->dist;
1063 ebo->rad_tail = bid->rad_tail;
1064 ebo->roll = bid->roll;
1065 ebo->xwidth = bid->xwidth;
1066 ebo->zwidth = bid->zwidth;
1067 copy_v3_v3(ebo->head, bid->head);
1068 copy_v3_v3(ebo->tail, bid->tail);
1075 /* ********************* armature ************** */
1076 static void createTransArmatureVerts(TransInfo *t)
1078 EditBone *ebo, *eboflip;
1079 bArmature *arm = t->obedit->data;
1080 ListBase *edbo = arm->edbo;
1081 TransData *td, *td_old;
1082 float mtx[3][3], smtx[3][3], bonemat[3][3];
1083 bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
1084 int total_mirrored = 0, i;
1089 for (ebo = edbo->first; ebo; ebo = ebo->next) {
1092 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
1093 if (t->mode == TFM_BONESIZE) {
1094 if (ebo->flag & BONE_SELECTED)
1097 else if (t->mode == TFM_BONE_ROLL) {
1098 if (ebo->flag & BONE_SELECTED)
1102 if (ebo->flag & BONE_TIPSEL)
1104 if (ebo->flag & BONE_ROOTSEL)
1109 if (mirror && (oldtot < t->total)) {
1110 eboflip = ED_armature_bone_get_mirrored(arm->edbo, ebo);
1116 if (!t->total) return;
1118 transform_around_single_fallback(t);
1120 copy_m3_m4(mtx, t->obedit->obmat);
1121 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
1123 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransEditBone");
1126 t->customData = bid = MEM_mallocN((total_mirrored + 1) * sizeof(BoneInitData), "BoneInitData");
1127 t->flag |= T_FREE_CUSTOMDATA;
1132 for (ebo = edbo->first; ebo; ebo = ebo->next) {
1134 ebo->oldlength = ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
1136 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
1137 if (t->mode == TFM_BONE_ENVELOPE) {
1138 if (ebo->flag & BONE_ROOTSEL) {
1139 td->val = &ebo->rad_head;
1140 td->ival = *td->val;
1142 copy_v3_v3(td->center, ebo->head);
1143 td->flag = TD_SELECTED;
1145 copy_m3_m3(td->smtx, smtx);
1146 copy_m3_m3(td->mtx, mtx);
1154 if (ebo->flag & BONE_TIPSEL) {
1155 td->val = &ebo->rad_tail;
1156 td->ival = *td->val;
1157 copy_v3_v3(td->center, ebo->tail);
1158 td->flag = TD_SELECTED;
1160 copy_m3_m3(td->smtx, smtx);
1161 copy_m3_m3(td->mtx, mtx);
1171 else if (t->mode == TFM_BONESIZE) {
1172 if (ebo->flag & BONE_SELECTED) {
1173 if (arm->drawtype == ARM_ENVELOPE) {
1175 td->val = &ebo->dist;
1176 td->ival = ebo->dist;
1179 // abusive storage of scale in the loc pointer :)
1180 td->loc = &ebo->xwidth;
1181 copy_v3_v3(td->iloc, td->loc);
1184 copy_v3_v3(td->center, ebo->head);
1185 td->flag = TD_SELECTED;
1187 /* use local bone matrix */
1188 ED_armature_ebone_to_mat3(ebo, bonemat);
1189 mul_m3_m3m3(td->mtx, mtx, bonemat);
1190 invert_m3_m3(td->smtx, td->mtx);
1192 copy_m3_m3(td->axismtx, td->mtx);
1193 normalize_m3(td->axismtx);
1201 else if (t->mode == TFM_BONE_ROLL) {
1202 if (ebo->flag & BONE_SELECTED) {
1204 td->val = &(ebo->roll);
1205 td->ival = ebo->roll;
1207 copy_v3_v3(td->center, ebo->head);
1208 td->flag = TD_SELECTED;
1217 if (ebo->flag & BONE_TIPSEL) {
1218 copy_v3_v3(td->iloc, ebo->tail);
1219 copy_v3_v3(td->center, (t->around == V3D_LOCAL) ? ebo->head : td->iloc);
1220 td->loc = ebo->tail;
1221 td->flag = TD_SELECTED;
1222 if (ebo->flag & BONE_EDITMODE_LOCKED)
1223 td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
1225 copy_m3_m3(td->smtx, smtx);
1226 copy_m3_m3(td->mtx, mtx);
1228 ED_armature_ebone_to_mat3(ebo, td->axismtx);
1230 if ((ebo->flag & BONE_ROOTSEL) == 0) {
1232 td->ival = ebo->roll;
1241 if (ebo->flag & BONE_ROOTSEL) {
1242 copy_v3_v3(td->iloc, ebo->head);
1243 copy_v3_v3(td->center, td->iloc);
1244 td->loc = ebo->head;
1245 td->flag = TD_SELECTED;
1246 if (ebo->flag & BONE_EDITMODE_LOCKED)
1247 td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
1249 copy_m3_m3(td->smtx, smtx);
1250 copy_m3_m3(td->mtx, mtx);
1252 ED_armature_ebone_to_mat3(ebo, td->axismtx);
1254 td->extra = ebo; /* to fix roll */
1255 td->ival = ebo->roll;
1266 if (mirror && (td_old != td)) {
1267 eboflip = ED_armature_bone_get_mirrored(arm->edbo, ebo);
1269 bid[i].bone = eboflip;
1270 bid[i].dist = eboflip->dist;
1271 bid[i].rad_tail = eboflip->rad_tail;
1272 bid[i].roll = eboflip->roll;
1273 bid[i].xwidth = eboflip->xwidth;
1274 bid[i].zwidth = eboflip->zwidth;
1275 copy_v3_v3(bid[i].head, eboflip->head);
1276 copy_v3_v3(bid[i].tail, eboflip->tail);
1283 /* trick to terminate iteration */
1284 bid[total_mirrored].bone = NULL;
1288 /* ********************* meta elements ********* */
1290 static void createTransMBallVerts(TransInfo *t)
1292 MetaBall *mb = (MetaBall *)t->obedit->data;
1295 TransDataExtension *tx;
1296 float mtx[3][3], smtx[3][3];
1297 int count = 0, countsel = 0;
1298 int propmode = t->flag & T_PROP_EDIT;
1301 for (ml = mb->editelems->first; ml; ml = ml->next) {
1302 if (ml->flag & SELECT) countsel++;
1303 if (propmode) count++;
1306 /* note: in prop mode we need at least 1 selected */
1307 if (countsel == 0) return;
1309 if (propmode) t->total = count;
1310 else t->total = countsel;
1312 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(MBall EditMode)");
1313 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "MetaElement_TransExtension");
1315 copy_m3_m4(mtx, t->obedit->obmat);
1316 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
1318 for (ml = mb->editelems->first; ml; ml = ml->next) {
1319 if (propmode || (ml->flag & SELECT)) {
1321 copy_v3_v3(td->iloc, td->loc);
1322 copy_v3_v3(td->center, td->loc);
1324 quat_to_mat3(td->axismtx, ml->quat);
1326 if (ml->flag & SELECT) td->flag = TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1327 else td->flag = TD_USEQUAT;
1329 copy_m3_m3(td->smtx, smtx);
1330 copy_m3_m3(td->mtx, mtx);
1334 /* Radius of MetaElem (mass of MetaElem influence) */
1335 if (ml->flag & MB_SCALE_RAD) {
1344 /* expx/expy/expz determine "shape" of some MetaElem types */
1345 tx->size = &ml->expx;
1346 tx->isize[0] = ml->expx;
1347 tx->isize[1] = ml->expy;
1348 tx->isize[2] = ml->expz;
1350 /* quat is used for rotation of MetaElem */
1351 tx->quat = ml->quat;
1352 copy_qt_qt(tx->iquat, ml->quat);
1362 /* ********************* curve/surface ********* */
1364 static void calc_distanceCurveVerts(TransData *head, TransData *tail)
1366 TransData *td, *td_near = NULL;
1367 for (td = head; td <= tail; td++) {
1368 if (td->flag & TD_SELECTED) {
1374 dist = len_v3v3(td_near->center, td->center);
1375 if (dist < (td - 1)->dist) {
1376 td->dist = (td - 1)->dist;
1384 td->flag |= TD_NOTCONNECTED;
1388 for (td = tail; td >= head; td--) {
1389 if (td->flag & TD_SELECTED) {
1395 dist = len_v3v3(td_near->center, td->center);
1396 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td + 1)->dist < td->dist) {
1397 td->flag &= ~TD_NOTCONNECTED;
1398 if (dist < (td + 1)->dist) {
1399 td->dist = (td + 1)->dist;
1409 /* Utility function for getting the handle data from bezier's */
1410 static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt)
1412 TransDataCurveHandleFlags *hdata;
1413 td->flag |= TD_BEZTRIPLE;
1414 hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1415 hdata->ih1 = bezt->h1;
1416 hdata->h1 = &bezt->h1;
1417 hdata->ih2 = bezt->h2; /* in case the second is not selected */
1418 hdata->h2 = &bezt->h2;
1422 static void createTransCurveVerts(TransInfo *t)
1424 Curve *cu = t->obedit->data;
1425 TransData *td = NULL;
1429 float mtx[3][3], smtx[3][3];
1431 int count = 0, countsel = 0;
1432 int propmode = t->flag & T_PROP_EDIT;
1433 short hide_handles = (cu->drawflag & CU_HIDE_HANDLES);
1437 if (cu->editnurb == NULL) return;
1439 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1440 nurbs = BKE_curve_editNurbs_get(cu);
1441 for (nu = nurbs->first; nu; nu = nu->next) {
1442 if (nu->type == CU_BEZIER) {
1443 for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
1444 if (bezt->hide == 0) {
1446 if (bezt->f2 & SELECT) countsel += 3;
1447 if (propmode) count += 3;
1450 if (bezt->f1 & SELECT) countsel++;
1451 if (bezt->f2 & SELECT) countsel++;
1452 if (bezt->f3 & SELECT) countsel++;
1453 if (propmode) count += 3;
1459 for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
1460 if (bp->hide == 0) {
1461 if (propmode) count++;
1462 if (bp->f1 & SELECT) countsel++;
1467 /* note: in prop mode we need at least 1 selected */
1468 if (countsel == 0) return;
1470 if (propmode) t->total = count;
1471 else t->total = countsel;
1472 t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)");
1474 transform_around_single_fallback(t);
1476 copy_m3_m4(mtx, t->obedit->obmat);
1477 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
1480 for (nu = nurbs->first; nu; nu = nu->next) {
1481 if (nu->type == CU_BEZIER) {
1482 TransData *head, *tail;
1484 for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
1485 if (bezt->hide == 0) {
1486 TransDataCurveHandleFlags *hdata = NULL;
1487 float axismtx[3][3];
1489 if (t->around == V3D_LOCAL) {
1490 float normal[3], plane[3];
1492 BKE_nurb_bezt_calc_normal(nu, bezt, normal);
1493 BKE_nurb_bezt_calc_plane(nu, bezt, plane);
1495 if (createSpaceNormalTangent(axismtx, normal, plane)) {
1499 normalize_v3(normal);
1500 axis_dominant_v3_to_m3(axismtx, normal);
1506 ((bezt->f2 & SELECT) && hide_handles) ||
1507 ((bezt->f1 & SELECT) && hide_handles == 0))
1509 copy_v3_v3(td->iloc, bezt->vec[0]);
1510 td->loc = bezt->vec[0];
1511 copy_v3_v3(td->center, bezt->vec[(hide_handles ||
1512 (t->around == V3D_LOCAL) ||
1513 (bezt->f2 & SELECT)) ? 1 : 0]);
1515 if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
1519 if (bezt->f1 & SELECT) td->flag = TD_SELECTED;
1525 hdata = initTransDataCurveHandles(td, bezt);
1527 copy_m3_m3(td->smtx, smtx);
1528 copy_m3_m3(td->mtx, mtx);
1529 if (t->around == V3D_LOCAL) {
1530 copy_m3_m3(td->axismtx, axismtx);
1538 /* This is the Curve Point, the other two are handles */
1539 if (propmode || (bezt->f2 & SELECT)) {
1540 copy_v3_v3(td->iloc, bezt->vec[1]);
1541 td->loc = bezt->vec[1];
1542 copy_v3_v3(td->center, td->loc);
1543 if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
1547 if (t->mode == TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1548 td->val = &(bezt->radius);
1549 td->ival = bezt->radius;
1551 else if (t->mode == TFM_TILT) {
1552 td->val = &(bezt->alfa);
1553 td->ival = bezt->alfa;
1559 copy_m3_m3(td->smtx, smtx);
1560 copy_m3_m3(td->mtx, mtx);
1561 if (t->around == V3D_LOCAL) {
1562 copy_m3_m3(td->axismtx, axismtx);
1565 if ((bezt->f1 & SELECT) == 0 && (bezt->f3 & SELECT) == 0)
1566 /* If the middle is selected but the sides arnt, this is needed */
1567 if (hdata == NULL) { /* if the handle was not saved by the previous handle */
1568 hdata = initTransDataCurveHandles(td, bezt);
1576 ((bezt->f2 & SELECT) && hide_handles) ||
1577 ((bezt->f3 & SELECT) && hide_handles == 0))
1579 copy_v3_v3(td->iloc, bezt->vec[2]);
1580 td->loc = bezt->vec[2];
1581 copy_v3_v3(td->center, bezt->vec[(hide_handles ||
1582 (t->around == V3D_LOCAL) ||
1583 (bezt->f2 & SELECT)) ? 1 : 2]);
1585 if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
1589 if (bezt->f3 & SELECT) td->flag = TD_SELECTED;
1595 if (hdata == NULL) { /* if the handle was not saved by the previous handle */
1596 hdata = initTransDataCurveHandles(td, bezt);
1599 copy_m3_m3(td->smtx, smtx);
1600 copy_m3_m3(td->mtx, mtx);
1601 if (t->around == V3D_LOCAL) {
1602 copy_m3_m3(td->axismtx, axismtx);
1610 (void)hdata; /* quiet warning */
1612 else if (propmode && head != tail) {
1613 calc_distanceCurveVerts(head, tail - 1);
1617 if (propmode && head != tail)
1618 calc_distanceCurveVerts(head, tail - 1);
1620 /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles
1621 * but for now just don't change handle types */
1622 if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0) {
1623 /* sets the handles based on their selection, do this after the data is copied to the TransData */
1624 BKE_nurb_handles_test(nu, !hide_handles);
1628 TransData *head, *tail;
1630 for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
1631 if (bp->hide == 0) {
1632 if (propmode || (bp->f1 & SELECT)) {
1633 copy_v3_v3(td->iloc, bp->vec);
1635 copy_v3_v3(td->center, td->loc);
1636 if (bp->f1 & SELECT) td->flag = TD_SELECTED;
1640 if (t->mode == TFM_CURVE_SHRINKFATTEN || t->mode == TFM_RESIZE) {
1641 td->val = &(bp->radius);
1642 td->ival = bp->radius;
1645 td->val = &(bp->alfa);
1646 td->ival = bp->alfa;
1649 copy_m3_m3(td->smtx, smtx);
1650 copy_m3_m3(td->mtx, mtx);
1657 else if (propmode && head != tail) {
1658 calc_distanceCurveVerts(head, tail - 1);
1662 if (propmode && head != tail)
1663 calc_distanceCurveVerts(head, tail - 1);
1668 /* ********************* lattice *************** */
1670 static void createTransLatticeVerts(TransInfo *t)
1672 Lattice *latt = ((Lattice *)t->obedit->data)->editlatt->latt;
1673 TransData *td = NULL;
1675 float mtx[3][3], smtx[3][3];
1677 int count = 0, countsel = 0;
1678 int propmode = t->flag & T_PROP_EDIT;
1681 a = latt->pntsu * latt->pntsv * latt->pntsw;
1683 if (bp->hide == 0) {
1684 if (bp->f1 & SELECT) countsel++;
1685 if (propmode) count++;
1690 /* note: in prop mode we need at least 1 selected */
1691 if (countsel == 0) return;
1693 if (propmode) t->total = count;
1694 else t->total = countsel;
1695 t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Lattice EditMode)");
1697 copy_m3_m4(mtx, t->obedit->obmat);
1698 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
1702 a = latt->pntsu * latt->pntsv * latt->pntsw;
1704 if (propmode || (bp->f1 & SELECT)) {
1705 if (bp->hide == 0) {
1706 copy_v3_v3(td->iloc, bp->vec);
1708 copy_v3_v3(td->center, td->loc);
1709 if (bp->f1 & SELECT) {
1710 td->flag = TD_SELECTED;
1713 copy_m3_m3(td->smtx, smtx);
1714 copy_m3_m3(td->mtx, mtx);
1727 /* ******************* particle edit **************** */
1728 static void createTransParticleVerts(bContext *C, TransInfo *t)
1730 TransData *td = NULL;
1731 TransDataExtension *tx;
1732 Base *base = CTX_data_active_base(C);
1733 Object *ob = CTX_data_active_object(C);
1734 ParticleEditSettings *pset = PE_settings(t->scene);
1735 PTCacheEdit *edit = PE_get_current(t->scene, ob);
1736 ParticleSystem *psys = NULL;
1737 ParticleSystemModifierData *psmd = NULL;
1738 PTCacheEditPoint *point;
1739 PTCacheEditKey *key;
1741 int i, k, transformparticle;
1742 int count = 0, hasselected = 0;
1743 int propmode = t->flag & T_PROP_EDIT;
1745 if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) return;
1750 psmd = psys_get_modifier(ob, psys);
1752 base->flag |= BA_HAS_RECALC_DATA;
1754 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
1755 point->flag &= ~PEP_TRANSFORM;
1756 transformparticle = 0;
1758 if ((point->flag & PEP_HIDE) == 0) {
1759 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
1760 if ((key->flag & PEK_HIDE) == 0) {
1761 if (key->flag & PEK_SELECT) {
1763 transformparticle = 1;
1766 transformparticle = 1;
1771 if (transformparticle) {
1772 count += point->totkey;
1773 point->flag |= PEP_TRANSFORM;
1777 /* note: in prop mode we need at least 1 selected */
1778 if (hasselected == 0) return;
1781 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1783 if (t->mode == TFM_BAKE_TIME)
1784 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1790 invert_m4_m4(ob->imat, ob->obmat);
1792 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
1793 TransData *head, *tail;
1796 if (!(point->flag & PEP_TRANSFORM)) continue;
1798 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR))
1799 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
1801 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
1802 if (key->flag & PEK_USE_WCO) {
1803 copy_v3_v3(key->world_co, key->co);
1804 mul_m4_v3(mat, key->world_co);
1805 td->loc = key->world_co;
1810 copy_v3_v3(td->iloc, td->loc);
1811 copy_v3_v3(td->center, td->loc);
1813 if (key->flag & PEK_SELECT)
1814 td->flag |= TD_SELECTED;
1816 td->flag |= TD_SKIP;
1821 /* don't allow moving roots */
1822 if (k == 0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR)))
1823 td->protectflag |= OB_LOCK_LOC;
1827 if (t->mode == TFM_BAKE_TIME) {
1828 td->val = key->time;
1829 td->ival = *(key->time);
1830 /* abuse size and quat for min/max values */
1831 td->flag |= TD_NO_EXT;
1832 if (k == 0) tx->size = NULL;
1833 else tx->size = (key - 1)->time;
1835 if (k == point->totkey - 1) tx->quat = NULL;
1836 else tx->quat = (key + 1)->time;
1844 if (propmode && head != tail)
1845 calc_distanceCurveVerts(head, tail - 1);
1849 void flushTransParticles(TransInfo *t)
1851 Scene *scene = t->scene;
1853 PTCacheEdit *edit = PE_get_current(scene, ob);
1854 ParticleSystem *psys = edit->psys;
1855 ParticleSystemModifierData *psmd = NULL;
1856 PTCacheEditPoint *point;
1857 PTCacheEditKey *key;
1859 float mat[4][4], imat[4][4], co[3];
1860 int i, k, propmode = t->flag & T_PROP_EDIT;
1863 psmd = psys_get_modifier(ob, psys);
1865 /* we do transform in world space, so flush world space position
1866 * back to particle local space (only for hair particles) */
1868 for (i = 0, point = edit->points; i < edit->totpoint; i++, point++, td++) {
1869 if (!(point->flag & PEP_TRANSFORM)) continue;
1871 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
1872 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
1873 invert_m4_m4(imat, mat);
1875 for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
1876 copy_v3_v3(co, key->world_co);
1877 mul_m4_v3(imat, co);
1880 /* optimization for proportional edit */
1881 if (!propmode || !compare_v3v3(key->co, co, 0.0001f)) {
1882 copy_v3_v3(key->co, co);
1883 point->flag |= PEP_EDIT_RECALC;
1888 point->flag |= PEP_EDIT_RECALC;
1891 PE_update_object(scene, OBACT, 1);
1894 /* ********************* mesh ****************** */
1896 static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other,
1897 float *dists, const float *dists_prev,
1900 if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) &&
1901 (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0))
1903 const int i = BM_elem_index_get(v);
1904 const int i_other = BM_elem_index_get(v_other);
1907 sub_v3_v3v3(vec, v->co, v_other->co);
1908 mul_m3_v3(mtx, vec);
1910 dist_other = dists_prev[i] + len_v3(vec);
1911 if (dist_other < dists[i_other]) {
1912 dists[i_other] = dist_other;
1920 static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists)
1922 /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
1923 float *dists_prev = MEM_mallocN(bm->totvert * sizeof(float), __func__);
1925 BLI_LINKSTACK_DECLARE(queue, BMVert *);
1927 /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */
1928 BLI_LINKSTACK_DECLARE(queue_next, BMVert *);
1930 BLI_LINKSTACK_INIT(queue);
1931 BLI_LINKSTACK_INIT(queue_next);
1938 BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
1939 BM_elem_index_set(v, i); /* set_inline */
1940 BM_elem_flag_disable(v, BM_ELEM_TAG);
1942 if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
1946 BLI_LINKSTACK_PUSH(queue, v);
1951 bm->elem_index_dirty &= ~BM_VERT;
1958 memcpy(dists_prev, dists, sizeof(float) * bm->totvert);
1960 while ((v = BLI_LINKSTACK_POP(queue))) {
1962 bool has_edges = (v->e != NULL);
1963 bool has_faces = false;
1965 /* connected edge-verts */
1970 BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
1971 has_faces |= (BM_edge_is_wire(e) == false);
1973 if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == 0) {
1974 BMVert *v_other = BM_edge_other_vert(e, v);
1975 if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
1976 if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
1977 BM_elem_flag_enable(v_other, BM_ELEM_TAG);
1978 BLI_LINKSTACK_PUSH(queue_next, v_other);
1985 /* imaginary edge diagonally across quad */
1990 BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
1991 if ((BM_elem_flag_test(l->f, BM_ELEM_HIDDEN) == 0) && (l->f->len == 4)) {
1992 BMVert *v_other = l->next->next->v;
1993 if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
1994 if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
1995 BM_elem_flag_enable(v_other, BM_ELEM_TAG);
1996 BLI_LINKSTACK_PUSH(queue_next, v_other);
2004 /* clear for the next loop */
2005 for (lnk = queue_next; lnk; lnk = lnk->next) {
2006 BM_elem_flag_disable((BMVert *)lnk->link, BM_ELEM_TAG);
2009 BLI_LINKSTACK_SWAP(queue, queue_next);
2011 /* none should be tagged now since 'queue_next' is empty */
2012 BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0);
2014 } while (BLI_LINKSTACK_SIZE(queue));
2016 BLI_LINKSTACK_FREE(queue);
2017 BLI_LINKSTACK_FREE(queue_next);
2019 MEM_freeN(dists_prev);
2022 static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r_island_tot, int **r_island_vert_map)
2025 struct TransIslandData *trans_islands;
2032 int (*group_index)[2];
2038 if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
2039 groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__);
2040 group_tot = BM_mesh_calc_edge_groups(bm, groups_array, &group_index,
2045 itype = BM_VERTS_OF_EDGE;
2048 else { /* (bm->selectmode & SCE_SELECT_FACE) */
2049 groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
2050 group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index,
2052 BM_ELEM_SELECT, BM_VERT);
2055 itype = BM_VERTS_OF_FACE;
2059 trans_islands = MEM_mallocN(sizeof(*trans_islands) * group_tot, __func__);
2061 vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__);
2062 /* we shouldn't need this, but with incorrect selection flushing
2063 * its possible we have a selected vertex thats not in a face, for now best not crash in that case. */
2064 fill_vn_i(vert_map, bm->totvert, -1);
2066 BM_mesh_elem_table_ensure(bm, htype);
2067 ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable;
2069 BM_mesh_elem_index_ensure(bm, BM_VERT);
2071 /* may be an edge OR a face array */
2072 for (i = 0; i < group_tot; i++) {
2073 BMEditSelection ese = {NULL};
2075 const int fg_sta = group_index[i][0];
2076 const int fg_len = group_index[i][1];
2077 float co[3], no[3], tangent[3];
2086 /* loop on each face in this group:
2087 * - assign r_vert_map
2088 * - calculate (co, no)
2090 for (j = 0; j < fg_len; j++) {
2091 float tmp_co[3], tmp_no[3], tmp_tangent[3];
2093 ese.ele = ele_array[groups_array[fg_sta + j]];
2095 BM_editselection_center(&ese, tmp_co);
2096 BM_editselection_normal(&ese, tmp_no);
2097 BM_editselection_plane(&ese, tmp_tangent);
2099 add_v3_v3(co, tmp_co);
2100 add_v3_v3(no, tmp_no);
2101 add_v3_v3(tangent, tmp_tangent);
2104 /* setup vertex map */
2108 /* connected edge-verts */
2109 BM_ITER_ELEM (v, &iter, ese.ele, itype) {
2110 vert_map[BM_elem_index_get(v)] = i;
2115 mul_v3_v3fl(trans_islands[i].co, co, 1.0f / (float)fg_len);
2117 if (createSpaceNormalTangent(trans_islands[i].axismtx, no, tangent)) {
2121 if (normalize_v3(no) != 0.0f) {
2122 axis_dominant_v3_to_m3(trans_islands[i].axismtx, no);
2123 invert_m3(trans_islands[i].axismtx);
2126 unit_m3(trans_islands[i].axismtx);
2131 MEM_freeN(groups_array);
2132 MEM_freeN(group_index);
2134 *r_island_tot = group_tot;
2135 *r_island_vert_map = vert_map;
2137 return trans_islands;
2140 /* way to overwrite what data is edited with transform */
2141 static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx,
2142 BMEditMesh *em, BMVert *eve, float *bweight,
2143 struct TransIslandData *v_island)
2145 BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
2149 // td->loc = key->co;
2152 copy_v3_v3(td->iloc, td->loc);
2155 copy_v3_v3(td->center, v_island->co);
2156 copy_m3_m3(td->axismtx, v_island->axismtx);
2158 else if (t->around == V3D_LOCAL) {
2159 copy_v3_v3(td->center, td->loc);
2160 createSpaceNormal(td->axismtx, eve->no);
2163 copy_v3_v3(td->center, td->loc);
2165 /* Setting normals */
2166 copy_v3_v3(td->axismtx[2], eve->no);
2172 td->axismtx[1][2] = 0.0f;
2179 if (t->mode == TFM_BWEIGHT) {
2181 td->ival = *bweight;
2183 else if (t->mode == TFM_SKIN_RESIZE) {
2184 MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata,
2187 /* skin node size */
2189 copy_v3_v3(tx->isize, vs->radius);
2190 tx->size = vs->radius;
2191 td->val = vs->radius;
2193 else if (t->mode == TFM_SHRINKFATTEN) {
2195 tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, BM_ELEM_SELECT);
2199 static void createTransEditVerts(TransInfo *t)
2201 TransData *tob = NULL;
2202 TransDataExtension *tx = NULL;
2203 BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
2204 Mesh *me = t->obedit->data;
2208 float (*mappedcos)[3] = NULL, (*quats)[4] = NULL;
2209 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2210 float *dists = NULL;
2212 int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
2214 int cd_vert_bweight_offset = -1;
2215 bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
2217 struct TransIslandData *island_info = NULL;
2218 int island_info_tot;
2219 int *island_vert_map = NULL;
2221 if (t->flag & T_MIRROR) {
2222 EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
2226 /* quick check if we can transform */
2227 /* note: in prop mode we need at least 1 selected */
2228 if (em->selectmode & SCE_SELECT_VERTEX) {
2229 if (bm->totvertsel == 0) {
2233 else if (em->selectmode & SCE_SELECT_EDGE) {
2234 if (bm->totvertsel == 0 || bm->totedgesel == 0) {
2238 else if (em->selectmode & SCE_SELECT_FACE) {
2239 if (bm->totvertsel == 0 || bm->totfacesel == 0) {
2247 if (t->mode == TFM_BWEIGHT) {
2248 BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_VERT_BWEIGHT);
2249 cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
2253 unsigned int count = 0;
2254 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
2255 if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2262 /* allocating scratch arrays */
2263 if (propmode & T_PROP_CONNECTED)
2264 dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears");
2267 t->total = bm->totvertsel;
2270 tob = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mesh EditMode)");
2271 if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
2272 /* warning, this is overkill, we only need 2 extra floats,
2273 * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
2274 * since we may not use the 'alt' transform mode to maintain shell thickness,
2275 * but with generic transform code its hard to lazy init vars */
2276 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension),
2280 copy_m3_m4(mtx, t->obedit->obmat);
2281 /* we use a pseudoinverse so that when one of the axes is scaled to 0,
2282 * matrix inversion still works and we can still moving along the other */
2283 pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
2285 if (propmode & T_PROP_CONNECTED) {
2286 editmesh_set_connectivity_distance(em->bm, mtx, dists);
2289 if (t->around == V3D_LOCAL) {
2290 island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map);
2293 /* detect CrazySpace [tm] */
2294 if (modifiers_getCageIndex(t->scene, t->obedit, NULL, 1) != -1) {
2296 if (modifiers_isCorrectableDeformed(t->scene, t->obedit)) {
2297 /* check if we can use deform matrices for modifier from the
2298 * start up to stack, they are more accurate than quats */
2299 totleft = editbmesh_get_first_deform_matrices(t->scene, t->obedit, em, &defmats, &defcos);
2302 /* if we still have more modifiers, also do crazyspace
2303 * correction with quats, relative to the coordinates after
2304 * the modifiers that support deform matrices (defcos) */
2306 #if 0 /* TODO, fix crazyspace+extrude so it can be enabled for general use - campbell */
2307 if ((totleft > 0) || (totleft == -1))
2312 mappedcos = BKE_crazyspace_get_mapped_editverts(t->scene, t->obedit);
2313 quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
2314 BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !propmode);
2316 MEM_freeN(mappedcos);
2324 /* find out which half we do */
2326 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
2327 if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve->co[0] != 0.0f) {
2328 if (eve->co[0] < 0.0f) {
2337 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
2338 if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2339 if (propmode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
2340 struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ?
2341 &island_info[island_vert_map[a]] : NULL;
2342 float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL;
2344 VertsToTransData(t, tob, tx, em, eve, bweight, v_island);
2349 if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
2350 tob->flag |= TD_SELECTED;
2353 if (propmode & T_PROP_CONNECTED) {
2354 tob->dist = dists[a];
2357 tob->flag |= TD_NOTCONNECTED;
2358 tob->dist = FLT_MAX;
2363 if (defmats || (quats && BM_elem_flag_test(eve, BM_ELEM_TAG))) {
2364 float mat[3][3], qmat[3][3], imat[3][3];
2366 /* use both or either quat and defmat correction */
2367 if (quats && BM_elem_flag_test(eve, BM_ELEM_TAG)) {
2368 quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
2371 mul_m3_series(mat, defmats[a], qmat, mtx);
2373 mul_m3_m3m3(mat, mtx, qmat);
2376 mul_m3_m3m3(mat, mtx, defmats[a]);
2378 invert_m3_m3(imat, mat);
2380 copy_m3_m3(tob->smtx, imat);
2381 copy_m3_m3(tob->mtx, mat);
2384 copy_m3_m3(tob->smtx, smtx);
2385 copy_m3_m3(tob->mtx, mtx);
2389 if ((mirror > 0 && tob->iloc[0] > 0.0f) || (mirror < 0 && tob->iloc[0] < 0.0f)) {
2390 BMVert *vmir = EDBM_verts_mirror_get(em, eve); //t->obedit, em, eve, tob->iloc, a);
2391 if (vmir && vmir != eve) {
2401 MEM_freeN(island_info);
2402 MEM_freeN(island_vert_map);
2407 for (a = 0; a < t->total; a++, tob++) {
2408 if (ABS(tob->loc[0]) <= 0.00001f) {
2409 tob->flag |= TD_MIRROR_EDGE;
2415 /* crazy space free */
2423 if (t->flag & T_MIRROR) {
2424 EDBM_verts_mirror_cache_end(em);
2428 /* *** NODE EDITOR *** */
2429 void flushTransNodes(TransInfo *t)
2431 const float dpi_fac = UI_DPI_FAC;
2436 applyGridAbsolute(t);
2438 /* flush to 2d vector from internally used 3d vector */
2439 for (a = 0, td = t->data, td2d = t->data2d; a < t->total; a++, td++, td2d++) {
2440 bNode *node = td->extra;
2443 /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
2444 #ifdef USE_NODE_CENTER
2445 locx = (td2d->loc[0] - (BLI_rctf_size_x(&node->totr)) * +0.5f) / dpi_fac;
2446 locy = (td2d->loc[1] - (BLI_rctf_size_y(&node->totr)) * -0.5f) / dpi_fac;
2448 locx = td2d->loc[0] / dpi_fac;
2449 locy = td2d->loc[1] / dpi_fac;
2452 /* account for parents (nested nodes) */
2454 nodeFromView(node->parent, locx, locy, &node->locx, &node->locy);
2462 /* handle intersection with noodles */
2463 if (t->total == 1) {
2464 ED_node_link_intersect_test(t->sa, 1);
2468 /* *** SEQUENCE EDITOR *** */
2470 /* commented _only_ because the meta may have animation data which
2471 * needs moving too [#28158] */
2473 #define SEQ_TX_NESTED_METAS
2475 BLI_INLINE void trans_update_seq(Scene *sce, Sequence *seq, int old_start, int sel_flag)
2477 if (seq->depth == 0) {
2478 /* Calculate this strip and all nested strips.
2479 * Children are ALWAYS transformed first so we don't need to do this in another loop.
2481 BKE_sequence_calc(sce, seq);
2484 BKE_sequence_calc_disp(sce, seq);
2487 if (sel_flag == SELECT)
2488 BKE_sequencer_offset_animdata(sce, seq, seq->start - old_start);
2491 void flushTransSeq(TransInfo *t)
2493 ListBase *seqbasep = BKE_sequencer_editing_get(t->scene, false)->seqbasep; /* Editing null check already done */
2495 TransData *td = NULL;
2496 TransData2D *td2d = NULL;
2497 TransDataSeq *tdsq = NULL;
2502 /* prevent updating the same seq twice
2503 * if the transdata order is changed this will mess up
2504 * but so will TransDataSeq */
2505 Sequence *seq_prev = NULL;
2506 int old_start_prev = 0, sel_flag_prev = 0;
2508 /* flush to 2d vector from internally used 3d vector */
2509 for (a = 0, td = t->data, td2d = t->data2d; a < t->total; a++, td++, td2d++) {
2511 tdsq = (TransDataSeq *)td->extra;
2513 old_start = seq->start;
2514 new_frame = iroundf(td2d->loc[0]);
2516 switch (tdsq->sel_flag) {
2518 #ifdef SEQ_TX_NESTED_METAS
2519 if ((seq->depth != 0 || BKE_sequence_tx_test(seq))) /* for meta's, their children move */
2520 seq->start = new_frame - tdsq->start_offset;
2522 if (seq->type != SEQ_TYPE_META && (seq->depth != 0 || seq_tx_test(seq))) /* for meta's, their children move */
2523 seq->start = new_frame - tdsq->start_offset;
2525 if (seq->depth == 0) {
2526 seq->machine = iroundf(td2d->loc[1]);
2527 CLAMP(seq->machine, 1, MAXSEQ);
2530 case SEQ_LEFTSEL: /* no vertical transform */
2531 BKE_sequence_tx_set_final_left(seq, new_frame);
2532 BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
2533 BKE_sequence_single_fix(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2535 case SEQ_RIGHTSEL: /* no vertical transform */
2536 BKE_sequence_tx_set_final_right(seq, new_frame);
2537 BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
2538 BKE_sequence_single_fix(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2542 /* Update *previous* seq! Else, we would update a seq after its first transform, and if it has more than one
2543 * (like e.g. SEQ_LEFTSEL and SEQ_RIGHTSEL), the others are not updated! See T38469.
2545 if (seq != seq_prev) {
2547 trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
2551 old_start_prev = old_start;
2552 sel_flag_prev = tdsq->sel_flag;
2555 /* We want to accumulate *all* sel_flags for this seq! */
2556 sel_flag_prev |= tdsq->sel_flag;
2560 /* Don't forget to update the last seq! */
2562 trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
2566 if (ELEM(t->mode, TFM_SEQ_SLIDE, TFM_TIME_TRANSLATE)) { /* originally TFM_TIME_EXTEND, transform changes */
2567 /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
2569 /* calc all meta's then effects [#27953] */
2570 for (seq = seqbasep->first; seq; seq = seq->next) {
2571 if (seq->type == SEQ_TYPE_META && seq->flag & SELECT) {
2572 BKE_sequence_calc(t->scene, seq);
2575 for (seq = seqbasep->first; seq; seq = seq->next) {
2576 if (seq->seq1 || seq->seq2 || seq->seq3) {
2577 BKE_sequence_calc(t->scene, seq);
2582 /* need to do the overlap check in a new loop otherwise adjacent strips
2583 * will not be updated and we'll get false positives */
2585 for (a = 0, td = t->data, td2d = t->data2d; a < t->total; a++, td++, td2d++) {
2587 tdsq = (TransDataSeq *)td->extra;
2590 if (seq != seq_prev) {
2591 if (seq->depth == 0) {
2592 /* test overlap, displayes red outline */
2593 seq->flag &= ~SEQ_OVERLAP;
2594 if (BKE_sequence_test_overlap(seqbasep, seq)) {
2595 seq->flag |= SEQ_OVERLAP;
2603 /* ********************* UV ****************** */
2605 static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, float *uv, int selected)
2609 ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
2611 /* uv coords are scaled by aspects. this is needed for rotations and
2612 * proportional editing to be consistent with the stretched uv coords
2613 * that are displayed. this also means that for display and numinput,
2614 * and when the the uv coords are flushed, these are converted each time */
2615 td2d->loc[0] = uv[0] * aspx;
2616 td2d->loc[1] = uv[1] * aspy;
2617 td2d->loc[2] = 0.0f;
2621 td->loc = td2d->loc;
2622 copy_v3_v3(td->center, td->loc);
2623 copy_v3_v3(td->iloc, td->loc);
2625 memset(td->axismtx, 0, sizeof(td->axismtx));
2626 td->axismtx[2][2] = 1.0f;
2628 td->ext = NULL; td->val = NULL;
2631 td->flag |= TD_SELECTED;
2641 static void createTransUVs(bContext *C, TransInfo *t)
2643 SpaceImage *sima = CTX_wm_space_image(C);
2644 Image *ima = CTX_data_edit_image(C);
2645 Scene *scene = t->scene;
2646 ToolSettings *ts = CTX_data_tool_settings(C);
2647 TransData *td = NULL;
2648 TransData2D *td2d = NULL;
2651 BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
2655 UvElementMap *elementmap = NULL;
2656 BLI_bitmap *island_enabled = NULL;
2657 int count = 0, countsel = 0, count_rejected = 0;
2658 const bool propmode = (t->flag & T_PROP_EDIT) != 0;
2659 const bool propconnected = (t->flag & T_PROP_CONNECTED) != 0;
2661 const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
2663 if (!ED_space_image_show_uvedit(sima, t->obedit)) return;
2666 if (propconnected) {
2667 /* create element map with island information */
2668 if (ts->uv_flag & UV_SYNC_SELECTION) {
2669 elementmap = BM_uv_element_map_create(em->bm, false, true);
2672 elementmap = BM_uv_element_map_create(em->bm, true, true);
2674 island_enabled = BLI_BITMAP_NEW(elementmap->totalIslands, "TransIslandData(UV Editing)");
2677 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2678 tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
2680 if (!uvedit_face_visible_test(scene, ima, efa, tf)) {
2681 BM_elem_flag_disable(efa, BM_ELEM_TAG);
2685 BM_elem_flag_enable(efa, BM_ELEM_TAG);
2686 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
2687 if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
2690 if (propconnected) {
2691 UvElement *element = BM_uv_element_get(elementmap, efa, l);
2692 BLI_BITMAP_ENABLE(island_enabled, element->island);
2703 /* note: in prop mode we need at least 1 selected */
2704 if (countsel == 0) {
2705 if (propconnected) {
2706 MEM_freeN(island_enabled);
2711 t->total = (propmode) ? count : countsel;
2712 t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(UV Editing)");
2713 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2714 * treated just as if they were 3d verts */
2715 t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransObData2D(UV Editing)");
2717 if (sima->flag & SI_CLIP_UV)
2718 t->flag |= T_CLIP_UV;
2723 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2724 if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
2727 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
2728 if (!propmode && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
2731 if (propconnected) {
2732 UvElement *element = BM_uv_element_get(elementmap, efa, l);
2733 if (!BLI_BITMAP_TEST(island_enabled, element->island)) {
2739 luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
2740 UVsToTransData(sima, td++, td2d++, luv->uv, uvedit_uv_select_test(scene, l, cd_loop_uv_offset));
2744 if (propconnected) {
2745 t->total -= count_rejected;
2746 BM_uv_element_map_free(elementmap);
2747 MEM_freeN(island_enabled);
2750 if (sima->flag & SI_LIVE_UNWRAP)
2751 ED_uvedit_live_unwrap_begin(t->scene, t->obedit);
2754 void flushTransUVs(TransInfo *t)
2756 SpaceImage *sima = t->sa->spacedata.first;
2758 int a, width, height;
2759 float aspx, aspy, invx, invy;