4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): none yet.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
43 #include "MEM_guardedalloc.h"
45 #include "DNA_action_types.h"
46 #include "DNA_armature_types.h"
47 #include "DNA_camera_types.h"
48 #include "DNA_curve_types.h"
49 #include "DNA_effect_types.h"
50 #include "DNA_image_types.h"
51 #include "DNA_ipo_types.h"
52 #include "DNA_key_types.h"
53 #include "DNA_lamp_types.h"
54 #include "DNA_lattice_types.h"
55 #include "DNA_mesh_types.h"
56 #include "DNA_meshdata_types.h"
57 #include "DNA_meta_types.h"
58 #include "DNA_modifier_types.h"
59 #include "DNA_object_types.h"
60 #include "DNA_object_force.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_screen_types.h"
63 #include "DNA_texture_types.h"
64 #include "DNA_view3d_types.h"
65 #include "DNA_world_types.h"
66 #include "DNA_userdef_types.h"
67 #include "DNA_property_types.h"
68 #include "DNA_vfont_types.h"
69 #include "DNA_constraint_types.h"
71 #include "BKE_action.h"
72 #include "BKE_armature.h"
73 #include "BKE_blender.h"
74 #include "BKE_curve.h"
75 #include "BKE_constraint.h"
76 #include "BKE_depsgraph.h"
77 #include "BKE_displist.h"
78 #include "BKE_effect.h"
80 #include "BKE_global.h"
82 #include "BKE_lattice.h"
83 #include "BKE_mball.h"
84 #include "BKE_modifier.h"
85 #include "BKE_object.h"
86 #include "BKE_softbody.h"
87 #include "BKE_utildefines.h"
89 #include "BIF_editaction.h"
90 #include "BIF_editview.h"
91 #include "BIF_editlattice.h"
92 #include "BIF_editconstraint.h"
93 #include "BIF_editarmature.h"
94 #include "BIF_editmesh.h"
96 #include "BIF_poseobject.h"
97 #include "BIF_mywindow.h"
98 #include "BIF_resources.h"
99 #include "BIF_screen.h"
100 #include "BIF_space.h"
101 #include "BIF_toolbox.h"
103 #include "BSE_view.h"
104 #include "BSE_edit.h"
105 #include "BSE_editipo.h"
106 #include "BSE_editipo_types.h"
108 #include "BDR_editobject.h" // reset_slowparents()
110 #include "BLI_arithb.h"
111 #include "BLI_editVert.h"
115 #include "mydevice.h"
117 extern ListBase editNurb;
118 extern ListBase editelems;
120 #include "transform.h"
123 /* ************************** Functions *************************** */
125 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
126 TransData pivot = *head;
127 TransData *ihead = head;
128 TransData *itail = tail;
129 short connected = t->flag & T_PROP_CONNECTED;
134 while ((tail->dist >= pivot.dist) && (head < tail))
138 while ((tail->rdist >= pivot.rdist) && (head < tail))
149 while ((head->dist <= pivot.dist) && (head < tail))
153 while ((head->rdist <= pivot.rdist) && (head < tail))
166 qsort_trans_data(t, ihead, head-1);
169 qsort_trans_data(t, head+1, itail);
173 void sort_trans_data_dist(TransInfo *t) {
174 TransData *start = t->data;
177 while(i < t->total && start->flag & TD_SELECTED) {
181 qsort_trans_data(t, start, t->data + t->total - 1);
184 static void sort_trans_data(TransInfo *t)
186 TransData *sel, *unsel;
191 while (sel > unsel) {
192 while (unsel->flag & TD_SELECTED) {
198 while (!(sel->flag & TD_SELECTED)) {
213 /* distance calculated from not-selected vertex to nearest selected vertex
214 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
215 static void set_prop_dist(TransInfo *t, short with_dist)
220 for(a=0, tob= t->data; a<t->total; a++, tob++) {
222 tob->rdist= 0.0f; // init, it was mallocced
224 if((tob->flag & TD_SELECTED)==0) {
229 tob->rdist = -1.0f; // signal for next loop
231 for (i = 0, td= t->data; i < t->total; i++, td++) {
232 if(td->flag & TD_SELECTED) {
233 VecSubf(vec, tob->center, td->center);
234 Mat3MulVecfl(tob->mtx, vec);
235 dist = Normalise(vec);
236 if (tob->rdist == -1.0f) {
239 else if (dist < tob->rdist) {
243 else break; // by definition transdata has selected items in beginning
246 tob->dist = tob->rdist;
252 /* ************************** CONVERSIONS ************************* */
254 /* ********************* texture space ********* */
256 static void createTransTexspace(TransInfo *t)
265 if(id==NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
271 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
272 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
274 td->flag= TD_SELECTED;
275 VECCOPY(td->center, ob->obmat[3]);
278 Mat3CpyMat4(td->mtx, ob->obmat);
279 Mat3Inv(td->smtx, td->mtx);
281 if( GS(id->name)==ID_ME) {
283 me->texflag &= ~AUTOSPACE;
285 td->ext->rot= me->rot;
286 td->ext->size= me->size;
288 else if( GS(id->name)==ID_CU) {
290 cu->texflag &= ~CU_AUTOSPACE;
292 td->ext->rot= cu->rot;
293 td->ext->size= cu->size;
295 else if( GS(id->name)==ID_MB) {
296 MetaBall *mb= ob->data;
297 mb->texflag &= ~MB_AUTOSPACE;
299 td->ext->rot= mb->rot;
300 td->ext->size= mb->size;
303 VECCOPY(td->iloc, td->loc);
304 VECCOPY(td->ext->irot, td->ext->rot);
305 VECCOPY(td->ext->isize, td->ext->size);
308 /* ********************* edge (for crease) ***** */
310 static void createTransEdge(TransInfo *t) {
311 TransData *td = NULL;
312 EditMesh *em = G.editMesh;
314 Mesh *me = G.obedit->data;
315 float mtx[3][3], smtx[3][3];
316 int count=0, countsel=0;
317 int propmode = t->flag & T_PROP_EDIT;
319 /* THIS IS A REALLY STUPID HACK, MUST BE A BETTER WAY TO DO IT */
320 /* this is sufficient to invoke edges added in mesh, but only in editmode */
321 if(me->medge==NULL) {
322 me->medge= MEM_callocN(sizeof(MEdge), "fake medge");
324 allqueue(REDRAWBUTSEDIT, 0);
327 for(eed= em->edges.first; eed; eed= eed->next) {
329 if (eed->f & SELECT) countsel++;
330 if (propmode) count++;
344 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
346 Mat3CpyMat4(mtx, G.obedit->obmat);
349 for(eed= em->edges.first; eed; eed= eed->next) {
350 if(eed->h==0 && (eed->f & SELECT || propmode)) {
351 /* need to set center for center calculations */
352 VecAddf(td->center, eed->v1->co, eed->v2->co);
353 VecMulf(td->center, 0.5f);
357 td->flag= TD_SELECTED;
362 Mat3CpyMat3(td->smtx, smtx);
363 Mat3CpyMat3(td->mtx, mtx);
367 td->val = &(eed->crease);
368 td->ival = eed->crease;
375 /* ********************* pose mode ************* */
377 /* recursive, make sure it's identical structured as next one */
378 /* only counts the parent selection, and tags transform flag */
379 /* exported for manipulator */
380 void count_bone_select(TransInfo *t, ListBase *lb, int do_it)
385 for(bone= lb->first; bone; bone= bone->next) {
386 bone->flag &= ~BONE_TRANSFORM;
389 if (bone->flag & BONE_SELECTED) {
390 /* We don't let IK children get "grabbed" */
391 if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_IK_TOPARENT)==0 ) {
392 bone->flag |= BONE_TRANSFORM;
394 do_next= 0; // no transform on children if one parent bone is selected
398 count_bone_select(t, &bone->childbase, do_next);
402 static int add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
404 Bone *bone= pchan->bone;
405 float pmat[3][3], omat[3][3];
409 if (bone->flag & BONE_TRANSFORM) {
410 /* We don't let IK children get "grabbed" */
411 if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_IK_TOPARENT)==0 ) {
413 VECCOPY(vec, pchan->pose_mat[3]);
414 VECCOPY(td->center, vec);
417 td->flag= TD_SELECTED|TD_USEQUAT;
418 td->loc = pchan->loc;
419 VECCOPY(td->iloc, pchan->loc);
422 td->ext->quat= pchan->quat;
423 td->ext->size= pchan->size;
425 QUATCOPY(td->ext->iquat, pchan->quat);
426 VECCOPY(td->ext->isize, pchan->size);
428 /* proper way to get the parent transform + own transform */
429 Mat3CpyMat4(omat, ob->obmat);
431 if(pchan->bone->flag & BONE_HINGE)
432 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
434 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
436 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
439 Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // huh, transposed?
442 Mat3Inv (td->smtx, td->mtx);
444 /* for axismat we use bone's own transform */
445 Mat3CpyMat4(pmat, pchan->pose_mat);
446 Mat3MulMat3(td->axismtx, omat, pmat);
447 Mat3Ortho(td->axismtx);
449 if(t->mode==TFM_BONESIZE) {
450 bArmature *arm= t->poseobj->data;
452 if(arm->drawtype==ARM_ENVELOPE) {
454 td->val= &bone->dist;
455 td->ival= bone->dist;
458 // abusive storage of scale in the loc pointer :)
459 td->loc= &bone->xwidth;
460 VECCOPY (td->iloc, td->loc);
472 /* only called with pose mode active object now */
473 static void createTransPose(Object *ob, TransInfo *t)
478 TransDataExtension *tdx;
481 /* check validity of state */
482 arm=get_armature (ob);
483 if (arm==NULL || ob->pose==NULL) return;
485 if (arm->flag & ARM_RESTPOS) {
486 if(t->mode!=TFM_BONESIZE) {
487 notice ("Pose edit not possible while Rest Position is enabled");
491 if (!(ob->lay & G.vd->lay)) return;
494 count_bone_select(t, &arm->bonebase, 1);
496 if(t->total==0 && t->mode==TFM_TRANSLATION) {
497 t->mode= TFM_ROTATION;
498 count_bone_select(t, &arm->bonebase, 1);
500 if(t->total==0) return;
503 t->poseobj= ob; // we also allow non-active objects to be transformed, in weightpaint
505 /* init trans data */
506 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
507 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
508 for(i=0; i<t->total; i++, td++, tdx++) {
514 /* use pose channels to fill trans data */
516 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
517 if( add_pose_transdata(t, pchan, ob, td) ) td++;
519 if(td != (t->data+t->total)) printf("Bone selection count error\n");
523 /* ********************* armature ************** */
525 static void createTransArmatureVerts(TransInfo *t)
528 bArmature *arm= G.obedit->data;
530 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
533 for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
534 if (t->mode==TFM_BONESIZE) {
535 if (ebo->flag & BONE_SELECTED)
539 if (ebo->flag & BONE_TIPSEL)
541 if (ebo->flag & BONE_ROOTSEL)
546 if (!t->total) return;
548 Mat3CpyMat4(mtx, G.obedit->obmat);
551 td = t->data = MEM_mallocN(t->total*sizeof(TransData), "TransEditBone");
553 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
555 ebo->oldlength= ebo->length; // might be used for scaling
557 if (t->mode==TFM_BONE_ENVELOPE) {
559 if (ebo->flag & BONE_ROOTSEL){
560 td->val= &ebo->rad_head;
563 VECCOPY (td->center, ebo->head);
564 td->flag= TD_SELECTED;
566 Mat3CpyMat3(td->smtx, smtx);
567 Mat3CpyMat3(td->mtx, mtx);
575 if (ebo->flag & BONE_TIPSEL){
576 td->val= &ebo->rad_tail;
578 VECCOPY (td->center, ebo->tail);
579 td->flag= TD_SELECTED;
581 Mat3CpyMat3(td->smtx, smtx);
582 Mat3CpyMat3(td->mtx, mtx);
592 else if (t->mode==TFM_BONESIZE) {
593 if (ebo->flag & BONE_SELECTED) {
594 if(arm->drawtype==ARM_ENVELOPE) {
600 // abusive storage of scale in the loc pointer :)
601 td->loc= &ebo->xwidth;
602 VECCOPY (td->iloc, td->loc);
605 VECCOPY (td->center, ebo->head);
606 td->flag= TD_SELECTED;
608 /* use local bone matrix */
609 VecSubf(delta, ebo->tail, ebo->head);
610 vec_roll_to_mat3(delta, ebo->roll, bonemat);
611 Mat3MulMat3(td->mtx, mtx, bonemat);
612 Mat3Inv(td->smtx, td->mtx);
614 Mat3CpyMat3(td->axismtx, td->mtx);
615 Mat3Ortho(td->axismtx);
624 if (ebo->flag & BONE_TIPSEL){
625 VECCOPY (td->iloc, ebo->tail);
626 VECCOPY (td->center, td->iloc);
628 td->flag= TD_SELECTED;
630 Mat3CpyMat3(td->smtx, smtx);
631 Mat3CpyMat3(td->mtx, mtx);
639 if (ebo->flag & BONE_ROOTSEL){
640 VECCOPY (td->iloc, ebo->head);
641 VECCOPY (td->center, td->iloc);
643 td->flag= TD_SELECTED;
645 Mat3CpyMat3(td->smtx, smtx);
646 Mat3CpyMat3(td->mtx, mtx);
658 /* ********************* meta elements ********* */
660 static void createTransMBallVerts(TransInfo *t)
664 TransDataExtension *tx;
665 float mtx[3][3], smtx[3][3];
666 int count=0, countsel=0;
667 int propmode = t->flag & T_PROP_EDIT;
670 for(ml= editelems.first; ml; ml= ml->next) {
671 if(ml->flag & SELECT) countsel++;
672 if(propmode) count++;
675 /* note: in prop mode we need at least 1 selected */
676 if (countsel==0) return;
678 if(propmode) t->total = count;
679 else t->total = countsel;
681 td = t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
682 tx = t->ext = MEM_mallocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
684 Mat3CpyMat4(mtx, G.obedit->obmat);
687 for(ml= editelems.first; ml; ml= ml->next) {
688 if(propmode || (ml->flag & SELECT)) {
690 VECCOPY(td->iloc, td->loc);
691 VECCOPY(td->center, td->loc);
693 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
694 else td->flag= TD_USEQUAT;
696 Mat3CpyMat3(td->smtx, smtx);
697 Mat3CpyMat3(td->mtx, mtx);
702 /* Radius of MetaElem (mass of MetaElem influence) */
703 if(ml->flag & MB_SCALE_RAD){
712 /* expx/expy/expz determine "shape" of some MetaElem types */
713 tx->size = &ml->expx;
714 tx->isize[0] = ml->expx;
715 tx->isize[1] = ml->expy;
716 tx->isize[2] = ml->expz;
718 /* quat is used for rotation of MetaElem */
720 QUATCOPY(tx->iquat, ml->quat);
730 /* ********************* curve/surface ********* */
732 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
733 TransData *td, *td_near = NULL;
734 for (td = head; td<=tail; td++) {
735 if (td->flag & TD_SELECTED) {
741 dist = VecLenf(td_near->center, td->center);
742 if (dist < (td-1)->dist) {
743 td->dist = (td-1)->dist;
751 td->flag |= TD_NOTCONNECTED;
755 for (td = tail; td>=head; td--) {
756 if (td->flag & TD_SELECTED) {
762 dist = VecLenf(td_near->center, td->center);
763 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
764 td->flag &= ~TD_NOTCONNECTED;
765 if (dist < (td+1)->dist) {
766 td->dist = (td+1)->dist;
776 static void createTransCurveVerts(TransInfo *t)
778 TransData *td = NULL;
782 float mtx[3][3], smtx[3][3];
784 int count=0, countsel=0;
785 int propmode = t->flag & T_PROP_EDIT;
787 /* count total of vertices, check identical as in 2nd loop for making transdata! */
788 for(nu= editNurb.first; nu; nu= nu->next) {
789 if((nu->type & 7)==CU_BEZIER) {
790 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
792 if(bezt->f1 & 1) countsel++;
793 if(bezt->f2 & 1) countsel++;
794 if(bezt->f3 & 1) countsel++;
795 if(propmode) count+= 3;
800 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
802 if(propmode) count++;
803 if(bp->f1 & 1) countsel++;
808 /* note: in prop mode we need at least 1 selected */
809 if (countsel==0) return;
811 if(propmode) t->total = count;
812 else t->total = countsel;
813 t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
815 Mat3CpyMat4(mtx, G.obedit->obmat);
819 for(nu= editNurb.first; nu; nu= nu->next) {
820 if((nu->type & 7)==CU_BEZIER) {
821 TransData *head, *tail;
823 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
825 if(propmode || (bezt->f1 & 1)) {
826 VECCOPY(td->iloc, bezt->vec[0]);
827 td->loc= bezt->vec[0];
828 VECCOPY(td->center, bezt->vec[1]);
829 if(bezt->f1 & 1) td->flag= TD_SELECTED;
835 Mat3CpyMat3(td->smtx, smtx);
836 Mat3CpyMat3(td->mtx, mtx);
842 /* THIS IS THE CV, the other two are handles */
843 if(propmode || (bezt->f2 & 1)) {
844 VECCOPY(td->iloc, bezt->vec[1]);
845 td->loc= bezt->vec[1];
846 VECCOPY(td->center, td->loc);
847 if(bezt->f2 & 1) td->flag= TD_SELECTED;
851 td->val = &(bezt->alfa);
852 td->ival = bezt->alfa;
854 Mat3CpyMat3(td->smtx, smtx);
855 Mat3CpyMat3(td->mtx, mtx);
861 if(propmode || (bezt->f3 & 1)) {
862 VECCOPY(td->iloc, bezt->vec[2]);
863 td->loc= bezt->vec[2];
864 VECCOPY(td->center, bezt->vec[1]);
865 if(bezt->f3 & 1) td->flag= TD_SELECTED;
871 Mat3CpyMat3(td->smtx, smtx);
872 Mat3CpyMat3(td->mtx, mtx);
879 else if (propmode && head != tail) {
880 calc_distanceCurveVerts(head, tail-1);
884 if (propmode && head != tail)
885 calc_distanceCurveVerts(head, tail-1);
888 TransData *head, *tail;
890 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
892 if(propmode || (bp->f1 & 1)) {
893 VECCOPY(td->iloc, bp->vec);
895 VECCOPY(td->center, td->loc);
896 if(bp->f1 & 1) td->flag= TD_SELECTED;
900 td->val = &(bp->alfa);
903 Mat3CpyMat3(td->smtx, smtx);
904 Mat3CpyMat3(td->mtx, mtx);
911 else if (propmode && head != tail) {
912 calc_distanceCurveVerts(head, tail-1);
916 if (propmode && head != tail)
917 calc_distanceCurveVerts(head, tail-1);
922 /* ********************* lattice *************** */
924 static void createTransLatticeVerts(TransInfo *t)
926 TransData *td = NULL;
928 float mtx[3][3], smtx[3][3];
930 int count=0, countsel=0;
931 int propmode = t->flag & T_PROP_EDIT;
934 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
936 if(bp->f1 & 1) countsel++;
937 if(propmode) count++;
941 /* note: in prop mode we need at least 1 selected */
942 if (countsel==0) return;
944 if(propmode) t->total = count;
945 else t->total = countsel;
946 t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
948 Mat3CpyMat4(mtx, G.obedit->obmat);
953 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
955 if(propmode || (bp->f1 & 1)) {
957 VECCOPY(td->iloc, bp->vec);
959 VECCOPY(td->center, td->loc);
960 if(bp->f1 & 1) td->flag= TD_SELECTED;
962 Mat3CpyMat3(td->smtx, smtx);
963 Mat3CpyMat3(td->mtx, mtx);
977 /* ********************* mesh ****************** */
979 /* proportional distance based on connectivity */
980 #define E_VEC(a) (vectors + (3 * (int)(a)->vn))
981 #define E_NEAR(a) (nears[((int)(a)->vn)])
982 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
984 EditMesh *em = G.editMesh;
989 /* f2 flag is used for 'selection' */
990 /* vn is offset on scratch array */
991 for(eve= em->verts.first; eve; eve= eve->next) {
993 eve->vn = (EditVert *)(i++);
995 if(eve->f & SELECT) {
998 E_VEC(eve)[0] = 0.0f;
999 E_VEC(eve)[1] = 0.0f;
1000 E_VEC(eve)[2] = 0.0f;
1009 /* Floodfill routine */
1011 At worst this is n*n of complexity where n is number of edges
1012 Best case would be n if the list is ordered perfectly.
1013 Estimate is n log n in average (so not too bad)
1018 for(eed= em->edges.first; eed; eed= eed->next) {
1020 EditVert *v1= eed->v1, *v2= eed->v2;
1021 float *vec2 = E_VEC(v2);
1022 float *vec1 = E_VEC(v1);
1024 if (v1->f2 + v2->f2 == 4)
1030 float len1 = VecLength(vec1);
1031 float len2 = VecLength(vec2);
1033 /* for v2 if not selected */
1035 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1036 lenn = VecLength(nvec);
1037 if (lenn - len1 > 0.00001f && len2 - lenn > 0.00001f) {
1038 VECCOPY(vec2, nvec);
1039 E_NEAR(v2) = E_NEAR(v1);
1042 else if (len2 - len1 > 0.00001f && len1 - lenn > 0.00001f) {
1043 VECCOPY(vec2, vec1);
1044 E_NEAR(v2) = E_NEAR(v1);
1048 /* for v1 if not selected */
1050 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1051 lenn = VecLength(nvec);
1052 if (lenn - len2 > 0.00001f && len1 - lenn > 0.00001f) {
1053 VECCOPY(vec1, nvec);
1054 E_NEAR(v1) = E_NEAR(v2);
1057 else if (len1 - len2 > 0.00001f && len2 - lenn > 0.00001f) {
1058 VECCOPY(vec1, vec2);
1059 E_NEAR(v1) = E_NEAR(v2);
1066 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1067 if (VecLength(vec1) - VecLength(vec2) > 0.00001f) {
1068 VECCOPY(vec2, vec1);
1070 E_NEAR(v2) = E_NEAR(v1);
1076 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1077 if (VecLength(vec2) - VecLength(vec1) > 0.00001f) {
1078 VECCOPY(vec1, vec2);
1080 E_NEAR(v1) = E_NEAR(v2);
1089 static void VertsToTransData(TransData *td, EditVert *eve)
1093 VECCOPY(td->center, td->loc);
1094 VECCOPY(td->iloc, td->loc);
1097 VECCOPY(td->axismtx[2], eve->no);
1103 td->axismtx[1][2] = 0.0f;
1110 static void createTransEditVerts(TransInfo *t)
1112 TransData *tob = NULL;
1113 EditMesh *em = G.editMesh;
1115 EditVert **nears = NULL;
1116 float *vectors = NULL;
1117 float mtx[3][3], smtx[3][3];
1118 int count=0, countsel=0;
1119 int propmode = t->flag & T_PROP_EDIT;
1121 // transform now requires awareness for select mode, so we tag the f1 flags in verts
1122 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1123 for(eve= em->verts.first; eve; eve= eve->next) {
1124 if(eve->h==0 && (eve->f & SELECT))
1130 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1132 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1133 for(eed= em->edges.first; eed; eed= eed->next) {
1134 if(eed->h==0 && (eed->f & SELECT))
1135 eed->v1->f1= eed->v2->f1= SELECT;
1140 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1141 for(efa= em->faces.first; efa; efa= efa->next) {
1142 if(efa->h==0 && (efa->f & SELECT)) {
1143 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1144 if(efa->v4) efa->v4->f1= SELECT;
1149 /* now we can count */
1150 for(eve= em->verts.first; eve; eve= eve->next) {
1152 if(eve->f1) countsel++;
1153 if(propmode) count++;
1157 /* note: in prop mode we need at least 1 selected */
1158 if (countsel==0) return;
1163 /* allocating scratch arrays */
1164 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
1165 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
1167 else t->total = countsel;
1168 tob= t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
1170 Mat3CpyMat4(mtx, G.obedit->obmat);
1173 if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
1175 for (eve=em->verts.first; eve; eve=eve->next) {
1177 if(propmode || eve->f1) {
1178 VertsToTransData(tob, eve);
1180 if(eve->f1) tob->flag |= TD_SELECTED;
1184 VECCOPY(vec, E_VEC(eve));
1185 Mat3MulVecfl(mtx, vec);
1186 tob->dist= VecLength(vec);
1189 tob->flag |= TD_NOTCONNECTED;
1190 tob->dist = MAXFLOAT;
1194 Mat3CpyMat3(tob->smtx, smtx);
1195 Mat3CpyMat3(tob->mtx, mtx);
1208 /* **************** IpoKey stuff, for Object TransData ********** */
1210 /* storage of bezier triple. thats why -3 and +3! */
1211 static void set_tdi_old(float *old, float *poin)
1218 /* while transforming */
1219 void add_tdi_poin(float *poin, float *old, float delta)
1222 poin[0]= old[0]+delta;
1223 poin[-3]= old[3]+delta;
1224 poin[3]= old[6]+delta;
1228 /* fill ipokey transdata with old vals and pointers */
1229 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
1231 extern int ob_ar[]; // blenkernel ipo.c
1232 TransDataIpokey *tdi= td->tdi;
1236 td->val= NULL; // is read on ESC
1238 for(a=0; a<OB_TOTIPO; a++) {
1242 switch( ob_ar[a] ) {
1245 tdi->locx= &(bezt->vec[1][1]); break;
1248 tdi->locy= &(bezt->vec[1][1]); break;
1251 tdi->locz= &(bezt->vec[1][1]); break;
1256 tdi->rotx= &(bezt->vec[1][1]); break;
1260 tdi->roty= &(bezt->vec[1][1]); break;
1264 tdi->rotz= &(bezt->vec[1][1]); break;
1268 tdi->sizex= &(bezt->vec[1][1]); break;
1271 tdi->sizey= &(bezt->vec[1][1]); break;
1274 tdi->sizez= &(bezt->vec[1][1]); break;
1279 /* oldvals for e.g. undo */
1280 if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
1281 if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
1282 if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
1284 /* remember, for mapping curves ('1'=10 degrees) */
1285 if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
1286 if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
1287 if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
1289 /* this is not allowed to be dsize! */
1290 if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
1291 if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
1292 if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
1295 if(delta) tdi->flag |= TOB_IPODROT;
1299 /* *************************** Object Transform data ******************* */
1301 static void ObjectToTransData(TransData *td, Object *ob)
1305 void *cfirst, *clast;
1307 /* set axismtx BEFORE clearing constraints to have the real orientation */
1308 Mat3CpyMat4(td->axismtx, ob->obmat);
1309 Mat3Ortho(td->axismtx);
1311 /* then why are constraints and track disabled here?
1312 they dont alter loc/rot/size itself (ton) */
1313 cfirst = ob->constraints.first;
1314 clast = ob->constraints.last;
1315 ob->constraints.first=ob->constraints.last=NULL;
1320 where_is_object(ob);
1324 ob->constraints.first = cfirst;
1325 ob->constraints.last = clast;
1330 VECCOPY(td->iloc, td->loc);
1332 td->ext->rot = ob->rot;
1333 VECCOPY(td->ext->irot, ob->rot);
1334 VECCOPY(td->ext->drot, ob->drot);
1336 td->ext->size = ob->size;
1337 VECCOPY(td->ext->isize, ob->size);
1338 VECCOPY(td->ext->dsize, ob->dsize);
1340 VECCOPY(td->center, ob->obmat[3]);
1344 float totmat[3][3], obinv[3][3];
1346 /* we calculate smtx without obmat: so a parmat */
1347 object_to_mat3(ob, obmtx);
1348 Mat3CpyMat4(totmat, ob->obmat);
1349 Mat3Inv(obinv, totmat);
1350 Mat3MulMat3(td->smtx, obmtx, obinv);
1351 Mat3Inv(td->mtx, td->smtx);
1361 /* sets flags in Bases to define whether they take part in transform */
1362 /* it deselects Bases, so we have to call the clear function always after */
1363 static void set_trans_object_base_flags(TransInfo *t)
1366 if Base selected and has parent selected:
1367 base->flag= BA_WAS_SEL
1371 /* makes sure base flags and object flags are identical */
1374 for (base= FIRSTBASE; base; base= base->next) {
1375 base->flag &= ~BA_WAS_SEL;
1377 if(TESTBASELIB(base)) {
1378 Object *ob= base->object;
1379 Object *parsel= ob->parent;
1381 /* if parent selected, deselect */
1383 if(parsel->flag & SELECT) break;
1384 parsel= parsel->parent;
1388 base->flag &= ~SELECT;
1389 base->flag |= BA_WAS_SEL;
1391 /* used for flush, depgraph will change recalcs if needed :) */
1392 ob->recalc |= OB_RECALC_OB;
1395 /* all recalc flags get flushed */
1396 DAG_scene_flush_update(G.scene);
1398 /* and we store them temporal in base (only used for transform code) */
1399 /* this because after doing updates, the object->recalc is cleared */
1400 for (base= FIRSTBASE; base; base= base->next) {
1401 if(base->object->recalc & OB_RECALC_OB)
1402 base->flag |= BA_HAS_RECALC_OB;
1403 if(base->object->recalc & OB_RECALC_DATA)
1404 base->flag |= BA_HAS_RECALC_DATA;
1408 static void clear_trans_object_base_flags(void)
1414 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
1415 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
1421 /* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
1422 /* note; transdata has been freed already! */
1423 void special_aftertrans_update(TransInfo *t)
1428 int cancelled= (t->state == TRANS_CANCEL);
1431 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
1432 allqueue(REDRAWBUTSEDIT, 0);
1434 else if( (t->flag & T_POSE) && t->poseobj) {
1438 bPoseChannel *pchan;
1443 if(cancelled) /* if cancelled we do the update always */
1444 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1445 else if(G.flags & G_RECORDKEYS) {
1450 act= ob->action= add_empty_action();
1452 set_pose_keys(ob); // sets chan->flag to POSE_KEY if bone selected
1453 for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
1454 if (pchan->flag & POSE_KEY){
1456 set_action_key(act, pchan, AC_QUAT_X, 1);
1457 set_action_key(act, pchan, AC_QUAT_Y, 1);
1458 set_action_key(act, pchan, AC_QUAT_Z, 1);
1459 set_action_key(act, pchan, AC_QUAT_W, 1);
1461 set_action_key(act, pchan, AC_SIZE_X, 1);
1462 set_action_key(act, pchan, AC_SIZE_Y, 1);
1463 set_action_key(act, pchan, AC_SIZE_Z, 1);
1465 set_action_key(act, pchan, AC_LOC_X, 1);
1466 set_action_key(act, pchan, AC_LOC_Y, 1);
1467 set_action_key(act, pchan, AC_LOC_Z, 1);
1471 remake_action_ipos (act);
1472 allspace(REMAKEIPO, 0);
1473 allqueue(REDRAWACTION, 0);
1474 allqueue(REDRAWIPO, 0);
1475 allqueue(REDRAWNLA, 0);
1477 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1479 else if(arm->flag & ARM_DELAYDEFORM) {
1480 /* old optimize trick... this enforces to bypass the depgraph */
1481 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1482 ob->recalc= 0; // is set on OK position already by recalcData()
1484 /* do not call DAG_object_flush_update always, we dont want actions to update, for inserting keys */
1486 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
1487 allqueue(REDRAWBUTSEDIT, 0);
1494 if(base->flag & BA_DO_IPO) redrawipo= 1;
1498 if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_RESET;
1500 /* Set autokey if necessary */
1501 if ((G.flags & G_RECORDKEYS) && (!cancelled) && (base->flag & SELECT)){
1503 insertkey(&base->object->id, OB_ROT_X);
1504 insertkey(&base->object->id, OB_ROT_Y);
1505 insertkey(&base->object->id, OB_ROT_Z);
1507 insertkey(&base->object->id, OB_LOC_X);
1508 insertkey(&base->object->id, OB_LOC_Y);
1509 insertkey(&base->object->id, OB_LOC_Z);
1511 insertkey(&base->object->id, OB_SIZE_X);
1512 insertkey(&base->object->id, OB_SIZE_Y);
1513 insertkey(&base->object->id, OB_SIZE_Z);
1515 remake_object_ipos (ob);
1516 allqueue(REDRAWIPO, 0);
1517 allspace(REMAKEIPO, 0);
1518 allqueue(REDRAWVIEW3D, 0);
1519 allqueue(REDRAWNLA, 0);
1527 clear_trans_object_base_flags();
1530 allqueue(REDRAWNLA, 0);
1531 allqueue(REDRAWACTION, 0);
1532 allqueue(REDRAWIPO, 0);
1535 reset_slowparents();
1537 /* note; should actually only be done for all objects when a lamp is moved... (ton) */
1538 if(G.vd->drawtype == OB_SHADED) reshadeall_displist();
1542 static void createTransObject(TransInfo *t)
1544 TransData *td = NULL;
1545 TransDataExtension *tx;
1551 set_trans_object_base_flags(t);
1554 for(base= FIRSTBASE; base; base= base->next) {
1555 if TESTBASELIB(base) {
1558 /* store ipo keys? */
1559 if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
1560 elems.first= elems.last= NULL;
1561 make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
1563 pushdata(&elems, sizeof(ListBase));
1565 for(ik= elems.first; ik; ik= ik->next) t->total++;
1567 if(elems.first==NULL) t->total++;
1576 /* clear here, main transform function escapes too */
1577 clear_trans_object_base_flags();
1581 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb");
1582 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension");
1584 for(base= FIRSTBASE; base; base= base->next) {
1585 if TESTBASELIB(base) {
1588 td->flag= TD_SELECTED;
1591 /* store ipo keys? */
1592 if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
1594 popfirst(&elems); // bring back pushed listbase
1600 base->flag |= BA_DO_IPO+BA_WAS_SEL;
1601 base->flag &= ~SELECT;
1604 set_no_parent_ipo(1);
1605 ipoflag= ob->ipoflag;
1606 ob->ipoflag &= ~OB_OFFS_OB;
1608 pushdata(ob->loc, 7*3*4); // tsk! tsk!
1610 for(ik= elems.first; ik; ik= ik->next) {
1612 /* weak... this doesn't correct for floating values, giving small errors */
1613 CFRA= (short)(ik->val/G.scene->r.framelen);
1616 ObjectToTransData(td, ob); // does where_is_object()
1618 td->flag= TD_SELECTED;
1620 td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
1621 /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
1622 ipokey_to_transdata(ik, td);
1626 if(ik->next) td->ext= tx; // prevent corrupting mem!
1628 free_ipokey(&elems);
1631 set_no_parent_ipo(0);
1633 CFRA= (short)cfraont;
1634 ob->ipoflag= ipoflag;
1636 where_is_object(ob); // restore
1639 ObjectToTransData(td, ob);
1647 ObjectToTransData(td, ob);
1657 void createTransData(TransInfo *t)
1661 if (t->context == CTX_TEXTURE) {
1662 t->flag |= T_TEXTURE;
1663 createTransTexspace(t);
1665 else if (t->context == CTX_EDGE) {
1669 if(t->data && t->flag & T_PROP_EDIT) {
1670 sort_trans_data(t); // makes selected become first in array
1671 set_prop_dist(t, 1);
1672 sort_trans_data_dist(t);
1675 else if (G.obedit) {
1677 if (G.obedit->type == OB_MESH) {
1678 createTransEditVerts(t);
1680 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
1681 createTransCurveVerts(t);
1683 else if (G.obedit->type==OB_LATTICE) {
1684 createTransLatticeVerts(t);
1686 else if (G.obedit->type==OB_MBALL) {
1687 createTransMBallVerts(t);
1689 else if (G.obedit->type==OB_ARMATURE) {
1690 createTransArmatureVerts(t);
1693 printf("not done yet! only have mesh surface curve\n");
1696 if(t->data && t->flag & T_PROP_EDIT) {
1697 if (ELEM(G.obedit->type, OB_CURVE, OB_MESH)) {
1698 sort_trans_data(t); // makes selected become first in array
1699 set_prop_dist(t, 0);
1700 sort_trans_data_dist(t);
1703 sort_trans_data(t); // makes selected become first in array
1704 set_prop_dist(t, 1);
1705 sort_trans_data_dist(t);
1710 /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
1711 if(t->mode==TFM_BONESIZE) {
1714 t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */
1717 else if (ob && (ob->flag & OB_POSEMODE)) {
1718 createTransPose(OBACT, t);
1720 else if (G.f & G_WEIGHTPAINT) {
1721 /* exception, we look for the one selected armature */
1723 for(base=FIRSTBASE; base; base= base->next) {
1724 if(TESTBASELIB(base)) {
1725 if(base->object->type==OB_ARMATURE)
1726 if(base->object->flag & OB_POSEMODE)
1731 createTransPose(base->object, t);
1735 createTransObject(t);
1736 t->flag |= T_OBJECT;
1739 if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp>1) {
1740 t->flag |= T_CAMERA;