Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #ifndef WIN32 00034 #include <unistd.h> 00035 #else 00036 #include <io.h> 00037 #endif 00038 #include <string.h> 00039 #include <math.h> 00040 00041 #include "DNA_anim_types.h" 00042 #include "DNA_armature_types.h" 00043 #include "DNA_lattice_types.h" 00044 #include "DNA_meta_types.h" 00045 #include "DNA_node_types.h" 00046 #include "DNA_screen_types.h" 00047 #include "DNA_space_types.h" 00048 #include "DNA_sequence_types.h" 00049 #include "DNA_view3d_types.h" 00050 #include "DNA_constraint_types.h" 00051 #include "DNA_scene_types.h" 00052 #include "DNA_meshdata_types.h" 00053 #include "DNA_gpencil_types.h" 00054 #include "DNA_movieclip_types.h" 00055 00056 #include "MEM_guardedalloc.h" 00057 00058 #include "BKE_action.h" 00059 #include "BKE_armature.h" 00060 #include "BKE_context.h" 00061 #include "BKE_curve.h" 00062 #include "BKE_constraint.h" 00063 #include "BKE_depsgraph.h" 00064 #include "BKE_fcurve.h" 00065 #include "BKE_gpencil.h" 00066 #include "BKE_global.h" 00067 #include "BKE_key.h" 00068 #include "BKE_main.h" 00069 #include "BKE_modifier.h" 00070 #include "BKE_nla.h" 00071 #include "BKE_object.h" 00072 #include "BKE_particle.h" 00073 #include "BKE_sequencer.h" 00074 #include "BKE_pointcache.h" 00075 #include "BKE_bmesh.h" 00076 #include "BKE_scene.h" 00077 #include "BKE_report.h" 00078 #include "BKE_tracking.h" 00079 #include "BKE_movieclip.h" 00080 #include "BKE_node.h" 00081 00082 00083 #include "ED_anim_api.h" 00084 #include "ED_armature.h" 00085 #include "ED_particle.h" 00086 #include "ED_image.h" 00087 #include "ED_keyframing.h" 00088 #include "ED_keyframes_edit.h" 00089 #include "ED_object.h" 00090 #include "ED_markers.h" 00091 #include "ED_mesh.h" 00092 #include "ED_node.h" 00093 #include "ED_types.h" 00094 #include "ED_uvedit.h" 00095 #include "ED_clip.h" 00096 #include "ED_util.h" /* for crazyspace correction */ 00097 00098 #include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */ 00099 #include "WM_types.h" 00100 00101 #include "UI_view2d.h" 00102 00103 #include "BLI_math.h" 00104 #include "BLI_blenlib.h" 00105 #include "BLI_editVert.h" 00106 #include "BLI_utildefines.h" 00107 00108 #include "RNA_access.h" 00109 00110 extern ListBase editelems; 00111 00112 #include "transform.h" 00113 00114 #include "BLO_sys_types.h" // for intptr_t support 00115 00116 /* local function prototype - for Object/Bone Constraints */ 00117 static short constraints_list_needinv(TransInfo *t, ListBase *list); 00118 00119 /* ************************** Functions *************************** */ 00120 00121 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail, TransData *temp) 00122 { 00123 TransData *ihead = head; 00124 TransData *itail = tail; 00125 *temp = *head; 00126 00127 while (head < tail) 00128 { 00129 if (t->flag & T_PROP_CONNECTED) { 00130 while ((tail->dist >= temp->dist) && (head < tail)) 00131 tail--; 00132 } 00133 else { 00134 while ((tail->rdist >= temp->rdist) && (head < tail)) 00135 tail--; 00136 } 00137 00138 if (head != tail) 00139 { 00140 *head = *tail; 00141 head++; 00142 } 00143 00144 if (t->flag & T_PROP_CONNECTED) { 00145 while ((head->dist <= temp->dist) && (head < tail)) 00146 head++; 00147 } 00148 else { 00149 while ((head->rdist <= temp->rdist) && (head < tail)) 00150 head++; 00151 } 00152 00153 if (head != tail) 00154 { 00155 *tail = *head; 00156 tail--; 00157 } 00158 } 00159 00160 *head = *temp; 00161 if (ihead < head) { 00162 qsort_trans_data(t, ihead, head-1, temp); 00163 } 00164 if (itail > head) { 00165 qsort_trans_data(t, head+1, itail, temp); 00166 } 00167 } 00168 00169 void sort_trans_data_dist(TransInfo *t) 00170 { 00171 TransData temp; 00172 TransData *start = t->data; 00173 int i = 1; 00174 00175 while(i < t->total && start->flag & TD_SELECTED) { 00176 start++; 00177 i++; 00178 } 00179 qsort_trans_data(t, start, t->data + t->total - 1, &temp); 00180 } 00181 00182 static void sort_trans_data(TransInfo *t) 00183 { 00184 TransData *sel, *unsel; 00185 TransData temp; 00186 unsel = t->data; 00187 sel = t->data; 00188 sel += t->total - 1; 00189 while (sel > unsel) { 00190 while (unsel->flag & TD_SELECTED) { 00191 unsel++; 00192 if (unsel == sel) { 00193 return; 00194 } 00195 } 00196 while (!(sel->flag & TD_SELECTED)) { 00197 sel--; 00198 if (unsel == sel) { 00199 return; 00200 } 00201 } 00202 temp = *unsel; 00203 *unsel = *sel; 00204 *sel = temp; 00205 sel--; 00206 unsel++; 00207 } 00208 } 00209 00210 /* distance calculated from not-selected vertex to nearest selected vertex 00211 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */ 00212 static void set_prop_dist(TransInfo *t, short with_dist) 00213 { 00214 TransData *tob; 00215 int a; 00216 00217 for(a=0, tob= t->data; a<t->total; a++, tob++) { 00218 00219 tob->rdist= 0.0f; // init, it was mallocced 00220 00221 if((tob->flag & TD_SELECTED)==0) { 00222 TransData *td; 00223 int i; 00224 float dist, vec[3]; 00225 00226 tob->rdist = -1.0f; // signal for next loop 00227 00228 for (i = 0, td= t->data; i < t->total; i++, td++) { 00229 if(td->flag & TD_SELECTED) { 00230 sub_v3_v3v3(vec, tob->center, td->center); 00231 mul_m3_v3(tob->mtx, vec); 00232 dist = normalize_v3(vec); 00233 if (tob->rdist == -1.0f) { 00234 tob->rdist = dist; 00235 } 00236 else if (dist < tob->rdist) { 00237 tob->rdist = dist; 00238 } 00239 } 00240 else break; // by definition transdata has selected items in beginning 00241 } 00242 if (with_dist) { 00243 tob->dist = tob->rdist; 00244 } 00245 } 00246 } 00247 } 00248 00249 /* ************************** CONVERSIONS ************************* */ 00250 00251 /* ********************* texture space ********* */ 00252 00253 static void createTransTexspace(TransInfo *t) 00254 { 00255 Scene *scene = t->scene; 00256 TransData *td; 00257 Object *ob; 00258 ID *id; 00259 short *texflag; 00260 00261 ob = OBACT; 00262 00263 if (ob == NULL) { // Shouldn't logically happen, but still... 00264 t->total = 0; 00265 return; 00266 } 00267 00268 id = ob->data; 00269 if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) { 00270 t->total = 0; 00271 return; 00272 } 00273 00274 t->total = 1; 00275 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace"); 00276 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace"); 00277 00278 td->flag= TD_SELECTED; 00279 copy_v3_v3(td->center, ob->obmat[3]); 00280 td->ob = ob; 00281 00282 copy_m3_m4(td->mtx, ob->obmat); 00283 copy_m3_m4(td->axismtx, ob->obmat); 00284 normalize_m3(td->axismtx); 00285 invert_m3_m3(td->smtx, td->mtx); 00286 00287 if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) { 00288 ob->dtx |= OB_TEXSPACE; 00289 *texflag &= ~AUTOSPACE; 00290 } 00291 00292 copy_v3_v3(td->iloc, td->loc); 00293 copy_v3_v3(td->ext->irot, td->ext->rot); 00294 copy_v3_v3(td->ext->isize, td->ext->size); 00295 } 00296 00297 /* ********************* edge (for crease) ***** */ 00298 00299 static void createTransEdge(TransInfo *t) 00300 { 00301 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh; 00302 TransData *td = NULL; 00303 EditEdge *eed; 00304 float mtx[3][3], smtx[3][3]; 00305 int count=0, countsel=0; 00306 int propmode = t->flag & T_PROP_EDIT; 00307 00308 for(eed= em->edges.first; eed; eed= eed->next) { 00309 if(eed->h==0) { 00310 if (eed->f & SELECT) countsel++; 00311 if (propmode) count++; 00312 } 00313 } 00314 00315 if (countsel == 0) 00316 return; 00317 00318 if(propmode) { 00319 t->total = count; 00320 } 00321 else { 00322 t->total = countsel; 00323 } 00324 00325 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease"); 00326 00327 copy_m3_m4(mtx, t->obedit->obmat); 00328 invert_m3_m3(smtx, mtx); 00329 00330 for(eed= em->edges.first; eed; eed= eed->next) { 00331 if(eed->h==0 && (eed->f & SELECT || propmode)) { 00332 /* need to set center for center calculations */ 00333 add_v3_v3v3(td->center, eed->v1->co, eed->v2->co); 00334 mul_v3_fl(td->center, 0.5f); 00335 00336 td->loc= NULL; 00337 if (eed->f & SELECT) 00338 td->flag= TD_SELECTED; 00339 else 00340 td->flag= 0; 00341 00342 00343 copy_m3_m3(td->smtx, smtx); 00344 copy_m3_m3(td->mtx, mtx); 00345 00346 td->ext = NULL; 00347 if (t->mode == TFM_BWEIGHT) { 00348 td->val = &(eed->bweight); 00349 td->ival = eed->bweight; 00350 } 00351 else { 00352 td->val = &(eed->crease); 00353 td->ival = eed->crease; 00354 } 00355 00356 td++; 00357 } 00358 } 00359 } 00360 00361 /* ********************* pose mode ************* */ 00362 00363 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan) 00364 { 00365 bConstraint *con= pchan->constraints.first; 00366 00367 for(;con; con= con->next) { 00368 if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0f)) { 00369 bKinematicConstraint *data= con->data; 00370 00371 if(data->tar==NULL) 00372 return data; 00373 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0) 00374 return data; 00375 } 00376 } 00377 return NULL; 00378 } 00379 00380 static short apply_targetless_ik(Object *ob) 00381 { 00382 bPoseChannel *pchan, *parchan, *chanlist[256]; 00383 bKinematicConstraint *data; 00384 int segcount, apply= 0; 00385 00386 /* now we got a difficult situation... we have to find the 00387 target-less IK pchans, and apply transformation to the all 00388 pchans that were in the chain */ 00389 00390 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { 00391 data= has_targetless_ik(pchan); 00392 if(data && (data->flag & CONSTRAINT_IK_AUTO)) { 00393 00394 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */ 00395 segcount= 0; 00396 00397 /* exclude tip from chain? */ 00398 if(!(data->flag & CONSTRAINT_IK_TIP)) 00399 parchan= pchan->parent; 00400 else 00401 parchan= pchan; 00402 00403 /* Find the chain's root & count the segments needed */ 00404 for (; parchan; parchan=parchan->parent){ 00405 chanlist[segcount]= parchan; 00406 segcount++; 00407 00408 if(segcount==data->rootbone || segcount>255) break; // 255 is weak 00409 } 00410 for(;segcount;segcount--) { 00411 Bone *bone; 00412 float rmat[4][4], tmat[4][4], imat[4][4]; 00413 00414 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */ 00415 /* we put in channel the entire result of rmat= (channel * constraint * IK) */ 00416 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */ 00417 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */ 00418 00419 parchan= chanlist[segcount-1]; 00420 bone= parchan->bone; 00421 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */ 00422 00423 if(parchan->parent) { 00424 Bone *parbone= parchan->parent->bone; 00425 float offs_bone[4][4]; 00426 00427 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */ 00428 copy_m4_m3(offs_bone, bone->bone_mat); 00429 00430 /* The bone's root offset (is in the parent's coordinate system) */ 00431 copy_v3_v3(offs_bone[3], bone->head); 00432 00433 /* Get the length translation of parent (length along y axis) */ 00434 offs_bone[3][1]+= parbone->length; 00435 00436 /* pose_mat(b-1) * offs_bone */ 00437 if(parchan->bone->flag & BONE_HINGE) { 00438 /* the rotation of the parent restposition */ 00439 copy_m4_m4(rmat, parbone->arm_mat); /* rmat used as temp */ 00440 00441 /* the location of actual parent transform */ 00442 copy_v3_v3(rmat[3], offs_bone[3]); 00443 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f; 00444 mul_m4_v3(parchan->parent->pose_mat, rmat[3]); 00445 00446 mult_m4_m4m4(tmat, rmat, offs_bone); 00447 } 00448 else if(parchan->bone->flag & BONE_NO_SCALE) { 00449 mult_m4_m4m4(tmat, parchan->parent->pose_mat, offs_bone); 00450 normalize_m4(tmat); 00451 } 00452 else 00453 mult_m4_m4m4(tmat, parchan->parent->pose_mat, offs_bone); 00454 00455 invert_m4_m4(imat, tmat); 00456 } 00457 else { 00458 copy_m4_m3(tmat, bone->bone_mat); 00459 00460 copy_v3_v3(tmat[3], bone->head); 00461 invert_m4_m4(imat, tmat); 00462 } 00463 /* result matrix */ 00464 mult_m4_m4m4(rmat, imat, parchan->pose_mat); 00465 00466 /* apply and decompose, doesn't work for constraints or non-uniform scale well */ 00467 { 00468 float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3]; 00469 00470 copy_m3_m4(rmat3, rmat); 00471 00472 /* rotation */ 00473 /* [#22409] is partially caused by this, as slight numeric error introduced during 00474 * the solving process leads to locked-axis values changing. However, we cannot modify 00475 * the values here, or else there are huge discreptancies between IK-solver (interactive) 00476 * and applied poses. 00477 */ 00478 if (parchan->rotmode > 0) 00479 mat3_to_eulO(parchan->eul, parchan->rotmode,rmat3); 00480 else if (parchan->rotmode == ROT_MODE_AXISANGLE) 00481 mat3_to_axis_angle(parchan->rotAxis, &parchan->rotAngle,rmat3); 00482 else 00483 mat3_to_quat(parchan->quat,rmat3); 00484 00485 /* for size, remove rotation */ 00486 /* causes problems with some constraints (so apply only if needed) */ 00487 if (data->flag & CONSTRAINT_IK_STRETCH) { 00488 if (parchan->rotmode > 0) 00489 eulO_to_mat3( qrmat,parchan->eul, parchan->rotmode); 00490 else if (parchan->rotmode == ROT_MODE_AXISANGLE) 00491 axis_angle_to_mat3( qrmat,parchan->rotAxis, parchan->rotAngle); 00492 else 00493 quat_to_mat3( qrmat,parchan->quat); 00494 00495 invert_m3_m3(imat3, qrmat); 00496 mul_m3_m3m3(smat, rmat3, imat3); 00497 mat3_to_size( parchan->size,smat); 00498 } 00499 00500 /* causes problems with some constraints (e.g. childof), so disable this */ 00501 /* as it is IK shouldn't affect location directly */ 00502 /* copy_v3_v3(parchan->loc, rmat[3]); */ 00503 } 00504 00505 } 00506 00507 apply= 1; 00508 data->flag &= ~CONSTRAINT_IK_AUTO; 00509 } 00510 } 00511 00512 return apply; 00513 } 00514 00515 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td) 00516 { 00517 Bone *bone= pchan->bone; 00518 float pmat[3][3], omat[3][3], bmat[3][3]; 00519 float cmat[3][3], tmat[3][3]; 00520 float vec[3]; 00521 00522 copy_v3_v3(vec, pchan->pose_mat[3]); 00523 copy_v3_v3(td->center, vec); 00524 00525 td->ob = ob; 00526 td->flag = TD_SELECTED; 00527 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) 00528 { 00529 td->flag |= TD_NOCENTER; 00530 } 00531 00532 if (bone->flag & BONE_TRANSFORM_CHILD) 00533 { 00534 td->flag |= TD_NOCENTER; 00535 td->flag |= TD_NO_LOC; 00536 } 00537 00538 td->protectflag= pchan->protectflag; 00539 00540 td->loc = pchan->loc; 00541 copy_v3_v3(td->iloc, pchan->loc); 00542 00543 td->ext->size= pchan->size; 00544 copy_v3_v3(td->ext->isize, pchan->size); 00545 00546 if (pchan->rotmode > 0) { 00547 td->ext->rot= pchan->eul; 00548 td->ext->rotAxis= NULL; 00549 td->ext->rotAngle= NULL; 00550 td->ext->quat= NULL; 00551 00552 copy_v3_v3(td->ext->irot, pchan->eul); 00553 } 00554 else if (pchan->rotmode == ROT_MODE_AXISANGLE) { 00555 td->ext->rot= NULL; 00556 td->ext->rotAxis= pchan->rotAxis; 00557 td->ext->rotAngle= &pchan->rotAngle; 00558 td->ext->quat= NULL; 00559 00560 td->ext->irotAngle= pchan->rotAngle; 00561 copy_v3_v3(td->ext->irotAxis, pchan->rotAxis); 00562 } 00563 else { 00564 td->ext->rot= NULL; 00565 td->ext->rotAxis= NULL; 00566 td->ext->rotAngle= NULL; 00567 td->ext->quat= pchan->quat; 00568 00569 copy_qt_qt(td->ext->iquat, pchan->quat); 00570 } 00571 td->ext->rotOrder= pchan->rotmode; 00572 00573 00574 /* proper way to get parent transform + own transform + constraints transform */ 00575 copy_m3_m4(omat, ob->obmat); 00576 00577 if (ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) 00578 unit_m3(bmat); 00579 else 00580 copy_m3_m3(bmat, pchan->bone->bone_mat); 00581 00582 if (pchan->parent) { 00583 if(pchan->bone->flag & BONE_HINGE) 00584 copy_m3_m4(pmat, pchan->parent->bone->arm_mat); 00585 else 00586 copy_m3_m4(pmat, pchan->parent->pose_mat); 00587 00588 if (constraints_list_needinv(t, &pchan->constraints)) { 00589 copy_m3_m4(tmat, pchan->constinv); 00590 invert_m3_m3(cmat, tmat); 00591 mul_serie_m3(td->mtx, bmat, pmat, omat, cmat, NULL,NULL,NULL,NULL); // dang mulserie swaps args 00592 } 00593 else 00594 mul_serie_m3(td->mtx, bmat, pmat, omat, NULL,NULL,NULL,NULL,NULL); // dang mulserie swaps args 00595 } 00596 else { 00597 if (constraints_list_needinv(t, &pchan->constraints)) { 00598 copy_m3_m4(tmat, pchan->constinv); 00599 invert_m3_m3(cmat, tmat); 00600 mul_serie_m3(td->mtx, bmat, omat, cmat, NULL,NULL,NULL,NULL,NULL); // dang mulserie swaps args 00601 } 00602 else 00603 mul_m3_m3m3(td->mtx, omat, bmat); // Mat3MulMat3 has swapped args! 00604 } 00605 00606 invert_m3_m3(td->smtx, td->mtx); 00607 00608 /* exceptional case: rotate the pose bone which also applies transformation 00609 * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */ 00610 if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) { 00611 if(pchan->parent) { 00612 /* same as td->smtx but without pchan->bone->bone_mat */ 00613 td->flag |= TD_PBONE_LOCAL_MTX_C; 00614 mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx); 00615 } 00616 else { 00617 td->flag |= TD_PBONE_LOCAL_MTX_P; 00618 } 00619 } 00620 00621 /* for axismat we use bone's own transform */ 00622 copy_m3_m4(pmat, pchan->pose_mat); 00623 mul_m3_m3m3(td->axismtx, omat, pmat); 00624 normalize_m3(td->axismtx); 00625 00626 if (t->mode==TFM_BONESIZE) { 00627 bArmature *arm= t->poseobj->data; 00628 00629 if(arm->drawtype==ARM_ENVELOPE) { 00630 td->loc= NULL; 00631 td->val= &bone->dist; 00632 td->ival= bone->dist; 00633 } 00634 else { 00635 // abusive storage of scale in the loc pointer :) 00636 td->loc= &bone->xwidth; 00637 copy_v3_v3(td->iloc, td->loc); 00638 td->val= NULL; 00639 } 00640 } 00641 00642 /* in this case we can do target-less IK grabbing */ 00643 if (t->mode==TFM_TRANSLATION) { 00644 bKinematicConstraint *data= has_targetless_ik(pchan); 00645 if(data) { 00646 if(data->flag & CONSTRAINT_IK_TIP) { 00647 copy_v3_v3(data->grabtarget, pchan->pose_tail); 00648 } 00649 else { 00650 copy_v3_v3(data->grabtarget, pchan->pose_head); 00651 } 00652 td->loc = data->grabtarget; 00653 copy_v3_v3(td->iloc, td->loc); 00654 data->flag |= CONSTRAINT_IK_AUTO; 00655 00656 /* only object matrix correction */ 00657 copy_m3_m3(td->mtx, omat); 00658 invert_m3_m3(td->smtx, td->mtx); 00659 } 00660 } 00661 00662 /* store reference to first constraint */ 00663 td->con= pchan->constraints.first; 00664 } 00665 00666 static void bone_children_clear_transflag(int mode, short around, ListBase *lb) 00667 { 00668 Bone *bone= lb->first; 00669 00670 for(;bone;bone= bone->next) { 00671 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED)) 00672 { 00673 bone->flag |= BONE_HINGE_CHILD_TRANSFORM; 00674 } 00675 else if (bone->flag & BONE_TRANSFORM && (mode == TFM_ROTATION || mode == TFM_TRACKBALL) && around == V3D_LOCAL) 00676 { 00677 bone->flag |= BONE_TRANSFORM_CHILD; 00678 } 00679 else 00680 { 00681 bone->flag &= ~BONE_TRANSFORM; 00682 } 00683 00684 bone_children_clear_transflag(mode, around, &bone->childbase); 00685 } 00686 } 00687 00688 /* sets transform flags in the bones 00689 * returns total number of bones with BONE_TRANSFORM */ 00690 int count_set_pose_transflags(int *out_mode, short around, Object *ob) 00691 { 00692 bArmature *arm= ob->data; 00693 bPoseChannel *pchan; 00694 Bone *bone; 00695 int mode = *out_mode; 00696 int hastranslation = 0; 00697 int total = 0; 00698 00699 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { 00700 bone = pchan->bone; 00701 if (PBONE_VISIBLE(arm, bone)) { 00702 if ((bone->flag & BONE_SELECTED)) 00703 bone->flag |= BONE_TRANSFORM; 00704 else 00705 bone->flag &= ~BONE_TRANSFORM; 00706 00707 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM; 00708 bone->flag &= ~BONE_TRANSFORM_CHILD; 00709 } 00710 else 00711 bone->flag &= ~BONE_TRANSFORM; 00712 } 00713 00714 /* make sure no bone can be transformed when a parent is transformed */ 00715 /* since pchans are depsgraph sorted, the parents are in beginning of list */ 00716 if(mode != TFM_BONESIZE) { 00717 for(pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { 00718 bone = pchan->bone; 00719 if(bone->flag & BONE_TRANSFORM) 00720 bone_children_clear_transflag(mode, around, &bone->childbase); 00721 } 00722 } 00723 /* now count, and check if we have autoIK or have to switch from translate to rotate */ 00724 hastranslation = 0; 00725 00726 for(pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { 00727 bone = pchan->bone; 00728 if(bone->flag & BONE_TRANSFORM) { 00729 total++; 00730 00731 if(mode == TFM_TRANSLATION) { 00732 if( has_targetless_ik(pchan)==NULL ) { 00733 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) { 00734 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM) 00735 hastranslation = 1; 00736 } 00737 else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC) 00738 hastranslation = 1; 00739 } 00740 else 00741 hastranslation = 1; 00742 } 00743 } 00744 } 00745 00746 /* if there are no translatable bones, do rotation */ 00747 if(mode == TFM_TRANSLATION && !hastranslation) 00748 { 00749 *out_mode = TFM_ROTATION; 00750 } 00751 00752 return total; 00753 } 00754 00755 00756 /* -------- Auto-IK ---------- */ 00757 00758 /* adjust pose-channel's auto-ik chainlen */ 00759 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen) 00760 { 00761 bConstraint *con; 00762 00763 /* don't bother to search if no valid constraints */ 00764 if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0) 00765 return; 00766 00767 /* check if pchan has ik-constraint */ 00768 for (con= pchan->constraints.first; con; con= con->next) { 00769 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0f)) { 00770 bKinematicConstraint *data= con->data; 00771 00772 /* only accept if a temporary one (for auto-ik) */ 00773 if (data->flag & CONSTRAINT_IK_TEMP) { 00774 /* chainlen is new chainlen, but is limited by maximum chainlen */ 00775 if ((chainlen==0) || (chainlen > data->max_rootbone)) 00776 data->rootbone= data->max_rootbone; 00777 else 00778 data->rootbone= chainlen; 00779 } 00780 } 00781 } 00782 } 00783 00784 /* change the chain-length of auto-ik */ 00785 void transform_autoik_update (TransInfo *t, short mode) 00786 { 00787 short *chainlen= &t->settings->autoik_chainlen; 00788 bPoseChannel *pchan; 00789 00790 /* mode determines what change to apply to chainlen */ 00791 if (mode == 1) { 00792 /* mode=1 is from WHEELMOUSEDOWN... increases len */ 00793 (*chainlen)++; 00794 } 00795 else if (mode == -1) { 00796 /* mode==-1 is from WHEELMOUSEUP... decreases len */ 00797 if (*chainlen > 0) (*chainlen)--; 00798 } 00799 00800 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */ 00801 if (ELEM(NULL, t->poseobj, t->poseobj->pose)) 00802 return; 00803 00804 /* apply to all pose-channels */ 00805 for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) { 00806 pchan_autoik_adjust(pchan, *chainlen); 00807 } 00808 } 00809 00810 /* frees temporal IKs */ 00811 static void pose_grab_with_ik_clear(Object *ob) 00812 { 00813 bKinematicConstraint *data; 00814 bPoseChannel *pchan; 00815 bConstraint *con, *next; 00816 00817 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 00818 /* clear all temporary lock flags */ 00819 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP); 00820 00821 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET); 00822 00823 /* remove all temporary IK-constraints added */ 00824 for (con= pchan->constraints.first; con; con= next) { 00825 next= con->next; 00826 if (con->type==CONSTRAINT_TYPE_KINEMATIC) { 00827 data= con->data; 00828 if (data->flag & CONSTRAINT_IK_TEMP) { 00829 BLI_remlink(&pchan->constraints, con); 00830 MEM_freeN(con->data); 00831 MEM_freeN(con); 00832 continue; 00833 } 00834 pchan->constflag |= PCHAN_HAS_IK; 00835 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) 00836 pchan->constflag |= PCHAN_HAS_TARGET; 00837 } 00838 } 00839 } 00840 } 00841 00842 /* adds the IK to pchan - returns if added */ 00843 static short pose_grab_with_ik_add(bPoseChannel *pchan) 00844 { 00845 bKinematicConstraint *targetless = NULL; 00846 bKinematicConstraint *data; 00847 bConstraint *con; 00848 00849 /* Sanity check */ 00850 if (pchan == NULL) 00851 return 0; 00852 00853 /* Rule: not if there's already an IK on this channel */ 00854 for (con= pchan->constraints.first; con; con= con->next) { 00855 if (con->type==CONSTRAINT_TYPE_KINEMATIC) { 00856 data= con->data; 00857 00858 if (data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]=='\0')) { 00859 /* make reference to constraint to base things off later (if it's the last targetless constraint encountered) */ 00860 targetless = (bKinematicConstraint *)con->data; 00861 00862 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */ 00863 if (con->enforce!=0.0f) { 00864 data->flag |= CONSTRAINT_IK_AUTO; 00865 00866 /* if no chain length has been specified, just make things obey standard rotation locks too */ 00867 if (data->rootbone == 0) { 00868 for (; pchan; pchan=pchan->parent) { 00869 /* here, we set ik-settings for bone from pchan->protectflag */ 00870 // XXX: careful with quats/axis-angle rotations where we're locking 4d components 00871 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP; 00872 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP; 00873 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP; 00874 } 00875 } 00876 00877 return 0; 00878 } 00879 } 00880 00881 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0f)) 00882 return 0; 00883 } 00884 } 00885 00886 con = add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC); 00887 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */ 00888 data= con->data; 00889 if (targetless) { 00890 /* if exists, use values from last targetless (but disabled) IK-constraint as base */ 00891 *data = *targetless; 00892 } 00893 else 00894 data->flag= CONSTRAINT_IK_TIP; 00895 data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO; 00896 copy_v3_v3(data->grabtarget, pchan->pose_tail); 00897 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] */ 00898 00899 /* we only include bones that are part of a continual connected chain */ 00900 while (pchan) { 00901 /* here, we set ik-settings for bone from pchan->protectflag */ 00902 // XXX: careful with quats/axis-angle rotations where we're locking 4d components 00903 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP; 00904 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP; 00905 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP; 00906 00907 /* now we count this pchan as being included */ 00908 data->rootbone++; 00909 00910 /* continue to parent, but only if we're connected to it */ 00911 if (pchan->bone->flag & BONE_CONNECTED) 00912 pchan = pchan->parent; 00913 else 00914 pchan = NULL; 00915 } 00916 00917 /* make a copy of maximum chain-length */ 00918 data->max_rootbone= data->rootbone; 00919 00920 return 1; 00921 } 00922 00923 /* bone is a candidate to get IK, but we don't do it if it has children connected */ 00924 static short pose_grab_with_ik_children(bPose *pose, Bone *bone) 00925 { 00926 Bone *bonec; 00927 short wentdeeper=0, added=0; 00928 00929 /* go deeper if children & children are connected */ 00930 for (bonec= bone->childbase.first; bonec; bonec= bonec->next) { 00931 if (bonec->flag & BONE_CONNECTED) { 00932 wentdeeper= 1; 00933 added+= pose_grab_with_ik_children(pose, bonec); 00934 } 00935 } 00936 if (wentdeeper==0) { 00937 bPoseChannel *pchan= get_pose_channel(pose, bone->name); 00938 if (pchan) 00939 added+= pose_grab_with_ik_add(pchan); 00940 } 00941 00942 return added; 00943 } 00944 00945 /* main call which adds temporal IK chains */ 00946 static short pose_grab_with_ik(Object *ob) 00947 { 00948 bArmature *arm; 00949 bPoseChannel *pchan, *parent; 00950 Bone *bonec; 00951 short tot_ik= 0; 00952 00953 if ((ob==NULL) || (ob->pose==NULL) || (ob->mode & OB_MODE_POSE)==0) 00954 return 0; 00955 00956 arm = ob->data; 00957 00958 /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */ 00959 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 00960 if (pchan->bone->layer & arm->layer) { 00961 if (pchan->bone->flag & BONE_SELECTED) { 00962 /* Rule: no IK for solitatry (unconnected) bones */ 00963 for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) { 00964 if (bonec->flag & BONE_CONNECTED) { 00965 break; 00966 } 00967 } 00968 if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL)) 00969 continue; 00970 00971 /* rule: if selected Bone is not a root bone, it gets a temporal IK */ 00972 if (pchan->parent) { 00973 /* only adds if there's no IK yet (and no parent bone was selected) */ 00974 for (parent= pchan->parent; parent; parent= parent->parent) { 00975 if (parent->bone->flag & BONE_SELECTED) 00976 break; 00977 } 00978 if (parent == NULL) 00979 tot_ik += pose_grab_with_ik_add(pchan); 00980 } 00981 else { 00982 /* rule: go over the children and add IK to the tips */ 00983 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone); 00984 } 00985 } 00986 } 00987 } 00988 00989 return (tot_ik) ? 1 : 0; 00990 } 00991 00992 00993 /* only called with pose mode active object now */ 00994 static void createTransPose(TransInfo *t, Object *ob) 00995 { 00996 bArmature *arm; 00997 bPoseChannel *pchan; 00998 TransData *td; 00999 TransDataExtension *tdx; 01000 short ik_on= 0; 01001 int i; 01002 01003 t->total= 0; 01004 01005 /* check validity of state */ 01006 arm= get_armature(ob); 01007 if ((arm==NULL) || (ob->pose==NULL)) return; 01008 01009 if (arm->flag & ARM_RESTPOS) { 01010 if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) { 01011 // XXX use transform operator reports 01012 // BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled"); 01013 return; 01014 } 01015 } 01016 01017 /* do we need to add temporal IK chains? */ 01018 if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) { 01019 ik_on= pose_grab_with_ik(ob); 01020 if (ik_on) t->flag |= T_AUTOIK; 01021 } 01022 01023 /* set flags and count total (warning, can change transform to rotate) */ 01024 t->total = count_set_pose_transflags(&t->mode, t->around, ob); 01025 01026 if(t->total == 0) return; 01027 01028 t->flag |= T_POSE; 01029 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */ 01030 01031 /* init trans data */ 01032 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone"); 01033 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt"); 01034 for(i=0; i<t->total; i++, td++, tdx++) { 01035 td->ext= tdx; 01036 td->val = NULL; 01037 } 01038 01039 /* use pose channels to fill trans data */ 01040 td= t->data; 01041 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 01042 if (pchan->bone->flag & BONE_TRANSFORM) { 01043 add_pose_transdata(t, pchan, ob, td); 01044 td++; 01045 } 01046 } 01047 01048 if(td != (t->data+t->total)) { 01049 // XXX use transform operator reports 01050 // BKE_report(op->reports, RPT_DEBUG, "Bone selection count error"); 01051 } 01052 01053 /* initialise initial auto=ik chainlen's? */ 01054 if (ik_on) transform_autoik_update(t, 0); 01055 } 01056 01057 /* ********************* armature ************** */ 01058 01059 static void createTransArmatureVerts(TransInfo *t) 01060 { 01061 EditBone *ebo; 01062 bArmature *arm= t->obedit->data; 01063 ListBase *edbo = arm->edbo; 01064 TransData *td; 01065 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3]; 01066 01067 /* special hack for envelope drawmode and scaling: 01068 * to allow scaling the size of the envelope around single points, 01069 * mode should become TFM_BONE_ENVELOPE in this case 01070 */ 01071 // TODO: maybe we need a separate hotkey for it, but this is consistent with 2.4x for now 01072 if ((t->mode == TFM_RESIZE) && (arm->drawtype==ARM_ENVELOPE)) 01073 t->mode= TFM_BONE_ENVELOPE; 01074 01075 t->total = 0; 01076 for (ebo = edbo->first; ebo; ebo = ebo->next) 01077 { 01078 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) 01079 { 01080 if (t->mode==TFM_BONESIZE) 01081 { 01082 if (ebo->flag & BONE_SELECTED) 01083 t->total++; 01084 } 01085 else if (t->mode==TFM_BONE_ROLL) 01086 { 01087 if (ebo->flag & BONE_SELECTED) 01088 t->total++; 01089 } 01090 else 01091 { 01092 if (ebo->flag & BONE_TIPSEL) 01093 t->total++; 01094 if (ebo->flag & BONE_ROOTSEL) 01095 t->total++; 01096 } 01097 } 01098 } 01099 01100 if (!t->total) return; 01101 01102 copy_m3_m4(mtx, t->obedit->obmat); 01103 invert_m3_m3(smtx, mtx); 01104 01105 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone"); 01106 01107 for (ebo = edbo->first; ebo; ebo = ebo->next) 01108 { 01109 ebo->oldlength = ebo->length; // length==0.0 on extrude, used for scaling radius of bone points 01110 01111 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) 01112 { 01113 if (t->mode==TFM_BONE_ENVELOPE) 01114 { 01115 if (ebo->flag & BONE_ROOTSEL) 01116 { 01117 td->val= &ebo->rad_head; 01118 td->ival= *td->val; 01119 01120 copy_v3_v3(td->center, ebo->head); 01121 td->flag= TD_SELECTED; 01122 01123 copy_m3_m3(td->smtx, smtx); 01124 copy_m3_m3(td->mtx, mtx); 01125 01126 td->loc = NULL; 01127 td->ext = NULL; 01128 td->ob = t->obedit; 01129 01130 td++; 01131 } 01132 if (ebo->flag & BONE_TIPSEL) 01133 { 01134 td->val= &ebo->rad_tail; 01135 td->ival= *td->val; 01136 copy_v3_v3(td->center, ebo->tail); 01137 td->flag= TD_SELECTED; 01138 01139 copy_m3_m3(td->smtx, smtx); 01140 copy_m3_m3(td->mtx, mtx); 01141 01142 td->loc = NULL; 01143 td->ext = NULL; 01144 td->ob = t->obedit; 01145 01146 td++; 01147 } 01148 01149 } 01150 else if (t->mode==TFM_BONESIZE) 01151 { 01152 if (ebo->flag & BONE_SELECTED) { 01153 if(arm->drawtype==ARM_ENVELOPE) 01154 { 01155 td->loc= NULL; 01156 td->val= &ebo->dist; 01157 td->ival= ebo->dist; 01158 } 01159 else 01160 { 01161 // abusive storage of scale in the loc pointer :) 01162 td->loc= &ebo->xwidth; 01163 copy_v3_v3(td->iloc, td->loc); 01164 td->val= NULL; 01165 } 01166 copy_v3_v3(td->center, ebo->head); 01167 td->flag= TD_SELECTED; 01168 01169 /* use local bone matrix */ 01170 sub_v3_v3v3(delta, ebo->tail, ebo->head); 01171 vec_roll_to_mat3(delta, ebo->roll, bonemat); 01172 mul_m3_m3m3(td->mtx, mtx, bonemat); 01173 invert_m3_m3(td->smtx, td->mtx); 01174 01175 copy_m3_m3(td->axismtx, td->mtx); 01176 normalize_m3(td->axismtx); 01177 01178 td->ext = NULL; 01179 td->ob = t->obedit; 01180 01181 td++; 01182 } 01183 } 01184 else if (t->mode==TFM_BONE_ROLL) 01185 { 01186 if (ebo->flag & BONE_SELECTED) 01187 { 01188 td->loc= NULL; 01189 td->val= &(ebo->roll); 01190 td->ival= ebo->roll; 01191 01192 copy_v3_v3(td->center, ebo->head); 01193 td->flag= TD_SELECTED; 01194 01195 td->ext = NULL; 01196 td->ob = t->obedit; 01197 01198 td++; 01199 } 01200 } 01201 else 01202 { 01203 if (ebo->flag & BONE_TIPSEL) 01204 { 01205 copy_v3_v3(td->iloc, ebo->tail); 01206 copy_v3_v3(td->center, (t->around==V3D_LOCAL) ? ebo->head : td->iloc); 01207 td->loc= ebo->tail; 01208 td->flag= TD_SELECTED; 01209 if (ebo->flag & BONE_EDITMODE_LOCKED) 01210 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE; 01211 01212 copy_m3_m3(td->smtx, smtx); 01213 copy_m3_m3(td->mtx, mtx); 01214 01215 sub_v3_v3v3(delta, ebo->tail, ebo->head); 01216 vec_roll_to_mat3(delta, ebo->roll, td->axismtx); 01217 01218 if ((ebo->flag & BONE_ROOTSEL) == 0) 01219 { 01220 td->extra = ebo; 01221 } 01222 01223 td->ext = NULL; 01224 td->val = NULL; 01225 td->ob = t->obedit; 01226 01227 td++; 01228 } 01229 if (ebo->flag & BONE_ROOTSEL) 01230 { 01231 copy_v3_v3(td->iloc, ebo->head); 01232 copy_v3_v3(td->center, td->iloc); 01233 td->loc= ebo->head; 01234 td->flag= TD_SELECTED; 01235 if (ebo->flag & BONE_EDITMODE_LOCKED) 01236 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE; 01237 01238 copy_m3_m3(td->smtx, smtx); 01239 copy_m3_m3(td->mtx, mtx); 01240 01241 sub_v3_v3v3(delta, ebo->tail, ebo->head); 01242 vec_roll_to_mat3(delta, ebo->roll, td->axismtx); 01243 01244 td->extra = ebo; /* to fix roll */ 01245 01246 td->ext = NULL; 01247 td->val = NULL; 01248 td->ob = t->obedit; 01249 01250 td++; 01251 } 01252 } 01253 } 01254 } 01255 } 01256 01257 /* ********************* meta elements ********* */ 01258 01259 static void createTransMBallVerts(TransInfo *t) 01260 { 01261 MetaBall *mb = (MetaBall*)t->obedit->data; 01262 MetaElem *ml; 01263 TransData *td; 01264 TransDataExtension *tx; 01265 float mtx[3][3], smtx[3][3]; 01266 int count=0, countsel=0; 01267 int propmode = t->flag & T_PROP_EDIT; 01268 01269 /* count totals */ 01270 for(ml= mb->editelems->first; ml; ml= ml->next) { 01271 if(ml->flag & SELECT) countsel++; 01272 if(propmode) count++; 01273 } 01274 01275 /* note: in prop mode we need at least 1 selected */ 01276 if (countsel==0) return; 01277 01278 if(propmode) t->total = count; 01279 else t->total = countsel; 01280 01281 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)"); 01282 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension"); 01283 01284 copy_m3_m4(mtx, t->obedit->obmat); 01285 invert_m3_m3(smtx, mtx); 01286 01287 for(ml= mb->editelems->first; ml; ml= ml->next) { 01288 if(propmode || (ml->flag & SELECT)) { 01289 td->loc= &ml->x; 01290 copy_v3_v3(td->iloc, td->loc); 01291 copy_v3_v3(td->center, td->loc); 01292 01293 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE; 01294 else td->flag= TD_USEQUAT; 01295 01296 copy_m3_m3(td->smtx, smtx); 01297 copy_m3_m3(td->mtx, mtx); 01298 01299 td->ext = tx; 01300 01301 /* Radius of MetaElem (mass of MetaElem influence) */ 01302 if(ml->flag & MB_SCALE_RAD){ 01303 td->val = &ml->rad; 01304 td->ival = ml->rad; 01305 } 01306 else{ 01307 td->val = &ml->s; 01308 td->ival = ml->s; 01309 } 01310 01311 /* expx/expy/expz determine "shape" of some MetaElem types */ 01312 tx->size = &ml->expx; 01313 tx->isize[0] = ml->expx; 01314 tx->isize[1] = ml->expy; 01315 tx->isize[2] = ml->expz; 01316 01317 /* quat is used for rotation of MetaElem */ 01318 tx->quat = ml->quat; 01319 copy_qt_qt(tx->iquat, ml->quat); 01320 01321 tx->rot = NULL; 01322 01323 td++; 01324 tx++; 01325 } 01326 } 01327 } 01328 01329 /* ********************* curve/surface ********* */ 01330 01331 static void calc_distanceCurveVerts(TransData *head, TransData *tail) 01332 { 01333 TransData *td, *td_near = NULL; 01334 for (td = head; td<=tail; td++) { 01335 if (td->flag & TD_SELECTED) { 01336 td_near = td; 01337 td->dist = 0.0f; 01338 } 01339 else if(td_near) { 01340 float dist; 01341 dist = len_v3v3(td_near->center, td->center); 01342 if (dist < (td-1)->dist) { 01343 td->dist = (td-1)->dist; 01344 } 01345 else { 01346 td->dist = dist; 01347 } 01348 } 01349 else { 01350 td->dist = MAXFLOAT; 01351 td->flag |= TD_NOTCONNECTED; 01352 } 01353 } 01354 td_near = NULL; 01355 for (td = tail; td>=head; td--) { 01356 if (td->flag & TD_SELECTED) { 01357 td_near = td; 01358 td->dist = 0.0f; 01359 } 01360 else if(td_near) { 01361 float dist; 01362 dist = len_v3v3(td_near->center, td->center); 01363 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) { 01364 td->flag &= ~TD_NOTCONNECTED; 01365 if (dist < (td+1)->dist) { 01366 td->dist = (td+1)->dist; 01367 } 01368 else { 01369 td->dist = dist; 01370 } 01371 } 01372 } 01373 } 01374 } 01375 01376 /* Utility function for getting the handle data from bezier's */ 01377 static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt) 01378 { 01379 TransDataCurveHandleFlags *hdata; 01380 td->flag |= TD_BEZTRIPLE; 01381 hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data"); 01382 hdata->ih1 = bezt->h1; 01383 hdata->h1 = &bezt->h1; 01384 hdata->ih2 = bezt->h2; /* incase the second is not selected */ 01385 hdata->h2 = &bezt->h2; 01386 return hdata; 01387 } 01388 01389 static void createTransCurveVerts(bContext *C, TransInfo *t) 01390 { 01391 Object *obedit= CTX_data_edit_object(C); 01392 Curve *cu= obedit->data; 01393 TransData *td = NULL; 01394 Nurb *nu; 01395 BezTriple *bezt; 01396 BPoint *bp; 01397 float mtx[3][3], smtx[3][3]; 01398 int a; 01399 int count=0, countsel=0; 01400 int propmode = t->flag & T_PROP_EDIT; 01401 short hide_handles = (cu->drawflag & CU_HIDE_HANDLES); 01402 ListBase *nurbs; 01403 01404 /* to be sure */ 01405 if(cu->editnurb==NULL) return; 01406 01407 /* count total of vertices, check identical as in 2nd loop for making transdata! */ 01408 nurbs= curve_editnurbs(cu); 01409 for(nu= nurbs->first; nu; nu= nu->next) { 01410 if(nu->type == CU_BEZIER) { 01411 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) { 01412 if(bezt->hide==0) { 01413 if (hide_handles) { 01414 if(bezt->f2 & SELECT) countsel+=3; 01415 if(propmode) count+= 3; 01416 } else { 01417 if(bezt->f1 & SELECT) countsel++; 01418 if(bezt->f2 & SELECT) countsel++; 01419 if(bezt->f3 & SELECT) countsel++; 01420 if(propmode) count+= 3; 01421 } 01422 } 01423 } 01424 } 01425 else { 01426 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) { 01427 if(bp->hide==0) { 01428 if(propmode) count++; 01429 if(bp->f1 & SELECT) countsel++; 01430 } 01431 } 01432 } 01433 } 01434 /* note: in prop mode we need at least 1 selected */ 01435 if (countsel==0) return; 01436 01437 if(propmode) t->total = count; 01438 else t->total = countsel; 01439 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)"); 01440 01441 copy_m3_m4(mtx, t->obedit->obmat); 01442 invert_m3_m3(smtx, mtx); 01443 01444 td = t->data; 01445 for(nu= nurbs->first; nu; nu= nu->next) { 01446 if(nu->type == CU_BEZIER) { 01447 TransData *head, *tail; 01448 head = tail = td; 01449 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) { 01450 if(bezt->hide==0) { 01451 TransDataCurveHandleFlags *hdata = NULL; 01452 01453 if( propmode || 01454 ((bezt->f2 & SELECT) && hide_handles) || 01455 ((bezt->f1 & SELECT) && hide_handles == 0) 01456 ) { 01457 copy_v3_v3(td->iloc, bezt->vec[0]); 01458 td->loc= bezt->vec[0]; 01459 copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1:0]); 01460 if (hide_handles) { 01461 if(bezt->f2 & SELECT) td->flag= TD_SELECTED; 01462 else td->flag= 0; 01463 } else { 01464 if(bezt->f1 & SELECT) td->flag= TD_SELECTED; 01465 else td->flag= 0; 01466 } 01467 td->ext = NULL; 01468 td->val = NULL; 01469 01470 hdata = initTransDataCurveHandles(td, bezt); 01471 01472 copy_m3_m3(td->smtx, smtx); 01473 copy_m3_m3(td->mtx, mtx); 01474 01475 td++; 01476 count++; 01477 tail++; 01478 } 01479 01480 /* This is the Curve Point, the other two are handles */ 01481 if(propmode || (bezt->f2 & SELECT)) { 01482 copy_v3_v3(td->iloc, bezt->vec[1]); 01483 td->loc= bezt->vec[1]; 01484 copy_v3_v3(td->center, td->loc); 01485 if(bezt->f2 & SELECT) td->flag= TD_SELECTED; 01486 else td->flag= 0; 01487 td->ext = NULL; 01488 01489 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */ 01490 td->val = &(bezt->radius); 01491 td->ival = bezt->radius; 01492 } else if (t->mode==TFM_TILT) { 01493 td->val = &(bezt->alfa); 01494 td->ival = bezt->alfa; 01495 } else { 01496 td->val = NULL; 01497 } 01498 01499 copy_m3_m3(td->smtx, smtx); 01500 copy_m3_m3(td->mtx, mtx); 01501 01502 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0) 01503 /* If the middle is selected but the sides arnt, this is needed */ 01504 if (hdata==NULL) { /* if the handle was not saved by the previous handle */ 01505 hdata = initTransDataCurveHandles(td, bezt); 01506 } 01507 01508 td++; 01509 count++; 01510 tail++; 01511 } 01512 if( propmode || 01513 ((bezt->f2 & SELECT) && hide_handles) || 01514 ((bezt->f3 & SELECT) && hide_handles == 0) 01515 ) { 01516 copy_v3_v3(td->iloc, bezt->vec[2]); 01517 td->loc= bezt->vec[2]; 01518 copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1:2]); 01519 if (hide_handles) { 01520 if(bezt->f2 & SELECT) td->flag= TD_SELECTED; 01521 else td->flag= 0; 01522 } else { 01523 if(bezt->f3 & SELECT) td->flag= TD_SELECTED; 01524 else td->flag= 0; 01525 } 01526 td->ext = NULL; 01527 td->val = NULL; 01528 01529 if (hdata==NULL) { /* if the handle was not saved by the previous handle */ 01530 hdata = initTransDataCurveHandles(td, bezt); 01531 } 01532 01533 copy_m3_m3(td->smtx, smtx); 01534 copy_m3_m3(td->mtx, mtx); 01535 01536 td++; 01537 count++; 01538 tail++; 01539 } 01540 } 01541 else if (propmode && head != tail) { 01542 calc_distanceCurveVerts(head, tail-1); 01543 head = tail; 01544 } 01545 } 01546 if (propmode && head != tail) 01547 calc_distanceCurveVerts(head, tail-1); 01548 01549 /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles 01550 * but for now just dont change handle types */ 01551 if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0) { 01552 /* sets the handles based on their selection, do this after the data is copied to the TransData */ 01553 testhandlesNurb(nu); 01554 } 01555 } 01556 else { 01557 TransData *head, *tail; 01558 head = tail = td; 01559 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) { 01560 if(bp->hide==0) { 01561 if(propmode || (bp->f1 & SELECT)) { 01562 copy_v3_v3(td->iloc, bp->vec); 01563 td->loc= bp->vec; 01564 copy_v3_v3(td->center, td->loc); 01565 if(bp->f1 & SELECT) td->flag= TD_SELECTED; 01566 else td->flag= 0; 01567 td->ext = NULL; 01568 01569 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) { 01570 td->val = &(bp->radius); 01571 td->ival = bp->radius; 01572 } else { 01573 td->val = &(bp->alfa); 01574 td->ival = bp->alfa; 01575 } 01576 01577 copy_m3_m3(td->smtx, smtx); 01578 copy_m3_m3(td->mtx, mtx); 01579 01580 td++; 01581 count++; 01582 tail++; 01583 } 01584 } 01585 else if (propmode && head != tail) { 01586 calc_distanceCurveVerts(head, tail-1); 01587 head = tail; 01588 } 01589 } 01590 if (propmode && head != tail) 01591 calc_distanceCurveVerts(head, tail-1); 01592 } 01593 } 01594 } 01595 01596 /* ********************* lattice *************** */ 01597 01598 static void createTransLatticeVerts(TransInfo *t) 01599 { 01600 Lattice *latt = ((Lattice*)t->obedit->data)->editlatt->latt; 01601 TransData *td = NULL; 01602 BPoint *bp; 01603 float mtx[3][3], smtx[3][3]; 01604 int a; 01605 int count=0, countsel=0; 01606 int propmode = t->flag & T_PROP_EDIT; 01607 01608 bp = latt->def; 01609 a = latt->pntsu * latt->pntsv * latt->pntsw; 01610 while(a--) { 01611 if(bp->hide==0) { 01612 if(bp->f1 & SELECT) countsel++; 01613 if(propmode) count++; 01614 } 01615 bp++; 01616 } 01617 01618 /* note: in prop mode we need at least 1 selected */ 01619 if (countsel==0) return; 01620 01621 if(propmode) t->total = count; 01622 else t->total = countsel; 01623 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)"); 01624 01625 copy_m3_m4(mtx, t->obedit->obmat); 01626 invert_m3_m3(smtx, mtx); 01627 01628 td = t->data; 01629 bp = latt->def; 01630 a = latt->pntsu * latt->pntsv * latt->pntsw; 01631 while(a--) { 01632 if(propmode || (bp->f1 & SELECT)) { 01633 if(bp->hide==0) { 01634 copy_v3_v3(td->iloc, bp->vec); 01635 td->loc= bp->vec; 01636 copy_v3_v3(td->center, td->loc); 01637 if(bp->f1 & SELECT) td->flag= TD_SELECTED; 01638 else td->flag= 0; 01639 copy_m3_m3(td->smtx, smtx); 01640 copy_m3_m3(td->mtx, mtx); 01641 01642 td->ext = NULL; 01643 td->val = NULL; 01644 01645 td++; 01646 count++; 01647 } 01648 } 01649 bp++; 01650 } 01651 } 01652 01653 /* ******************* particle edit **************** */ 01654 static void createTransParticleVerts(bContext *C, TransInfo *t) 01655 { 01656 TransData *td = NULL; 01657 TransDataExtension *tx; 01658 Base *base = CTX_data_active_base(C); 01659 Object *ob = CTX_data_active_object(C); 01660 ParticleEditSettings *pset = PE_settings(t->scene); 01661 PTCacheEdit *edit = PE_get_current(t->scene, ob); 01662 ParticleSystem *psys = NULL; 01663 ParticleSystemModifierData *psmd = NULL; 01664 PTCacheEditPoint *point; 01665 PTCacheEditKey *key; 01666 float mat[4][4]; 01667 int i,k, transformparticle; 01668 int count = 0, hasselected = 0; 01669 int propmode = t->flag & T_PROP_EDIT; 01670 01671 if(edit==NULL || t->settings->particle.selectmode==SCE_SELECT_PATH) return; 01672 01673 psys = edit->psys; 01674 01675 if(psys) 01676 psmd = psys_get_modifier(ob,psys); 01677 01678 base->flag |= BA_HAS_RECALC_DATA; 01679 01680 for(i=0, point=edit->points; i<edit->totpoint; i++, point++) { 01681 point->flag &= ~PEP_TRANSFORM; 01682 transformparticle= 0; 01683 01684 if((point->flag & PEP_HIDE)==0) { 01685 for(k=0, key=point->keys; k<point->totkey; k++, key++) { 01686 if((key->flag&PEK_HIDE)==0) { 01687 if(key->flag&PEK_SELECT) { 01688 hasselected= 1; 01689 transformparticle= 1; 01690 } 01691 else if(propmode) 01692 transformparticle= 1; 01693 } 01694 } 01695 } 01696 01697 if(transformparticle) { 01698 count += point->totkey; 01699 point->flag |= PEP_TRANSFORM; 01700 } 01701 } 01702 01703 /* note: in prop mode we need at least 1 selected */ 01704 if (hasselected==0) return; 01705 01706 t->total = count; 01707 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)"); 01708 01709 if(t->mode == TFM_BAKE_TIME) 01710 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension"); 01711 else 01712 tx = t->ext = NULL; 01713 01714 unit_m4(mat); 01715 01716 invert_m4_m4(ob->imat,ob->obmat); 01717 01718 for(i=0, point=edit->points; i<edit->totpoint; i++, point++) { 01719 TransData *head, *tail; 01720 head = tail = td; 01721 01722 if(!(point->flag & PEP_TRANSFORM)) continue; 01723 01724 if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) 01725 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat); 01726 01727 for(k=0, key=point->keys; k<point->totkey; k++, key++) { 01728 if(key->flag & PEK_USE_WCO) { 01729 copy_v3_v3(key->world_co, key->co); 01730 mul_m4_v3(mat, key->world_co); 01731 td->loc = key->world_co; 01732 } 01733 else 01734 td->loc = key->co; 01735 01736 copy_v3_v3(td->iloc, td->loc); 01737 copy_v3_v3(td->center, td->loc); 01738 01739 if(key->flag & PEK_SELECT) 01740 td->flag |= TD_SELECTED; 01741 else if(!propmode) 01742 td->flag |= TD_SKIP; 01743 01744 unit_m3(td->mtx); 01745 unit_m3(td->smtx); 01746 01747 /* don't allow moving roots */ 01748 if(k==0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR))) 01749 td->protectflag |= OB_LOCK_LOC; 01750 01751 td->ob = ob; 01752 td->ext = tx; 01753 if(t->mode == TFM_BAKE_TIME) { 01754 td->val = key->time; 01755 td->ival = *(key->time); 01756 /* abuse size and quat for min/max values */ 01757 td->flag |= TD_NO_EXT; 01758 if(k==0) tx->size = NULL; 01759 else tx->size = (key - 1)->time; 01760 01761 if(k == point->totkey - 1) tx->quat = NULL; 01762 else tx->quat = (key + 1)->time; 01763 } 01764 01765 td++; 01766 if(tx) 01767 tx++; 01768 tail++; 01769 } 01770 if (propmode && head != tail) 01771 calc_distanceCurveVerts(head, tail - 1); 01772 } 01773 } 01774 01775 void flushTransParticles(TransInfo *t) 01776 { 01777 Scene *scene = t->scene; 01778 Object *ob = OBACT; 01779 PTCacheEdit *edit = PE_get_current(scene, ob); 01780 ParticleSystem *psys = edit->psys; 01781 ParticleSystemModifierData *psmd = NULL; 01782 PTCacheEditPoint *point; 01783 PTCacheEditKey *key; 01784 TransData *td; 01785 float mat[4][4], imat[4][4], co[3]; 01786 int i, k, propmode = t->flag & T_PROP_EDIT; 01787 01788 if(psys) 01789 psmd = psys_get_modifier(ob, psys); 01790 01791 /* we do transform in world space, so flush world space position 01792 * back to particle local space (only for hair particles) */ 01793 td= t->data; 01794 for(i=0, point=edit->points; i<edit->totpoint; i++, point++, td++) { 01795 if(!(point->flag & PEP_TRANSFORM)) continue; 01796 01797 if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) { 01798 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat); 01799 invert_m4_m4(imat,mat); 01800 01801 for(k=0, key=point->keys; k<point->totkey; k++, key++) { 01802 copy_v3_v3(co, key->world_co); 01803 mul_m4_v3(imat, co); 01804 01805 01806 /* optimization for proportional edit */ 01807 if(!propmode || !compare_v3v3(key->co, co, 0.0001f)) { 01808 copy_v3_v3(key->co, co); 01809 point->flag |= PEP_EDIT_RECALC; 01810 } 01811 } 01812 } 01813 else 01814 point->flag |= PEP_EDIT_RECALC; 01815 } 01816 01817 PE_update_object(scene, OBACT, 1); 01818 } 01819 01820 /* ********************* mesh ****************** */ 01821 01822 /* proportional distance based on connectivity */ 01823 #define THRESHOLDFACTOR (1.0f-0.0001f) 01824 01825 static int connectivity_edge(float mtx[][3], EditVert *v1, EditVert *v2) 01826 { 01827 float edge_vec[3]; 01828 float edge_len; 01829 int done = 0; 01830 01831 /* note: hidden verts are not being checked for, this assumes 01832 * flushing of hidden faces & edges is working right */ 01833 01834 if (v1->f2 + v2->f2 == 4) 01835 return 0; 01836 01837 sub_v3_v3v3(edge_vec, v1->co, v2->co); 01838 mul_m3_v3(mtx, edge_vec); 01839 01840 edge_len = len_v3(edge_vec); 01841 01842 if (v1->f2) { 01843 if (v2->f2) { 01844 if (v2->tmp.fp + edge_len < THRESHOLDFACTOR * v1->tmp.fp) { 01845 v1->tmp.fp = v2->tmp.fp + edge_len; 01846 done = 1; 01847 } else if (v1->tmp.fp + edge_len < THRESHOLDFACTOR * v2->tmp.fp) { 01848 v2->tmp.fp = v1->tmp.fp + edge_len; 01849 done = 1; 01850 } 01851 } 01852 else { 01853 v2->f2 = 1; 01854 v2->tmp.fp = v1->tmp.fp + edge_len; 01855 done = 1; 01856 } 01857 } 01858 else if (v2->f2) { 01859 v1->f2 = 1; 01860 v1->tmp.fp = v2->tmp.fp + edge_len; 01861 done = 1; 01862 } 01863 01864 return done; 01865 } 01866 01867 static void editmesh_set_connectivity_distance(EditMesh *em, float mtx[][3]) 01868 { 01869 EditVert *eve; 01870 EditEdge *eed; 01871 EditFace *efa; 01872 int done= 1; 01873 01874 /* f2 flag is used for 'selection' */ 01875 /* tmp.l is offset on scratch array */ 01876 for(eve= em->verts.first; eve; eve= eve->next) { 01877 if(eve->h==0) { 01878 eve->tmp.fp = 0; 01879 01880 if(eve->f & SELECT) { 01881 eve->f2= 2; 01882 } 01883 else { 01884 eve->f2 = 0; 01885 } 01886 } 01887 } 01888 01889 01890 /* Floodfill routine */ 01891 /* 01892 At worst this is n*n of complexity where n is number of edges 01893 Best case would be n if the list is ordered perfectly. 01894 Estimate is n log n in average (so not too bad) 01895 */ 01896 while(done) { 01897 done= 0; 01898 01899 for(eed= em->edges.first; eed; eed= eed->next) { 01900 if(eed->h==0) { 01901 done |= connectivity_edge(mtx, eed->v1, eed->v2); 01902 } 01903 } 01904 01905 /* do internal edges for quads */ 01906 for(efa= em->faces.first; efa; efa= efa->next) { 01907 if (efa->v4 && efa->h==0) { 01908 done |= connectivity_edge(mtx, efa->v1, efa->v3); 01909 done |= connectivity_edge(mtx, efa->v2, efa->v4); 01910 } 01911 } 01912 } 01913 } 01914 01915 /* loop-in-a-loop I know, but we need it! (ton) */ 01916 static void get_face_center(float *cent, EditMesh *em, EditVert *eve) 01917 { 01918 EditFace *efa; 01919 01920 for(efa= em->faces.first; efa; efa= efa->next) 01921 if(efa->f & SELECT) 01922 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve) 01923 break; 01924 if(efa) { 01925 copy_v3_v3(cent, efa->cent); 01926 } 01927 } 01928 01929 static void get_edge_center(float *cent, EditMesh *em, EditVert *eve) 01930 { 01931 EditEdge *eed; 01932 01933 for(eed= em->edges.first; eed; eed= eed->next) 01934 if(eed->f & SELECT) 01935 if(eed->v1==eve || eed->v2==eve) 01936 break; 01937 if(eed) { 01938 mid_v3_v3v3(cent, eed->v1->co, eed->v2->co); 01939 } 01940 } 01941 01942 /* way to overwrite what data is edited with transform 01943 * static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key) */ 01944 static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve) 01945 { 01946 td->flag = 0; 01947 //if(key) 01948 // td->loc = key->co; 01949 //else 01950 td->loc = eve->co; 01951 01952 copy_v3_v3(td->center, td->loc); 01953 if(t->around==V3D_LOCAL) { 01954 if(em->selectmode & SCE_SELECT_FACE) 01955 get_face_center(td->center, em, eve); 01956 else if(em->selectmode & SCE_SELECT_EDGE) 01957 get_edge_center(td->center, em, eve); 01958 } 01959 copy_v3_v3(td->iloc, td->loc); 01960 01961 // Setting normals 01962 copy_v3_v3(td->axismtx[2], eve->no); 01963 td->axismtx[0][0] = 01964 td->axismtx[0][1] = 01965 td->axismtx[0][2] = 01966 td->axismtx[1][0] = 01967 td->axismtx[1][1] = 01968 td->axismtx[1][2] = 0.0f; 01969 01970 td->ext = NULL; 01971 td->val = NULL; 01972 td->extra = NULL; 01973 if (t->mode == TFM_BWEIGHT) { 01974 td->val = &(eve->bweight); 01975 td->ival = eve->bweight; 01976 } 01977 } 01978 01979 static void createTransEditVerts(bContext *C, TransInfo *t) 01980 { 01981 ToolSettings *ts = CTX_data_tool_settings(C); 01982 TransData *tob = NULL; 01983 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh; 01984 EditVert *eve; 01985 EditVert *eve_act = NULL; 01986 float *mappedcos = NULL, *quats= NULL; 01987 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL; 01988 int count=0, countsel=0, a, totleft; 01989 int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) : 0; 01990 int mirror = 0; 01991 short selectmode = ts->selectmode; 01992 01993 if (t->flag & T_MIRROR) 01994 { 01995 mirror = 1; 01996 } 01997 01998 /* edge slide forces edge select */ 01999 if (t->mode == TFM_EDGE_SLIDE) { 02000 selectmode = SCE_SELECT_EDGE; 02001 } 02002 02003 // transform now requires awareness for select mode, so we tag the f1 flags in verts 02004 if(selectmode & SCE_SELECT_VERTEX) { 02005 for(eve= em->verts.first; eve; eve= eve->next) { 02006 if(eve->h==0 && (eve->f & SELECT)) 02007 eve->f1= SELECT; 02008 else 02009 eve->f1= 0; 02010 } 02011 } 02012 else if(selectmode & SCE_SELECT_EDGE) { 02013 EditEdge *eed; 02014 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; 02015 for(eed= em->edges.first; eed; eed= eed->next) { 02016 if(eed->h==0 && (eed->f & SELECT)) 02017 eed->v1->f1= eed->v2->f1= SELECT; 02018 } 02019 } 02020 else { 02021 EditFace *efa; 02022 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; 02023 for(efa= em->faces.first; efa; efa= efa->next) { 02024 if(efa->h==0 && (efa->f & SELECT)) { 02025 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT; 02026 if(efa->v4) efa->v4->f1= SELECT; 02027 } 02028 } 02029 } 02030 02031 /* now we can count */ 02032 for(eve= em->verts.first; eve; eve= eve->next) { 02033 if(eve->h==0) { 02034 if(eve->f1) countsel++; 02035 if(propmode) count++; 02036 } 02037 } 02038 02039 /* note: in prop mode we need at least 1 selected */ 02040 if (countsel==0) return; 02041 02042 /* check active */ 02043 if (em->selected.last) { 02044 EditSelection *ese = em->selected.last; 02045 if ( ese->type == EDITVERT ) { 02046 eve_act = (EditVert *)ese->data; 02047 } 02048 } 02049 02050 02051 if(propmode) t->total = count; 02052 else t->total = countsel; 02053 02054 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)"); 02055 02056 copy_m3_m4(mtx, t->obedit->obmat); 02057 invert_m3_m3(smtx, mtx); 02058 02059 if(propmode & T_PROP_CONNECTED) { 02060 editmesh_set_connectivity_distance(em, mtx); 02061 } 02062 02063 /* detect CrazySpace [tm] */ 02064 if(modifiers_getCageIndex(t->scene, t->obedit, NULL, 1)>=0) { 02065 if(modifiers_isCorrectableDeformed(t->obedit)) { 02066 /* check if we can use deform matrices for modifier from the 02067 start up to stack, they are more accurate than quats */ 02068 totleft= editmesh_get_first_deform_matrices(t->scene, t->obedit, em, &defmats, &defcos); 02069 02070 /* if we still have more modifiers, also do crazyspace 02071 correction with quats, relative to the coordinates after 02072 the modifiers that support deform matrices (defcos) */ 02073 if(totleft > 0) { 02074 mappedcos= crazyspace_get_mapped_editverts(t->scene, t->obedit); 02075 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats"); 02076 crazyspace_set_quats_editmesh(em, (float*)defcos, mappedcos, quats); 02077 if(mappedcos) 02078 MEM_freeN(mappedcos); 02079 } 02080 02081 if(defcos) 02082 MEM_freeN(defcos); 02083 } 02084 } 02085 02086 /* find out which half we do */ 02087 if(mirror) { 02088 for (eve=em->verts.first; eve; eve=eve->next) { 02089 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) { 02090 if(eve->co[0]<0.0f) 02091 { 02092 t->mirror = -1; 02093 mirror = -1; 02094 } 02095 break; 02096 } 02097 } 02098 } 02099 02100 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) { 02101 if(eve->h==0) { 02102 if(propmode || eve->f1) { 02103 VertsToTransData(t, tob, em, eve); 02104 02105 /* selected */ 02106 if(eve->f1) tob->flag |= TD_SELECTED; 02107 02108 /* active */ 02109 if(eve == eve_act) tob->flag |= TD_ACTIVE; 02110 02111 if(propmode) { 02112 if (eve->f2) { 02113 tob->dist= eve->tmp.fp; 02114 } 02115 else { 02116 tob->flag |= TD_NOTCONNECTED; 02117 tob->dist = MAXFLOAT; 02118 } 02119 } 02120 02121 /* CrazySpace */ 02122 if(defmats || (quats && eve->tmp.p)) { 02123 float mat[3][3], imat[3][3], qmat[3][3]; 02124 02125 /* use both or either quat and defmat correction */ 02126 if(quats && eve->tmp.f) { 02127 quat_to_mat3( qmat,eve->tmp.p); 02128 02129 if(defmats) 02130 mul_serie_m3(mat, mtx, qmat, defmats[a], 02131 NULL, NULL, NULL, NULL, NULL); 02132 else 02133 mul_m3_m3m3(mat, mtx, qmat); 02134 } 02135 else 02136 mul_m3_m3m3(mat, mtx, defmats[a]); 02137 02138 invert_m3_m3(imat, mat); 02139 02140 copy_m3_m3(tob->smtx, imat); 02141 copy_m3_m3(tob->mtx, mat); 02142 } 02143 else { 02144 copy_m3_m3(tob->smtx, smtx); 02145 copy_m3_m3(tob->mtx, mtx); 02146 } 02147 02148 /* Mirror? */ 02149 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) { 02150 EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, eve, tob->iloc, a); /* initializes octree on first call */ 02151 if(vmir != eve) { 02152 tob->extra = vmir; 02153 } 02154 } 02155 tob++; 02156 } 02157 } 02158 } 02159 02160 if (mirror != 0) 02161 { 02162 tob = t->data; 02163 for( a = 0; a < t->total; a++, tob++ ) 02164 { 02165 if (ABS(tob->loc[0]) <= 0.00001f) 02166 { 02167 tob->flag |= TD_MIRROR_EDGE; 02168 } 02169 } 02170 } 02171 02172 /* crazy space free */ 02173 if(quats) 02174 MEM_freeN(quats); 02175 if(defmats) 02176 MEM_freeN(defmats); 02177 } 02178 02179 /* *** NODE EDITOR *** */ 02180 void flushTransNodes(TransInfo *t) 02181 { 02182 int a; 02183 TransData2D *td; 02184 02185 /* flush to 2d vector from internally used 3d vector */ 02186 for(a=0, td= t->data2d; a<t->total; a++, td++) { 02187 td->loc2d[0]= td->loc[0]; 02188 td->loc2d[1]= td->loc[1]; 02189 } 02190 02191 /* handle intersection with noodles */ 02192 if(t->total==1) { 02193 ED_node_link_intersect_test(t->sa, 1); 02194 } 02195 02196 } 02197 02198 /* *** SEQUENCE EDITOR *** */ 02199 02200 /* commented _only_ because the meta may have animaion data which 02201 * needs moving too [#28158] */ 02202 02203 #define SEQ_TX_NESTED_METAS 02204 02205 void flushTransSeq(TransInfo *t) 02206 { 02207 ListBase *seqbasep= seq_give_editing(t->scene, FALSE)->seqbasep; /* Editing null check already done */ 02208 int a, new_frame, old_start; 02209 TransData *td= NULL; 02210 TransData2D *td2d= NULL; 02211 TransDataSeq *tdsq= NULL; 02212 Sequence *seq; 02213 02214 02215 02216 /* prevent updating the same seq twice 02217 * if the transdata order is changed this will mess up 02218 * but so will TransDataSeq */ 02219 Sequence *seq_prev= NULL; 02220 02221 /* flush to 2d vector from internally used 3d vector */ 02222 for(a=0, td= t->data, td2d= t->data2d; a<t->total; a++, td++, td2d++) { 02223 tdsq= (TransDataSeq *)td->extra; 02224 seq= tdsq->seq; 02225 old_start = seq->start; 02226 new_frame= (int)floor(td2d->loc[0] + 0.5f); 02227 02228 switch (tdsq->sel_flag) { 02229 case SELECT: 02230 #ifdef SEQ_TX_NESTED_METAS 02231 if ((seq->depth != 0 || seq_tx_test(seq))) /* for meta's, their children move */ 02232 seq->start= new_frame - tdsq->start_offset; 02233 #else 02234 if (seq->type != SEQ_META && (seq->depth != 0 || seq_tx_test(seq))) /* for meta's, their children move */ 02235 seq->start= new_frame - tdsq->start_offset; 02236 #endif 02237 if (seq->depth==0) { 02238 seq->machine= (int)floor(td2d->loc[1] + 0.5f); 02239 CLAMP(seq->machine, 1, MAXSEQ); 02240 } 02241 break; 02242 case SEQ_LEFTSEL: /* no vertical transform */ 02243 seq_tx_set_final_left(seq, new_frame); 02244 seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL); 02245 seq_single_fix(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */ 02246 break; 02247 case SEQ_RIGHTSEL: /* no vertical transform */ 02248 seq_tx_set_final_right(seq, new_frame); 02249 seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL); 02250 seq_single_fix(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */ 02251 break; 02252 } 02253 02254 if (seq != seq_prev) { 02255 if(seq->depth==0) { 02256 /* Calculate this strip and all nested strips 02257 * children are ALWAYS transformed first 02258 * so we dont need to do this in another loop. */ 02259 calc_sequence(t->scene, seq); 02260 } 02261 else { 02262 calc_sequence_disp(t->scene, seq); 02263 } 02264 02265 if(tdsq->sel_flag == SELECT) 02266 seq_offset_animdata(t->scene, seq, seq->start - old_start); 02267 } 02268 seq_prev= seq; 02269 } 02270 02271 /* need to do the overlap check in a new loop otherwise adjacent strips 02272 * will not be updated and we'll get false positives */ 02273 seq_prev= NULL; 02274 for(a=0, td= t->data, td2d= t->data2d; a<t->total; a++, td++, td2d++) { 02275 02276 tdsq= (TransDataSeq *)td->extra; 02277 seq= tdsq->seq; 02278 02279 if (seq != seq_prev) { 02280 if(seq->depth==0) { 02281 /* test overlap, displayes red outline */ 02282 seq->flag &= ~SEQ_OVERLAP; 02283 if( seq_test_overlap(seqbasep, seq) ) { 02284 seq->flag |= SEQ_OVERLAP; 02285 } 02286 } 02287 } 02288 seq_prev= seq; 02289 } 02290 02291 if (t->mode == TFM_SEQ_SLIDE) { /* originally TFM_TIME_EXTEND, transform changes */ 02292 /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */ 02293 seq= seqbasep->first; 02294 02295 while(seq) { 02296 if (seq->type == SEQ_META && seq->flag & SELECT) 02297 calc_sequence(t->scene, seq); 02298 seq= seq->next; 02299 } 02300 } 02301 } 02302 02303 /* ********************* UV ****************** */ 02304 02305 static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, float *uv, int selected) 02306 { 02307 float aspx, aspy; 02308 02309 ED_space_image_uv_aspect(sima, &aspx, &aspy); 02310 02311 /* uv coords are scaled by aspects. this is needed for rotations and 02312 proportional editing to be consistent with the stretchted uv coords 02313 that are displayed. this also means that for display and numinput, 02314 and when the the uv coords are flushed, these are converted each time */ 02315 td2d->loc[0] = uv[0]*aspx; 02316 td2d->loc[1] = uv[1]*aspy; 02317 td2d->loc[2] = 0.0f; 02318 td2d->loc2d = uv; 02319 02320 td->flag = 0; 02321 td->loc = td2d->loc; 02322 copy_v3_v3(td->center, td->loc); 02323 copy_v3_v3(td->iloc, td->loc); 02324 02325 memset(td->axismtx, 0, sizeof(td->axismtx)); 02326 td->axismtx[2][2] = 1.0f; 02327 02328 td->ext= NULL; td->val= NULL; 02329 02330 if(selected) { 02331 td->flag |= TD_SELECTED; 02332 td->dist= 0.0; 02333 } 02334 else { 02335 td->dist= MAXFLOAT; 02336 } 02337 unit_m3(td->mtx); 02338 unit_m3(td->smtx); 02339 } 02340 02341 static void createTransUVs(bContext *C, TransInfo *t) 02342 { 02343 SpaceImage *sima = CTX_wm_space_image(C); 02344 Image *ima = CTX_data_edit_image(C); 02345 Scene *scene = t->scene; 02346 TransData *td = NULL; 02347 TransData2D *td2d = NULL; 02348 MTFace *tf; 02349 int count=0, countsel=0; 02350 int propmode = t->flag & T_PROP_EDIT; 02351 02352 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh; 02353 EditFace *efa; 02354 02355 if(!ED_space_image_show_uvedit(sima, t->obedit)) return; 02356 02357 /* count */ 02358 for (efa= em->faces.first; efa; efa= efa->next) { 02359 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02360 02361 if(uvedit_face_visible(scene, ima, efa, tf)) { 02362 efa->tmp.p = tf; 02363 02364 if (uvedit_uv_selected(scene, efa, tf, 0)) countsel++; 02365 if (uvedit_uv_selected(scene, efa, tf, 1)) countsel++; 02366 if (uvedit_uv_selected(scene, efa, tf, 2)) countsel++; 02367 if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) countsel++; 02368 if(propmode) 02369 count += (efa->v4)? 4: 3; 02370 } else { 02371 efa->tmp.p = NULL; 02372 } 02373 } 02374 02375 /* note: in prop mode we need at least 1 selected */ 02376 if (countsel==0) return; 02377 02378 t->total= (propmode)? count: countsel; 02379 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)"); 02380 /* for each 2d uv coord a 3d vector is allocated, so that they can be 02381 treated just as if they were 3d verts */ 02382 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)"); 02383 02384 if(sima->flag & SI_CLIP_UV) 02385 t->flag |= T_CLIP_UV; 02386 02387 td= t->data; 02388 td2d= t->data2d; 02389 02390 for (efa= em->faces.first; efa; efa= efa->next) { 02391 if ((tf=(MTFace *)efa->tmp.p)) { 02392 if (propmode) { 02393 UVsToTransData(sima, td++, td2d++, tf->uv[0], uvedit_uv_selected(scene, efa, tf, 0)); 02394 UVsToTransData(sima, td++, td2d++, tf->uv[1], uvedit_uv_selected(scene, efa, tf, 1)); 02395 UVsToTransData(sima, td++, td2d++, tf->uv[2], uvedit_uv_selected(scene, efa, tf, 2)); 02396 if(efa->v4) 02397 UVsToTransData(sima, td++, td2d++, tf->uv[3], uvedit_uv_selected(scene, efa, tf, 3)); 02398 } else { 02399 if(uvedit_uv_selected(scene, efa, tf, 0)) UVsToTransData(sima, td++, td2d++, tf->uv[0], 1); 02400 if(uvedit_uv_selected(scene, efa, tf, 1)) UVsToTransData(sima, td++, td2d++, tf->uv[1], 1); 02401 if(uvedit_uv_selected(scene, efa, tf, 2)) UVsToTransData(sima, td++, td2d++, tf->uv[2], 1); 02402 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) UVsToTransData(sima, td++, td2d++, tf->uv[3], 1); 02403 } 02404 } 02405 } 02406 02407 if (sima->flag & SI_LIVE_UNWRAP) 02408 ED_uvedit_live_unwrap_begin(t->scene, t->obedit); 02409 } 02410 02411 void flushTransUVs(TransInfo *t) 02412 { 02413 SpaceImage *sima = t->sa->spacedata.first; 02414 TransData2D *td; 02415 int a, width, height; 02416 float aspx, aspy, invx, invy; 02417 02418 ED_space_image_uv_aspect(sima, &aspx, &aspy); 02419 ED_space_image_size(sima, &width, &height); 02420 invx= 1.0f/aspx; 02421 invy= 1.0f/aspy; 02422 02423 /* flush to 2d vector from internally used 3d vector */ 02424 for(a=0, td= t->data2d; a<t->total; a++, td++) { 02425 td->loc2d[0]= td->loc[0]*invx; 02426 td->loc2d[1]= td->loc[1]*invy; 02427 02428 if((sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) { 02429 td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width; 02430 td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height; 02431 } 02432 } 02433 } 02434 02435 int clipUVTransform(TransInfo *t, float *vec, int resize) 02436 { 02437 TransData *td; 02438 int a, clipx=1, clipy=1; 02439 float aspx, aspy, min[2], max[2]; 02440 02441 ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy); 02442 min[0]= min[1]= 0.0f; 02443 max[0]= aspx; max[1]= aspy; 02444 02445 for(a=0, td= t->data; a<t->total; a++, td++) { 02446 DO_MINMAX2(td->loc, min, max); 02447 } 02448 02449 if(resize) { 02450 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f) 02451 vec[0] *= t->center[0]/(t->center[0] - min[0]); 02452 else if(max[0] > aspx && t->center[0] < aspx) 02453 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]); 02454 else 02455 clipx= 0; 02456 02457 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f) 02458 vec[1] *= t->center[1]/(t->center[1] - min[1]); 02459 else if(max[1] > aspy && t->center[1] < aspy) 02460 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]); 02461 else 02462 clipy= 0; 02463 } 02464 else { 02465 if(min[0] < 0.0f) 02466 vec[0] -= min[0]; 02467 else if(max[0] > aspx) 02468 vec[0] -= max[0]-aspx; 02469 else 02470 clipx= 0; 02471 02472 if(min[1] < 0.0f) 02473 vec[1] -= min[1]; 02474 else if(max[1] > aspy) 02475 vec[1] -= max[1]-aspy; 02476 else 02477 clipy= 0; 02478 } 02479 02480 return (clipx || clipy); 02481 } 02482 02483 /* ********************* ANIMATION EDITORS (GENERAL) ************************* */ 02484 02485 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */ 02486 static short FrameOnMouseSide(char side, float frame, float cframe) 02487 { 02488 /* both sides, so it doesn't matter */ 02489 if (side == 'B') return 1; 02490 02491 /* only on the named side */ 02492 if (side == 'R') 02493 return (frame >= cframe) ? 1 : 0; 02494 else 02495 return (frame <= cframe) ? 1 : 0; 02496 } 02497 02498 /* ********************* NLA EDITOR ************************* */ 02499 02500 static void createTransNlaData(bContext *C, TransInfo *t) 02501 { 02502 Scene *scene= t->scene; 02503 SpaceNla *snla = NULL; 02504 TransData *td = NULL; 02505 TransDataNla *tdn = NULL; 02506 02507 bAnimContext ac; 02508 ListBase anim_data = {NULL, NULL}; 02509 bAnimListElem *ale; 02510 int filter; 02511 02512 int count=0; 02513 02514 /* determine what type of data we are operating on */ 02515 if (ANIM_animdata_get_context(C, &ac) == 0) 02516 return; 02517 snla = (SpaceNla *)ac.sl; 02518 02519 /* filter data */ 02520 filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); 02521 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 02522 02523 /* which side of the current frame should be allowed */ 02524 if (t->mode == TFM_TIME_EXTEND) { 02525 /* only side on which mouse is gets transformed */ 02526 float xmouse, ymouse; 02527 02528 UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse); 02529 t->frame_side= (xmouse > CFRA) ? 'R' : 'L'; 02530 } 02531 else { 02532 /* normal transform - both sides of current frame are considered */ 02533 t->frame_side = 'B'; 02534 } 02535 02536 /* loop 1: count how many strips are selected (consider each strip as 2 points) */ 02537 for (ale= anim_data.first; ale; ale= ale->next) { 02538 NlaTrack *nlt= (NlaTrack *)ale->data; 02539 NlaStrip *strip; 02540 02541 /* make some meta-strips for chains of selected strips */ 02542 BKE_nlastrips_make_metas(&nlt->strips, 1); 02543 02544 /* only consider selected strips */ 02545 for (strip= nlt->strips.first; strip; strip= strip->next) { 02546 // TODO: we can make strips have handles later on... 02547 /* transition strips can't get directly transformed */ 02548 if (strip->type != NLASTRIP_TYPE_TRANSITION) { 02549 if (strip->flag & NLASTRIP_FLAG_SELECT) { 02550 if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) count++; 02551 if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) count++; 02552 } 02553 } 02554 } 02555 } 02556 02557 /* stop if trying to build list if nothing selected */ 02558 if (count == 0) { 02559 /* cleanup temp list */ 02560 BLI_freelistN(&anim_data); 02561 return; 02562 } 02563 02564 /* allocate memory for data */ 02565 t->total= count; 02566 02567 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(NLA Editor)"); 02568 td= t->data; 02569 t->customData= MEM_callocN(t->total*sizeof(TransDataNla), "TransDataNla (NLA Editor)"); 02570 tdn= t->customData; 02571 02572 /* loop 2: build transdata array */ 02573 for (ale= anim_data.first; ale; ale= ale->next) { 02574 /* only if a real NLA-track */ 02575 if (ale->type == ANIMTYPE_NLATRACK) { 02576 AnimData *adt = ale->adt; 02577 NlaTrack *nlt= (NlaTrack *)ale->data; 02578 NlaStrip *strip; 02579 02580 /* only consider selected strips */ 02581 for (strip= nlt->strips.first; strip; strip= strip->next) { 02582 // TODO: we can make strips have handles later on... 02583 /* transition strips can't get directly transformed */ 02584 if (strip->type != NLASTRIP_TYPE_TRANSITION) { 02585 if (strip->flag & NLASTRIP_FLAG_SELECT) { 02586 /* our transform data is constructed as follows: 02587 * - only the handles on the right side of the current-frame get included 02588 * - td structs are transform-elements operated on by the transform system 02589 * and represent a single handle. The storage/pointer used (val or loc) depends on 02590 * whether we're scaling or transforming. Ultimately though, the handles 02591 * the td writes to will simply be a dummy in tdn 02592 * - for each strip being transformed, a single tdn struct is used, so in some 02593 * cases, there will need to be 1 of these tdn elements in the array skipped... 02594 */ 02595 float center[3], yval; 02596 02597 /* firstly, init tdn settings */ 02598 tdn->id= ale->id; 02599 tdn->oldTrack= tdn->nlt= nlt; 02600 tdn->strip= strip; 02601 tdn->trackIndex= BLI_findindex(&adt->nla_tracks, nlt); 02602 02603 yval= (float)(tdn->trackIndex * NLACHANNEL_STEP(snla)); 02604 02605 tdn->h1[0]= strip->start; 02606 tdn->h1[1]= yval; 02607 tdn->h2[0]= strip->end; 02608 tdn->h2[1]= yval; 02609 02610 center[0]= (float)CFRA; 02611 center[1]= yval; 02612 center[2]= 0.0f; 02613 02614 /* set td's based on which handles are applicable */ 02615 if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) 02616 { 02617 /* just set tdn to assume that it only has one handle for now */ 02618 tdn->handle= -1; 02619 02620 /* now, link the transform data up to this data */ 02621 if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) { 02622 td->loc= tdn->h1; 02623 copy_v3_v3(td->iloc, tdn->h1); 02624 02625 /* store all the other gunk that is required by transform */ 02626 copy_v3_v3(td->center, center); 02627 memset(td->axismtx, 0, sizeof(td->axismtx)); 02628 td->axismtx[2][2] = 1.0f; 02629 02630 td->ext= NULL; td->val= NULL; 02631 02632 td->flag |= TD_SELECTED; 02633 td->dist= 0.0f; 02634 02635 unit_m3(td->mtx); 02636 unit_m3(td->smtx); 02637 } 02638 else { 02639 /* time scaling only needs single value */ 02640 td->val= &tdn->h1[0]; 02641 td->ival= tdn->h1[0]; 02642 } 02643 02644 td->extra= tdn; 02645 td++; 02646 } 02647 if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) 02648 { 02649 /* if tdn is already holding the start handle, then we're doing both, otherwise, only end */ 02650 tdn->handle= (tdn->handle) ? 2 : 1; 02651 02652 /* now, link the transform data up to this data */ 02653 if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) { 02654 td->loc= tdn->h2; 02655 copy_v3_v3(td->iloc, tdn->h2); 02656 02657 /* store all the other gunk that is required by transform */ 02658 copy_v3_v3(td->center, center); 02659 memset(td->axismtx, 0, sizeof(td->axismtx)); 02660 td->axismtx[2][2] = 1.0f; 02661 02662 td->ext= NULL; td->val= NULL; 02663 02664 td->flag |= TD_SELECTED; 02665 td->dist= 0.0f; 02666 02667 unit_m3(td->mtx); 02668 unit_m3(td->smtx); 02669 } 02670 else { 02671 /* time scaling only needs single value */ 02672 td->val= &tdn->h2[0]; 02673 td->ival= tdn->h2[0]; 02674 } 02675 02676 td->extra= tdn; 02677 td++; 02678 } 02679 02680 /* if both handles were used, skip the next tdn (i.e. leave it blank) since the counting code is dumb... 02681 * otherwise, just advance to the next one... 02682 */ 02683 if (tdn->handle == 2) 02684 tdn += 2; 02685 else 02686 tdn++; 02687 } 02688 } 02689 } 02690 } 02691 } 02692 02693 /* cleanup temp list */ 02694 BLI_freelistN(&anim_data); 02695 } 02696 02697 /* ********************* ACTION EDITOR ****************** */ 02698 02699 /* Called by special_aftertrans_update to make sure selected gp-frames replace 02700 * any other gp-frames which may reside on that frame (that are not selected). 02701 * It also makes sure gp-frames are still stored in chronological order after 02702 * transform. 02703 */ 02704 static void posttrans_gpd_clean (bGPdata *gpd) 02705 { 02706 bGPDlayer *gpl; 02707 02708 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) { 02709 ListBase sel_buffer = {NULL, NULL}; 02710 bGPDframe *gpf, *gpfn; 02711 bGPDframe *gfs, *gfsn; 02712 02713 /* loop 1: loop through and isolate selected gp-frames to buffer 02714 * (these need to be sorted as they are isolated) 02715 */ 02716 for (gpf= gpl->frames.first; gpf; gpf= gpfn) { 02717 short added= 0; 02718 gpfn= gpf->next; 02719 02720 if (gpf->flag & GP_FRAME_SELECT) { 02721 BLI_remlink(&gpl->frames, gpf); 02722 02723 /* find place to add them in buffer 02724 * - go backwards as most frames will still be in order, 02725 * so doing it this way will be faster 02726 */ 02727 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) { 02728 /* if current (gpf) occurs after this one in buffer, add! */ 02729 if (gfs->framenum < gpf->framenum) { 02730 BLI_insertlinkafter(&sel_buffer, gfs, gpf); 02731 added= 1; 02732 break; 02733 } 02734 } 02735 if (added == 0) 02736 BLI_addhead(&sel_buffer, gpf); 02737 } 02738 } 02739 02740 /* error checking: it is unlikely, but may be possible to have none selected */ 02741 if (sel_buffer.first == NULL) 02742 continue; 02743 02744 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */ 02745 if (gpl->frames.first == NULL) { 02746 gpl->frames.first= sel_buffer.first; 02747 gpl->frames.last= sel_buffer.last; 02748 02749 continue; 02750 } 02751 02752 /* loop 2: remove duplicates of frames in buffers */ 02753 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) { 02754 gpfn= gpf->next; 02755 02756 /* loop through sel_buffer, emptying stuff from front of buffer if ok */ 02757 for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) { 02758 gfsn= gfs->next; 02759 02760 /* if this buffer frame needs to go before current, add it! */ 02761 if (gfs->framenum < gpf->framenum) { 02762 /* transfer buffer frame to frames list (before current) */ 02763 BLI_remlink(&sel_buffer, gfs); 02764 BLI_insertlinkbefore(&gpl->frames, gpf, gfs); 02765 } 02766 /* if this buffer frame is on same frame, replace current with it and stop */ 02767 else if (gfs->framenum == gpf->framenum) { 02768 /* transfer buffer frame to frames list (before current) */ 02769 BLI_remlink(&sel_buffer, gfs); 02770 BLI_insertlinkbefore(&gpl->frames, gpf, gfs); 02771 02772 /* get rid of current frame */ 02773 gpencil_layer_delframe(gpl, gpf); 02774 } 02775 } 02776 } 02777 02778 /* if anything is still in buffer, append to end */ 02779 for (gfs= sel_buffer.first; gfs; gfs= gfsn) { 02780 gfsn= gfs->next; 02781 02782 BLI_remlink(&sel_buffer, gfs); 02783 BLI_addtail(&gpl->frames, gfs); 02784 } 02785 } 02786 } 02787 02788 /* Called during special_aftertrans_update to make sure selected keyframes replace 02789 * any other keyframes which may reside on that frame (that is not selected). 02790 */ 02791 static void posttrans_fcurve_clean (FCurve *fcu, const short use_handle) 02792 { 02793 float *selcache; /* cache for frame numbers of selected frames (fcu->totvert*sizeof(float)) */ 02794 int len, index, i; /* number of frames in cache, item index */ 02795 02796 /* allocate memory for the cache */ 02797 // TODO: investigate using BezTriple columns instead? 02798 if (fcu->totvert == 0 || fcu->bezt==NULL) 02799 return; 02800 selcache= MEM_callocN(sizeof(float)*fcu->totvert, "FCurveSelFrameNums"); 02801 len= 0; 02802 index= 0; 02803 02804 /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting 02805 * as there is no guarantee what order the keyframes are exactly, even though 02806 * they have been sorted by time. 02807 */ 02808 02809 /* Loop 1: find selected keyframes */ 02810 for (i = 0; i < fcu->totvert; i++) { 02811 BezTriple *bezt= &fcu->bezt[i]; 02812 02813 if (BEZSELECTED(bezt)) { 02814 selcache[index]= bezt->vec[1][0]; 02815 index++; 02816 len++; 02817 } 02818 } 02819 02820 /* Loop 2: delete unselected keyframes on the same frames 02821 * (if any keyframes were found, or the whole curve wasn't affected) 02822 */ 02823 if ((len) && (len != fcu->totvert)) { 02824 for (i= fcu->totvert-1; i >= 0; i--) { 02825 BezTriple *bezt= &fcu->bezt[i]; 02826 02827 if (BEZSELECTED(bezt) == 0) { 02828 /* check beztriple should be removed according to cache */ 02829 for (index= 0; index < len; index++) { 02830 if (IS_EQF(bezt->vec[1][0], selcache[index])) { 02831 delete_fcurve_key(fcu, i, 0); 02832 break; 02833 } 02834 else if (bezt->vec[1][0] < selcache[index]) 02835 break; 02836 } 02837 } 02838 } 02839 02840 testhandles_fcurve(fcu, use_handle); 02841 } 02842 02843 /* free cache */ 02844 MEM_freeN(selcache); 02845 } 02846 02847 02848 02849 /* Called by special_aftertrans_update to make sure selected keyframes replace 02850 * any other keyframes which may reside on that frame (that is not selected). 02851 * remake_action_ipos should have already been called 02852 */ 02853 static void posttrans_action_clean (bAnimContext *ac, bAction *act) 02854 { 02855 ListBase anim_data = {NULL, NULL}; 02856 bAnimListElem *ale; 02857 int filter; 02858 02859 /* filter data */ 02860 filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/); 02861 ANIM_animdata_filter(ac, &anim_data, filter, act, ANIMCONT_ACTION); 02862 02863 /* loop through relevant data, removing keyframes as appropriate 02864 * - all keyframes are converted in/out of global time 02865 */ 02866 for (ale= anim_data.first; ale; ale= ale->next) { 02867 AnimData *adt= ANIM_nla_mapping_get(ac, ale); 02868 02869 if (adt) { 02870 ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); 02871 posttrans_fcurve_clean(ale->key_data, FALSE); /* only use handles in graph editor */ 02872 ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); 02873 } 02874 else 02875 posttrans_fcurve_clean(ale->key_data, FALSE); /* only use handles in graph editor */ 02876 } 02877 02878 /* free temp data */ 02879 BLI_freelistN(&anim_data); 02880 } 02881 02882 /* ----------------------------- */ 02883 02884 /* fully select selected beztriples, but only include if it's on the right side of cfra */ 02885 static int count_fcurve_keys(FCurve *fcu, char side, float cfra) 02886 { 02887 BezTriple *bezt; 02888 int i, count = 0; 02889 02890 if (ELEM(NULL, fcu, fcu->bezt)) 02891 return count; 02892 02893 /* only include points that occur on the right side of cfra */ 02894 for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) { 02895 if (bezt->f2 & SELECT) { 02896 /* no need to adjust the handle selection since they are assumed 02897 * selected (like graph editor with SIPO_NOHANDLES) */ 02898 if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { 02899 count += 1; 02900 } 02901 } 02902 } 02903 02904 return count; 02905 } 02906 02907 /* fully select selected beztriples, but only include if it's on the right side of cfra */ 02908 static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra) 02909 { 02910 bGPDframe *gpf; 02911 int count = 0; 02912 02913 if (gpl == NULL) 02914 return count; 02915 02916 /* only include points that occur on the right side of cfra */ 02917 for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { 02918 if (gpf->flag & GP_FRAME_SELECT) { 02919 if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) 02920 count++; 02921 } 02922 } 02923 02924 return count; 02925 } 02926 02927 /* This function assigns the information to transdata */ 02928 static void TimeToTransData(TransData *td, float *time, AnimData *adt) 02929 { 02930 /* memory is calloc'ed, so that should zero everything nicely for us */ 02931 td->val = time; 02932 td->ival = *(time); 02933 02934 /* store the AnimData where this keyframe exists as a keyframe of the 02935 * active action as td->extra. 02936 */ 02937 td->extra= adt; 02938 } 02939 02940 /* This function advances the address to which td points to, so it must return 02941 * the new address so that the next time new transform data is added, it doesn't 02942 * overwrite the existing ones... i.e. td = IcuToTransData(td, icu, ob, side, cfra); 02943 * 02944 * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data 02945 * on the named side are used. 02946 */ 02947 static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra) 02948 { 02949 BezTriple *bezt; 02950 TransData2D *td2d = *td2dv; 02951 int i; 02952 02953 if (ELEM(NULL, fcu, fcu->bezt)) 02954 return td; 02955 02956 for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) { 02957 /* only add selected keyframes (for now, proportional edit is not enabled) */ 02958 if (bezt->f2 & SELECT) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */ 02959 /* only add if on the right 'side' of the current frame */ 02960 if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { 02961 TimeToTransData(td, bezt->vec[1], adt); 02962 02963 /*set flags to move handles as necassary*/ 02964 td->flag |= TD_MOVEHANDLE1|TD_MOVEHANDLE2; 02965 td2d->h1 = bezt->vec[0]; 02966 td2d->h2 = bezt->vec[2]; 02967 02968 copy_v2_v2(td2d->ih1, td2d->h1); 02969 copy_v2_v2(td2d->ih2, td2d->h2); 02970 02971 td++; 02972 td2d++; 02973 } 02974 } 02975 } 02976 02977 *td2dv = td2d; 02978 02979 return td; 02980 } 02981 02982 /* helper struct for gp-frame transforms (only used here) */ 02983 typedef struct tGPFtransdata { 02984 float val; /* where transdata writes transform */ 02985 int *sdata; /* pointer to gpf->framenum */ 02986 } tGPFtransdata; 02987 02988 /* This function helps flush transdata written to tempdata into the gp-frames */ 02989 void flushTransGPactionData (TransInfo *t) 02990 { 02991 tGPFtransdata *tfd; 02992 int i; 02993 02994 /* find the first one to start from */ 02995 if (t->mode == TFM_TIME_SLIDE) 02996 tfd= (tGPFtransdata *)( (float *)(t->customData) + 2 ); 02997 else 02998 tfd= (tGPFtransdata *)(t->customData); 02999 03000 /* flush data! */ 03001 for (i = 0; i < t->total; i++, tfd++) { 03002 *(tfd->sdata)= (int)floor(tfd->val + 0.5f); 03003 } 03004 } 03005 03006 /* This function advances the address to which td points to, so it must return 03007 * the new address so that the next time new transform data is added, it doesn't 03008 * overwrite the existing ones... i.e. td = GPLayerToTransData(td, ipo, ob, side, cfra); 03009 * 03010 * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data 03011 * on the named side are used. 03012 */ 03013 static int GPLayerToTransData (TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra) 03014 { 03015 bGPDframe *gpf; 03016 int count= 0; 03017 03018 /* check for select frames on right side of current frame */ 03019 for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { 03020 if (gpf->flag & GP_FRAME_SELECT) { 03021 if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) { 03022 /* memory is calloc'ed, so that should zero everything nicely for us */ 03023 td->val= &tfd->val; 03024 td->ival= (float)gpf->framenum; 03025 03026 tfd->val= (float)gpf->framenum; 03027 tfd->sdata= &gpf->framenum; 03028 03029 /* advance td now */ 03030 td++; 03031 tfd++; 03032 count++; 03033 } 03034 } 03035 } 03036 03037 return count; 03038 } 03039 03040 static void createTransActionData(bContext *C, TransInfo *t) 03041 { 03042 Scene *scene= t->scene; 03043 TransData *td = NULL; 03044 TransData2D *td2d = NULL; 03045 tGPFtransdata *tfd = NULL; 03046 03047 bAnimContext ac; 03048 ListBase anim_data = {NULL, NULL}; 03049 bAnimListElem *ale; 03050 int filter; 03051 03052 int count=0; 03053 float cfra; 03054 03055 /* determine what type of data we are operating on */ 03056 if (ANIM_animdata_get_context(C, &ac) == 0) 03057 return; 03058 03059 /* filter data */ 03060 if (ac.datatype == ANIMCONT_GPENCIL) 03061 filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT); 03062 else 03063 filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/); 03064 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 03065 03066 /* which side of the current frame should be allowed */ 03067 if (t->mode == TFM_TIME_EXTEND) { 03068 /* only side on which mouse is gets transformed */ 03069 float xmouse, ymouse; 03070 03071 UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse); 03072 t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side 03073 } 03074 else { 03075 /* normal transform - both sides of current frame are considered */ 03076 t->frame_side = 'B'; 03077 } 03078 03079 /* loop 1: fully select ipo-keys and count how many BezTriples are selected */ 03080 for (ale= anim_data.first; ale; ale= ale->next) { 03081 AnimData *adt= ANIM_nla_mapping_get(&ac, ale); 03082 03083 /* convert current-frame to action-time (slightly less accurate, espcially under 03084 * higher scaling ratios, but is faster than converting all points) 03085 */ 03086 if (adt) 03087 cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); 03088 else 03089 cfra = (float)CFRA; 03090 03091 if (ale->type == ANIMTYPE_FCURVE) 03092 count += count_fcurve_keys(ale->key_data, t->frame_side, cfra); 03093 else 03094 count += count_gplayer_frames(ale->data, t->frame_side, cfra); 03095 } 03096 03097 /* stop if trying to build list if nothing selected */ 03098 if (count == 0) { 03099 /* cleanup temp list */ 03100 BLI_freelistN(&anim_data); 03101 return; 03102 } 03103 03104 /* allocate memory for data */ 03105 t->total= count; 03106 03107 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(Action Editor)"); 03108 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "transdata2d"); 03109 td= t->data; 03110 td2d = t->data2d; 03111 03112 if (ac.datatype == ANIMCONT_GPENCIL) { 03113 if (t->mode == TFM_TIME_SLIDE) { 03114 t->customData= MEM_callocN((sizeof(float)*2)+(sizeof(tGPFtransdata)*count), "TimeSlide + tGPFtransdata"); 03115 tfd= (tGPFtransdata *)( (float *)(t->customData) + 2 ); 03116 } 03117 else { 03118 t->customData= MEM_callocN(sizeof(tGPFtransdata)*count, "tGPFtransdata"); 03119 tfd= (tGPFtransdata *)(t->customData); 03120 } 03121 } 03122 else if (t->mode == TFM_TIME_SLIDE) 03123 t->customData= MEM_callocN(sizeof(float)*2, "TimeSlide Min/Max"); 03124 03125 /* loop 2: build transdata array */ 03126 for (ale= anim_data.first; ale; ale= ale->next) { 03127 if (ale->type == ANIMTYPE_GPLAYER) { 03128 bGPDlayer *gpl= (bGPDlayer *)ale->data; 03129 int i; 03130 03131 i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra); 03132 td += i; 03133 tfd += i; 03134 } 03135 else { 03136 AnimData *adt= ANIM_nla_mapping_get(&ac, ale); 03137 FCurve *fcu= (FCurve *)ale->key_data; 03138 03139 /* convert current-frame to action-time (slightly less accurate, espcially under 03140 * higher scaling ratios, but is faster than converting all points) 03141 */ 03142 if (adt) 03143 cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); 03144 else 03145 cfra = (float)CFRA; 03146 03147 td= ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra); 03148 } 03149 } 03150 03151 /* check if we're supposed to be setting minx/maxx for TimeSlide */ 03152 if (t->mode == TFM_TIME_SLIDE) { 03153 float min=999999999.0f, max=-999999999.0f; 03154 int i; 03155 03156 td= t->data; 03157 for (i=0; i < count; i++, td++) { 03158 if (min > *(td->val)) min= *(td->val); 03159 if (max < *(td->val)) max= *(td->val); 03160 } 03161 03162 if (min == max) { 03163 /* just use the current frame ranges */ 03164 min = (float)PSFRA; 03165 max = (float)PEFRA; 03166 } 03167 03168 /* minx/maxx values used by TimeSlide are stored as a 03169 * calloced 2-float array in t->customData. This gets freed 03170 * in postTrans (T_FREE_CUSTOMDATA). 03171 */ 03172 *((float *)(t->customData)) = min; 03173 *((float *)(t->customData) + 1) = max; 03174 } 03175 03176 /* cleanup temp list */ 03177 BLI_freelistN(&anim_data); 03178 } 03179 03180 /* ********************* GRAPH EDITOR ************************* */ 03181 03182 /* Helper function for createTransGraphEditData, which is reponsible for associating 03183 * source data with transform data 03184 */ 03185 static void bezt_to_transdata (TransData *td, TransData2D *td2d, AnimData *adt, BezTriple *bezt, 03186 int bi, short selected, short ishandle, short intvals, 03187 float mtx[3][3], float smtx[3][3]) 03188 { 03189 float *loc = bezt->vec[bi]; 03190 float *cent = bezt->vec[1]; 03191 03192 /* New location from td gets dumped onto the old-location of td2d, which then 03193 * gets copied to the actual data at td2d->loc2d (bezt->vec[n]) 03194 * 03195 * Due to NLA mapping, we apply NLA mapping to some of the verts here, 03196 * and then that mapping will be undone after transform is done. 03197 */ 03198 03199 if (adt) { 03200 td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP); 03201 td2d->loc[1] = loc[1]; 03202 td2d->loc[2] = 0.0f; 03203 td2d->loc2d = loc; 03204 03205 td->loc = td2d->loc; 03206 td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_MAP); 03207 td->center[1] = cent[1]; 03208 td->center[2] = 0.0f; 03209 03210 copy_v3_v3(td->iloc, td->loc); 03211 } 03212 else { 03213 td2d->loc[0] = loc[0]; 03214 td2d->loc[1] = loc[1]; 03215 td2d->loc[2] = 0.0f; 03216 td2d->loc2d = loc; 03217 03218 td->loc = td2d->loc; 03219 copy_v3_v3(td->center, cent); 03220 copy_v3_v3(td->iloc, td->loc); 03221 } 03222 03223 if (td->flag & TD_MOVEHANDLE1) { 03224 td2d->h1 = bezt->vec[0]; 03225 copy_v2_v2(td2d->ih1, td2d->h1); 03226 } 03227 else 03228 td2d->h1 = NULL; 03229 03230 if (td->flag & TD_MOVEHANDLE2) { 03231 td2d->h2 = bezt->vec[2]; 03232 copy_v2_v2(td2d->ih2, td2d->h2); 03233 } 03234 else 03235 td2d->h2 = NULL; 03236 03237 memset(td->axismtx, 0, sizeof(td->axismtx)); 03238 td->axismtx[2][2] = 1.0f; 03239 03240 td->ext= NULL; td->val= NULL; 03241 03242 /* store AnimData info in td->extra, for applying mapping when flushing */ 03243 td->extra= adt; 03244 03245 if (selected) { 03246 td->flag |= TD_SELECTED; 03247 td->dist= 0.0f; 03248 } 03249 else 03250 td->dist= MAXFLOAT; 03251 03252 if (ishandle) 03253 td->flag |= TD_NOTIMESNAP; 03254 if (intvals) 03255 td->flag |= TD_INTVALUES; 03256 03257 /* copy space-conversion matrices for dealing with non-uniform scales */ 03258 copy_m3_m3(td->mtx, mtx); 03259 copy_m3_m3(td->smtx, smtx); 03260 } 03261 03262 static void createTransGraphEditData(bContext *C, TransInfo *t) 03263 { 03264 SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first; 03265 Scene *scene= t->scene; 03266 ARegion *ar= t->ar; 03267 View2D *v2d= &ar->v2d; 03268 03269 TransData *td = NULL; 03270 TransData2D *td2d = NULL; 03271 03272 bAnimContext ac; 03273 ListBase anim_data = {NULL, NULL}; 03274 bAnimListElem *ale; 03275 int filter; 03276 03277 BezTriple *bezt; 03278 int count=0, i; 03279 float cfra; 03280 float mtx[3][3], smtx[3][3]; 03281 const short use_handle = !(sipo->flag & SIPO_NOHANDLES); 03282 03283 /* determine what type of data we are operating on */ 03284 if (ANIM_animdata_get_context(C, &ac) == 0) 03285 return; 03286 03287 /* filter data */ 03288 filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE); 03289 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 03290 03291 /* which side of the current frame should be allowed */ 03292 // XXX we still want this mode, but how to get this using standard transform too? 03293 if (t->mode == TFM_TIME_EXTEND) { 03294 /* only side on which mouse is gets transformed */ 03295 float xmouse, ymouse; 03296 03297 UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &xmouse, &ymouse); 03298 t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side 03299 } 03300 else { 03301 /* normal transform - both sides of current frame are considered */ 03302 t->frame_side = 'B'; 03303 } 03304 03305 /* loop 1: count how many BezTriples (specifically their verts) are selected (or should be edited) */ 03306 for (ale= anim_data.first; ale; ale= ale->next) { 03307 AnimData *adt= ANIM_nla_mapping_get(&ac, ale); 03308 FCurve *fcu= (FCurve *)ale->key_data; 03309 03310 /* convert current-frame to action-time (slightly less accurate, espcially under 03311 * higher scaling ratios, but is faster than converting all points) 03312 */ 03313 if (adt) 03314 cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); 03315 else 03316 cfra = (float)CFRA; 03317 03318 /* F-Curve may not have any keyframes */ 03319 if (fcu->bezt == NULL) 03320 continue; 03321 03322 /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse */ 03323 for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) { 03324 if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { 03325 const char sel2= bezt->f2 & SELECT; 03326 const char sel1= use_handle ? bezt->f1 & SELECT : sel2; 03327 const char sel3= use_handle ? bezt->f3 & SELECT : sel2; 03328 03329 if (ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)) { 03330 /* for 'normal' pivots - just include anything that is selected. 03331 this works a bit differently in translation modes */ 03332 if (sel2) count++; 03333 else { 03334 if (sel1) count++; 03335 if (sel3) count++; 03336 } 03337 } 03338 else if (sipo->around == V3D_LOCAL) { 03339 /* for local-pivot we only need to count the number of selected handles only, so that centerpoints don't 03340 * don't get moved wrong 03341 */ 03342 if (bezt->ipo == BEZT_IPO_BEZ) { 03343 if (sel1) count++; 03344 if (sel3) count++; 03345 } 03346 /* else if (sel2) count++; // TODO: could this cause problems? */ 03347 /* - yes this causes problems, because no td is created for the center point */ 03348 } 03349 else { 03350 /* for 'normal' pivots - just include anything that is selected */ 03351 if (sel1) count++; 03352 if (sel2) count++; 03353 if (sel3) count++; 03354 } 03355 } 03356 } 03357 } 03358 03359 /* stop if trying to build list if nothing selected */ 03360 if (count == 0) { 03361 /* cleanup temp list */ 03362 BLI_freelistN(&anim_data); 03363 return; 03364 } 03365 03366 /* allocate memory for data */ 03367 t->total= count; 03368 03369 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData (Graph Editor)"); 03370 /* for each 2d vert a 3d vector is allocated, so that they can be treated just as if they were 3d verts */ 03371 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransData2D (Graph Editor)"); 03372 03373 td= t->data; 03374 td2d= t->data2d; 03375 03376 /* precompute space-conversion matrices for dealing with non-uniform scaling of Graph Editor */ 03377 unit_m3(mtx); 03378 unit_m3(smtx); 03379 03380 if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) { 03381 float xscale, yscale; 03382 03383 /* apply scale factors to x and y axes of space-conversion matrices */ 03384 UI_view2d_getscale(v2d, &xscale, &yscale); 03385 03386 /* mtx is data to global (i.e. view) conversion */ 03387 mul_v3_fl(mtx[0], xscale); 03388 mul_v3_fl(mtx[1], yscale); 03389 03390 /* smtx is global (i.e. view) to data conversion */ 03391 if (IS_EQF(xscale, 0.0f) == 0) mul_v3_fl(smtx[0], 1.0f/xscale); 03392 if (IS_EQF(yscale, 0.0f) == 0) mul_v3_fl(smtx[1], 1.0f/yscale); 03393 } 03394 03395 /* loop 2: build transdata arrays */ 03396 for (ale= anim_data.first; ale; ale= ale->next) { 03397 AnimData *adt= ANIM_nla_mapping_get(&ac, ale); 03398 FCurve *fcu= (FCurve *)ale->key_data; 03399 short intvals= (fcu->flag & FCURVE_INT_VALUES); 03400 03401 /* convert current-frame to action-time (slightly less accurate, espcially under 03402 * higher scaling ratios, but is faster than converting all points) 03403 */ 03404 if (adt) 03405 cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); 03406 else 03407 cfra = (float)CFRA; 03408 03409 /* F-Curve may not have any keyframes */ 03410 if (fcu->bezt == NULL) 03411 continue; 03412 03413 ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, ANIM_UNITCONV_ONLYSEL|ANIM_UNITCONV_SELVERTS); 03414 03415 /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */ 03416 for (i=0, bezt= fcu->bezt; i < fcu->totvert; i++, bezt++) { 03417 if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { 03418 const char sel2= bezt->f2 & SELECT; 03419 const char sel1= use_handle ? bezt->f1 & SELECT : sel2; 03420 const char sel3= use_handle ? bezt->f3 & SELECT : sel2; 03421 03422 TransDataCurveHandleFlags *hdata = NULL; 03423 /* short h1=1, h2=1; */ /* UNUSED */ 03424 03425 /* only include handles if selected, irrespective of the interpolation modes. 03426 * also, only treat handles specially if the center point isn't selected. 03427 */ 03428 if (!ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE) || !(sel2)) { 03429 if (sel1) { 03430 hdata = initTransDataCurveHandles(td, bezt); 03431 bezt_to_transdata(td++, td2d++, adt, bezt, 0, 1, 1, intvals, mtx, smtx); 03432 } 03433 else { 03434 /* h1= 0; */ /* UNUSED */ 03435 } 03436 03437 if (sel3) { 03438 if (hdata==NULL) 03439 hdata = initTransDataCurveHandles(td, bezt); 03440 bezt_to_transdata(td++, td2d++, adt, bezt, 2, 1, 1, intvals, mtx, smtx); 03441 } 03442 else { 03443 /* h2= 0; */ /* UNUSED */ 03444 } 03445 } 03446 03447 /* only include main vert if selected */ 03448 if (sel2 && (sipo->around != V3D_LOCAL || ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE))) { 03449 03450 /* move handles relative to center */ 03451 if (ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)) { 03452 if (sel1) td->flag |= TD_MOVEHANDLE1; 03453 if (sel3) td->flag |= TD_MOVEHANDLE2; 03454 } 03455 03456 /* if handles were not selected, store their selection status */ 03457 if (!(sel1) && !(sel3)) { 03458 if (hdata == NULL) 03459 hdata = initTransDataCurveHandles(td, bezt); 03460 } 03461 03462 bezt_to_transdata(td++, td2d++, adt, bezt, 1, 1, 0, intvals, mtx, smtx); 03463 03464 } 03465 /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...): 03466 * - Check if we've got entire BezTriple selected and we're scaling/rotating that point, 03467 * then check if we're using auto-handles. 03468 * - If so, change them auto-handles to aligned handles so that handles get affected too 03469 */ 03470 if ( ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && 03471 ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) && 03472 ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) 03473 { 03474 if (hdata && (sel1) && (sel3)) { 03475 bezt->h1= HD_ALIGN; 03476 bezt->h2= HD_ALIGN; 03477 } 03478 } 03479 } 03480 } 03481 03482 /* Sets handles based on the selection */ 03483 testhandles_fcurve(fcu, use_handle); 03484 } 03485 03486 /* cleanup temp list */ 03487 BLI_freelistN(&anim_data); 03488 } 03489 03490 03491 /* ------------------------ */ 03492 03493 /* struct for use in re-sorting BezTriples during Graph Editor transform */ 03494 typedef struct BeztMap { 03495 BezTriple *bezt; 03496 unsigned int oldIndex; /* index of bezt in fcu->bezt array before sorting */ 03497 unsigned int newIndex; /* index of bezt in fcu->bezt array after sorting */ 03498 short swapHs; /* swap order of handles (-1=clear; 0=not checked, 1=swap) */ 03499 char pipo, cipo; /* interpolation of current and next segments */ 03500 } BeztMap; 03501 03502 03503 /* This function converts an FCurve's BezTriple array to a BeztMap array 03504 * NOTE: this allocates memory that will need to get freed later 03505 */ 03506 static BeztMap *bezt_to_beztmaps (BezTriple *bezts, int totvert, const short UNUSED(use_handle)) 03507 { 03508 BezTriple *bezt= bezts; 03509 BezTriple *prevbezt= NULL; 03510 BeztMap *bezm, *bezms; 03511 int i; 03512 03513 /* allocate memory for this array */ 03514 if (totvert==0 || bezts==NULL) 03515 return NULL; 03516 bezm= bezms= MEM_callocN(sizeof(BeztMap)*totvert, "BeztMaps"); 03517 03518 /* assign beztriples to beztmaps */ 03519 for (i=0; i < totvert; i++, bezm++, prevbezt=bezt, bezt++) { 03520 bezm->bezt= bezt; 03521 03522 bezm->oldIndex= i; 03523 bezm->newIndex= i; 03524 03525 bezm->pipo= (prevbezt) ? prevbezt->ipo : bezt->ipo; 03526 bezm->cipo= bezt->ipo; 03527 } 03528 03529 return bezms; 03530 } 03531 03532 /* This function copies the code of sort_time_ipocurve, but acts on BeztMap structs instead */ 03533 static void sort_time_beztmaps (BeztMap *bezms, int totvert, const short UNUSED(use_handle)) 03534 { 03535 BeztMap *bezm; 03536 int i, ok= 1; 03537 03538 /* keep repeating the process until nothing is out of place anymore */ 03539 while (ok) { 03540 ok= 0; 03541 03542 bezm= bezms; 03543 i= totvert; 03544 while (i--) { 03545 /* is current bezm out of order (i.e. occurs later than next)? */ 03546 if (i > 0) { 03547 if (bezm->bezt->vec[1][0] > (bezm+1)->bezt->vec[1][0]) { 03548 bezm->newIndex++; 03549 (bezm+1)->newIndex--; 03550 03551 SWAP(BeztMap, *bezm, *(bezm+1)); 03552 03553 ok= 1; 03554 } 03555 } 03556 03557 /* do we need to check if the handles need to be swapped? 03558 * optimisation: this only needs to be performed in the first loop 03559 */ 03560 if (bezm->swapHs == 0) { 03561 if ( (bezm->bezt->vec[0][0] > bezm->bezt->vec[1][0]) && 03562 (bezm->bezt->vec[2][0] < bezm->bezt->vec[1][0]) ) 03563 { 03564 /* handles need to be swapped */ 03565 bezm->swapHs = 1; 03566 } 03567 else { 03568 /* handles need to be cleared */ 03569 bezm->swapHs = -1; 03570 } 03571 } 03572 03573 bezm++; 03574 } 03575 } 03576 } 03577 03578 /* This function firstly adjusts the pointers that the transdata has to each BezTriple */ 03579 static void beztmap_to_data (TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert, const short UNUSED(use_handle)) 03580 { 03581 BezTriple *bezts = fcu->bezt; 03582 BeztMap *bezm; 03583 TransData2D *td2d; 03584 TransData *td; 03585 int i, j; 03586 char *adjusted; 03587 03588 /* dynamically allocate an array of chars to mark whether an TransData's 03589 * pointers have been fixed already, so that we don't override ones that are 03590 * already done 03591 */ 03592 adjusted= MEM_callocN(t->total, "beztmap_adjusted_map"); 03593 03594 /* for each beztmap item, find if it is used anywhere */ 03595 bezm= bezms; 03596 for (i= 0; i < totvert; i++, bezm++) { 03597 /* loop through transdata, testing if we have a hit 03598 * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped... 03599 */ 03600 td2d= t->data2d; 03601 td= t->data; 03602 for (j= 0; j < t->total; j++, td2d++, td++) { 03603 /* skip item if already marked */ 03604 if (adjusted[j] != 0) continue; 03605 03606 /* update all transdata pointers, no need to check for selections etc, 03607 * since only points that are really needed were created as transdata 03608 */ 03609 if (td2d->loc2d == bezm->bezt->vec[0]) { 03610 if (bezm->swapHs == 1) 03611 td2d->loc2d= (bezts + bezm->newIndex)->vec[2]; 03612 else 03613 td2d->loc2d= (bezts + bezm->newIndex)->vec[0]; 03614 adjusted[j] = 1; 03615 } 03616 else if (td2d->loc2d == bezm->bezt->vec[2]) { 03617 if (bezm->swapHs == 1) 03618 td2d->loc2d= (bezts + bezm->newIndex)->vec[0]; 03619 else 03620 td2d->loc2d= (bezts + bezm->newIndex)->vec[2]; 03621 adjusted[j] = 1; 03622 } 03623 else if (td2d->loc2d == bezm->bezt->vec[1]) { 03624 td2d->loc2d= (bezts + bezm->newIndex)->vec[1]; 03625 03626 /* if only control point is selected, the handle pointers need to be updated as well */ 03627 if(td2d->h1) 03628 td2d->h1= (bezts + bezm->newIndex)->vec[0]; 03629 if(td2d->h2) 03630 td2d->h2= (bezts + bezm->newIndex)->vec[2]; 03631 03632 adjusted[j] = 1; 03633 } 03634 03635 /* the handle type pointer has to be updated too */ 03636 if (adjusted[j] && td->flag & TD_BEZTRIPLE && td->hdata) { 03637 if(bezm->swapHs == 1) { 03638 td->hdata->h1 = &(bezts + bezm->newIndex)->h2; 03639 td->hdata->h2 = &(bezts + bezm->newIndex)->h1; 03640 } 03641 else { 03642 td->hdata->h1 = &(bezts + bezm->newIndex)->h1; 03643 td->hdata->h2 = &(bezts + bezm->newIndex)->h2; 03644 } 03645 } 03646 } 03647 03648 } 03649 03650 /* free temp memory used for 'adjusted' array */ 03651 MEM_freeN(adjusted); 03652 } 03653 03654 /* This function is called by recalcData during the Transform loop to recalculate 03655 * the handles of curves and sort the keyframes so that the curves draw correctly. 03656 * It is only called if some keyframes have moved out of order. 03657 * 03658 * anim_data is the list of channels (F-Curves) retrieved already containing the 03659 * channels to work on. It should not be freed here as it may still need to be used. 03660 */ 03661 void remake_graph_transdata (TransInfo *t, ListBase *anim_data) 03662 { 03663 SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first; 03664 bAnimListElem *ale; 03665 const short use_handle = !(sipo->flag & SIPO_NOHANDLES); 03666 03667 /* sort and reassign verts */ 03668 for (ale= anim_data->first; ale; ale= ale->next) { 03669 FCurve *fcu= (FCurve *)ale->key_data; 03670 03671 if (fcu->bezt) { 03672 BeztMap *bezm; 03673 03674 /* adjust transform-data pointers */ 03675 /* note, none of these functions use 'use_handle', it could be removed */ 03676 bezm= bezt_to_beztmaps(fcu->bezt, fcu->totvert, use_handle); 03677 sort_time_beztmaps(bezm, fcu->totvert, use_handle); 03678 beztmap_to_data(t, fcu, bezm, fcu->totvert, use_handle); 03679 03680 /* free mapping stuff */ 03681 MEM_freeN(bezm); 03682 03683 /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */ 03684 sort_time_fcurve(fcu); 03685 03686 /* make sure handles are all set correctly */ 03687 testhandles_fcurve(fcu, use_handle); 03688 } 03689 } 03690 } 03691 03692 /* this function is called on recalcData to apply the transforms applied 03693 * to the transdata on to the actual keyframe data 03694 */ 03695 void flushTransGraphData(TransInfo *t) 03696 { 03697 SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first; 03698 TransData *td; 03699 TransData2D *td2d; 03700 Scene *scene= t->scene; 03701 double secf= FPS; 03702 int a; 03703 03704 /* flush to 2d vector from internally used 3d vector */ 03705 for (a=0, td= t->data, td2d=t->data2d; a<t->total; a++, td++, td2d++) { 03706 AnimData *adt= (AnimData *)td->extra; /* pointers to relevant AnimData blocks are stored in the td->extra pointers */ 03707 03708 /* handle snapping for time values 03709 * - we should still be in NLA-mapping timespace 03710 * - only apply to keyframes (but never to handles) 03711 */ 03712 if ((td->flag & TD_NOTIMESNAP)==0) { 03713 switch (sipo->autosnap) { 03714 case SACTSNAP_FRAME: /* snap to nearest frame (or second if drawing seconds) */ 03715 if (sipo->flag & SIPO_DRAWTIME) 03716 td2d->loc[0]= (float)( floor((td2d->loc[0]/secf) + 0.5f) * secf ); 03717 else 03718 td2d->loc[0]= (float)( floor(td2d->loc[0]+0.5f) ); 03719 break; 03720 03721 case SACTSNAP_MARKER: /* snap to nearest marker */ 03722 td2d->loc[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, td2d->loc[0]); 03723 break; 03724 } 03725 } 03726 03727 /* we need to unapply the nla-mapping from the time in some situations */ 03728 if (adt) 03729 td2d->loc2d[0]= BKE_nla_tweakedit_remap(adt, td2d->loc[0], NLATIME_CONVERT_UNMAP); 03730 else 03731 td2d->loc2d[0]= td2d->loc[0]; 03732 03733 /* if int-values only, truncate to integers */ 03734 if (td->flag & TD_INTVALUES) 03735 td2d->loc2d[1]= floorf(td2d->loc[1] + 0.5f); 03736 else 03737 td2d->loc2d[1]= td2d->loc[1]; 03738 03739 if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) { 03740 td2d->h1[0] = td2d->ih1[0] + td->loc[0] - td->iloc[0]; 03741 td2d->h1[1] = td2d->ih1[1] + td->loc[1] - td->iloc[1]; 03742 } 03743 03744 if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) { 03745 td2d->h2[0] = td2d->ih2[0] + td->loc[0] - td->iloc[0]; 03746 td2d->h2[1] = td2d->ih2[1] + td->loc[1] - td->iloc[1]; 03747 } 03748 } 03749 } 03750 03751 /* ******************* Sequencer Transform data ******************* */ 03752 03753 /* This function applies the rules for transforming a strip so duplicate 03754 * checks dont need to be added in multiple places. 03755 * 03756 * recursive, count and flag MUST be set. 03757 * 03758 * seq->depth must be set before running this function so we know if the strips 03759 * are root level or not 03760 */ 03761 static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count, int *flag) 03762 { 03763 /* for extend we need to do some tricks */ 03764 if (t->mode == TFM_TIME_EXTEND) { 03765 03766 /* *** Extend Transform *** */ 03767 03768 Scene * scene= t->scene; 03769 int cfra= CFRA; 03770 int left= seq_tx_get_final_left(seq, 0); 03771 int right= seq_tx_get_final_right(seq, 0); 03772 03773 if (seq->depth == 0 && ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK))) { 03774 *recursive= 0; 03775 *count= 0; 03776 *flag= 0; 03777 } 03778 else if (seq->type ==SEQ_META) { 03779 03780 /* for meta's we only ever need to extend their children, no matter what depth 03781 * just check the meta's are in the bounds */ 03782 if (t->frame_side=='R' && right <= cfra) *recursive= 0; 03783 else if (t->frame_side=='L' && left >= cfra) *recursive= 0; 03784 else *recursive= 1; 03785 03786 *count= 0; 03787 *flag= 0; 03788 } 03789 else { 03790 03791 *recursive= 0; /* not a meta, so no thinking here */ 03792 *count= 1; /* unless its set to 0, extend will never set 2 handles at once */ 03793 *flag= (seq->flag | SELECT) & ~(SEQ_LEFTSEL|SEQ_RIGHTSEL); 03794 03795 if (t->frame_side=='R') { 03796 if (right <= cfra) *count= *flag= 0; /* ignore */ 03797 else if (left > cfra) ; /* keep the selection */ 03798 else *flag |= SEQ_RIGHTSEL; 03799 } 03800 else { 03801 if (left >= cfra) *count= *flag= 0; /* ignore */ 03802 else if (right < cfra) ; /* keep the selection */ 03803 else *flag |= SEQ_LEFTSEL; 03804 } 03805 } 03806 } else { 03807 03808 t->frame_side= 'B'; 03809 03810 /* *** Normal Transform *** */ 03811 03812 if (seq->depth == 0) { 03813 03814 /* Count */ 03815 03816 /* Non nested strips (resect selection and handles) */ 03817 if ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK)) { 03818 *recursive= 0; 03819 *count= 0; 03820 *flag= 0; 03821 } 03822 else { 03823 if ((seq->flag & (SEQ_LEFTSEL|SEQ_RIGHTSEL)) == (SEQ_LEFTSEL|SEQ_RIGHTSEL)) { 03824 *flag= seq->flag; 03825 *count= 2; /* we need 2 transdata's */ 03826 } else { 03827 *flag= seq->flag; 03828 *count= 1; /* selected or with a handle selected */ 03829 } 03830 03831 /* Recursive */ 03832 03833 if ((seq->type == SEQ_META) && ((seq->flag & (SEQ_LEFTSEL|SEQ_RIGHTSEL)) == 0)) { 03834 /* if any handles are selected, dont recurse */ 03835 *recursive = 1; 03836 } 03837 else { 03838 *recursive = 0; 03839 } 03840 } 03841 } 03842 else { 03843 /* Nested, different rules apply */ 03844 03845 #ifdef SEQ_TX_NESTED_METAS 03846 *flag= (seq->flag | SELECT) & ~(SEQ_LEFTSEL|SEQ_RIGHTSEL); 03847 *count= 1; /* ignore the selection for nested */ 03848 *recursive = (seq->type == SEQ_META ); 03849 #else 03850 if (seq->type == SEQ_META) { 03851 /* Meta's can only directly be moved between channels since they 03852 * dont have their start and length set directly (children affect that) 03853 * since this Meta is nested we dont need any of its data infact. 03854 * calc_sequence() will update its settings when run on the toplevel meta */ 03855 *flag= 0; 03856 *count= 0; 03857 *recursive = 1; 03858 } 03859 else { 03860 *flag= (seq->flag | SELECT) & ~(SEQ_LEFTSEL|SEQ_RIGHTSEL); 03861 *count= 1; /* ignore the selection for nested */ 03862 *recursive = 0; 03863 } 03864 #endif 03865 } 03866 } 03867 } 03868 03869 03870 03871 static int SeqTransCount(TransInfo *t, ListBase *seqbase, int depth) 03872 { 03873 Sequence *seq; 03874 int tot= 0, recursive, count, flag; 03875 03876 for (seq= seqbase->first; seq; seq= seq->next) { 03877 seq->depth= depth; 03878 03879 SeqTransInfo(t, seq, &recursive, &count, &flag); /* ignore the flag */ 03880 tot += count; 03881 03882 if (recursive) { 03883 tot += SeqTransCount(t, &seq->seqbase, depth+1); 03884 } 03885 } 03886 03887 return tot; 03888 } 03889 03890 03891 static TransData *SeqToTransData(TransData *td, TransData2D *td2d, TransDataSeq *tdsq, Sequence *seq, int flag, int sel_flag) 03892 { 03893 int start_left; 03894 03895 switch(sel_flag) { 03896 case SELECT: 03897 /* Use seq_tx_get_final_left() and an offset here 03898 * so transform has the left hand location of the strip. 03899 * tdsq->start_offset is used when flushing the tx data back */ 03900 start_left= seq_tx_get_final_left(seq, 0); 03901 td2d->loc[0]= start_left; 03902 tdsq->start_offset= start_left - seq->start; /* use to apply the original location */ 03903 break; 03904 case SEQ_LEFTSEL: 03905 start_left= seq_tx_get_final_left(seq, 0); 03906 td2d->loc[0] = start_left; 03907 break; 03908 case SEQ_RIGHTSEL: 03909 td2d->loc[0] = seq_tx_get_final_right(seq, 0); 03910 break; 03911 } 03912 03913 td2d->loc[1] = seq->machine; /* channel - Y location */ 03914 td2d->loc[2] = 0.0f; 03915 td2d->loc2d = NULL; 03916 03917 03918 tdsq->seq= seq; 03919 03920 /* Use instead of seq->flag for nested strips and other 03921 * cases where the selection may need to be modified */ 03922 tdsq->flag= flag; 03923 tdsq->sel_flag= sel_flag; 03924 03925 03926 td->extra= (void *)tdsq; /* allow us to update the strip from here */ 03927 03928 td->flag = 0; 03929 td->loc = td2d->loc; 03930 copy_v3_v3(td->center, td->loc); 03931 copy_v3_v3(td->iloc, td->loc); 03932 03933 memset(td->axismtx, 0, sizeof(td->axismtx)); 03934 td->axismtx[2][2] = 1.0f; 03935 03936 td->ext= NULL; td->val= NULL; 03937 03938 td->flag |= TD_SELECTED; 03939 td->dist= 0.0; 03940 03941 unit_m3(td->mtx); 03942 unit_m3(td->smtx); 03943 03944 /* Time Transform (extend) */ 03945 td->val= td2d->loc; 03946 td->ival= td2d->loc[0]; 03947 03948 return td; 03949 } 03950 03951 static int SeqToTransData_Recursive(TransInfo *t, ListBase *seqbase, TransData *td, TransData2D *td2d, TransDataSeq *tdsq) 03952 { 03953 Sequence *seq; 03954 int recursive, count, flag; 03955 int tot= 0; 03956 03957 for (seq= seqbase->first; seq; seq= seq->next) { 03958 03959 SeqTransInfo(t, seq, &recursive, &count, &flag); 03960 03961 /* add children first so recalculating metastrips does nested strips first */ 03962 if (recursive) { 03963 int tot_children= SeqToTransData_Recursive(t, &seq->seqbase, td, td2d, tdsq); 03964 03965 td= td + tot_children; 03966 td2d= td2d + tot_children; 03967 tdsq= tdsq + tot_children; 03968 03969 tot += tot_children; 03970 } 03971 03972 /* use 'flag' which is derived from seq->flag but modified for special cases */ 03973 if (flag & SELECT) { 03974 if (flag & (SEQ_LEFTSEL|SEQ_RIGHTSEL)) { 03975 if (flag & SEQ_LEFTSEL) { 03976 SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_LEFTSEL); 03977 tot++; 03978 } 03979 if (flag & SEQ_RIGHTSEL) { 03980 SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_RIGHTSEL); 03981 tot++; 03982 } 03983 } 03984 else { 03985 SeqToTransData(td++, td2d++, tdsq++, seq, flag, SELECT); 03986 tot++; 03987 } 03988 } 03989 } 03990 03991 return tot; 03992 } 03993 03994 static void freeSeqData(TransInfo *t) 03995 { 03996 Editing *ed= seq_give_editing(t->scene, FALSE); 03997 03998 if(ed != NULL) { 03999 ListBase *seqbasep= ed->seqbasep; 04000 TransData *td= t->data; 04001 int a; 04002 04003 /* prevent updating the same seq twice 04004 * if the transdata order is changed this will mess up 04005 * but so will TransDataSeq */ 04006 Sequence *seq_prev= NULL; 04007 Sequence *seq; 04008 04009 04010 if (!(t->state == TRANS_CANCEL)) { 04011 04012 #if 0 // default 2.4 behavior 04013 04014 /* flush to 2d vector from internally used 3d vector */ 04015 for(a=0; a<t->total; a++, td++) { 04016 if ((seq != seq_prev) && (seq->depth==0) && (seq->flag & SEQ_OVERLAP)) { 04017 seq= ((TransDataSeq *)td->extra)->seq; 04018 shuffle_seq(seqbasep, seq); 04019 } 04020 04021 seq_prev= seq; 04022 } 04023 04024 #else // durian hack 04025 { 04026 int overlap= 0; 04027 04028 for(a=0; a<t->total; a++, td++) { 04029 seq_prev= NULL; 04030 seq= ((TransDataSeq *)td->extra)->seq; 04031 if ((seq != seq_prev) && (seq->depth==0) && (seq->flag & SEQ_OVERLAP)) { 04032 overlap= 1; 04033 break; 04034 } 04035 seq_prev= seq; 04036 } 04037 04038 if(overlap) { 04039 int has_effect= 0; 04040 for(seq= seqbasep->first; seq; seq= seq->next) 04041 seq->tmp= NULL; 04042 04043 td= t->data; 04044 seq_prev= NULL; 04045 for(a=0; a<t->total; a++, td++) { 04046 seq= ((TransDataSeq *)td->extra)->seq; 04047 if ((seq != seq_prev)) { 04048 /* check effects strips, we cant change their time */ 04049 if((seq->type & SEQ_EFFECT) && seq->seq1) { 04050 has_effect= TRUE; 04051 } 04052 else { 04053 /* Tag seq with a non zero value, used by shuffle_seq_time to identify the ones to shuffle */ 04054 seq->tmp= (void*)1; 04055 } 04056 } 04057 } 04058 04059 shuffle_seq_time(seqbasep, t->scene); 04060 04061 if(has_effect) { 04062 /* update effects strips based on strips just moved in time */ 04063 td= t->data; 04064 seq_prev= NULL; 04065 for(a=0; a<t->total; a++, td++) { 04066 seq= ((TransDataSeq *)td->extra)->seq; 04067 if ((seq != seq_prev)) { 04068 if((seq->type & SEQ_EFFECT) && seq->seq1) { 04069 calc_sequence(t->scene, seq); 04070 } 04071 } 04072 } 04073 04074 /* now if any effects _still_ overlap, we need to move them up */ 04075 td= t->data; 04076 seq_prev= NULL; 04077 for(a=0; a<t->total; a++, td++) { 04078 seq= ((TransDataSeq *)td->extra)->seq; 04079 if ((seq != seq_prev)) { 04080 if((seq->type & SEQ_EFFECT) && seq->seq1) { 04081 if(seq_test_overlap(seqbasep, seq)) { 04082 shuffle_seq(seqbasep, seq, t->scene); 04083 } 04084 } 04085 } 04086 } 04087 /* done with effects */ 04088 } 04089 } 04090 } 04091 #endif 04092 04093 for(seq= seqbasep->first; seq; seq= seq->next) { 04094 /* We might want to build a list of effects that need to be updated during transform */ 04095 if(seq->type & SEQ_EFFECT) { 04096 if (seq->seq1 && seq->seq1->flag & SELECT) calc_sequence(t->scene, seq); 04097 else if (seq->seq2 && seq->seq2->flag & SELECT) calc_sequence(t->scene, seq); 04098 else if (seq->seq3 && seq->seq3->flag & SELECT) calc_sequence(t->scene, seq); 04099 } 04100 } 04101 04102 sort_seq(t->scene); 04103 } 04104 else { 04105 /* Cancelled, need to update the strips display */ 04106 for(a=0; a<t->total; a++, td++) { 04107 seq= ((TransDataSeq *)td->extra)->seq; 04108 if ((seq != seq_prev) && (seq->depth==0)) { 04109 calc_sequence_disp(t->scene, seq); 04110 } 04111 seq_prev= seq; 04112 } 04113 } 04114 } 04115 04116 if (t->customData) { 04117 MEM_freeN(t->customData); 04118 t->customData= NULL; 04119 } 04120 if (t->data) { 04121 MEM_freeN(t->data); // XXX postTrans usually does this 04122 t->data= NULL; 04123 } 04124 } 04125 04126 static void createTransSeqData(bContext *C, TransInfo *t) 04127 { 04128 #define XXX_DURIAN_ANIM_TX_HACK 04129 04130 View2D *v2d= UI_view2d_fromcontext(C); 04131 Scene *scene= t->scene; 04132 Editing *ed= seq_give_editing(t->scene, FALSE); 04133 TransData *td = NULL; 04134 TransData2D *td2d= NULL; 04135 TransDataSeq *tdsq= NULL; 04136 04137 int count=0; 04138 04139 if (ed==NULL) { 04140 t->total= 0; 04141 return; 04142 } 04143 04144 t->customFree= freeSeqData; 04145 04146 /* which side of the current frame should be allowed */ 04147 if (t->mode == TFM_TIME_EXTEND) { 04148 /* only side on which mouse is gets transformed */ 04149 float xmouse, ymouse; 04150 04151 UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &xmouse, &ymouse); 04152 t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; 04153 } 04154 else { 04155 /* normal transform - both sides of current frame are considered */ 04156 t->frame_side = 'B'; 04157 } 04158 04159 #ifdef XXX_DURIAN_ANIM_TX_HACK 04160 { 04161 Sequence *seq; 04162 for(seq= ed->seqbasep->first; seq; seq= seq->next) { 04163 /* hack */ 04164 if((seq->flag & SELECT)==0 && seq->type & SEQ_EFFECT) { 04165 Sequence *seq_user; 04166 int i; 04167 for(i=0; i<3; i++) { 04168 seq_user= *((&seq->seq1) + i); 04169 if ( seq_user && (seq_user->flag & SELECT) && 04170 !(seq_user->flag & SEQ_LOCK) && 04171 !(seq_user->flag & (SEQ_LEFTSEL|SEQ_RIGHTSEL))) 04172 { 04173 seq->flag |= SELECT; 04174 } 04175 } 04176 } 04177 } 04178 } 04179 #endif 04180 04181 count = SeqTransCount(t, ed->seqbasep, 0); 04182 04183 /* allocate memory for data */ 04184 t->total= count; 04185 04186 /* stop if trying to build list if nothing selected */ 04187 if (count == 0) { 04188 return; 04189 } 04190 04191 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransSeq TransData"); 04192 td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransSeq TransData2D"); 04193 tdsq = t->customData= MEM_callocN(t->total*sizeof(TransDataSeq), "TransSeq TransDataSeq"); 04194 04195 04196 04197 /* loop 2: build transdata array */ 04198 SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq); 04199 04200 #undef XXX_DURIAN_ANIM_TX_HACK 04201 } 04202 04203 04204 /* *********************** Object Transform data ******************* */ 04205 04206 /* Little helper function for ObjectToTransData used to give certain 04207 * constraints (ChildOf, FollowPath, and others that may be added) 04208 * inverse corrections for transform, so that they aren't in CrazySpace. 04209 * These particular constraints benefit from this, but others don't, hence 04210 * this semi-hack ;-) - Aligorith 04211 */ 04212 static short constraints_list_needinv(TransInfo *t, ListBase *list) 04213 { 04214 bConstraint *con; 04215 04216 /* loop through constraints, checking if there's one of the mentioned 04217 * constraints needing special crazyspace corrections 04218 */ 04219 if (list) { 04220 for (con= list->first; con; con=con->next) { 04221 /* only consider constraint if it is enabled, and has influence on result */ 04222 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0f)) { 04223 /* (affirmative) returns for specific constraints here... */ 04224 /* constraints that require this regardless */ 04225 if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1; 04226 if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1; 04227 if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1; 04228 if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) return 1; 04229 04230 /* constraints that require this only under special conditions */ 04231 if (con->type == CONSTRAINT_TYPE_ROTLIKE) { 04232 /* CopyRot constraint only does this when rotating, and offset is on */ 04233 bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data; 04234 04235 if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION)) 04236 return 1; 04237 } 04238 } 04239 } 04240 } 04241 04242 /* no appropriate candidates found */ 04243 return 0; 04244 } 04245 04246 /* transcribe given object into TransData for Transforming */ 04247 static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) 04248 { 04249 Scene *scene = t->scene; 04250 float obmtx[3][3]; 04251 short constinv; 04252 short skip_invert = 0; 04253 04254 /* axismtx has the real orientation */ 04255 copy_m3_m4(td->axismtx, ob->obmat); 04256 normalize_m3(td->axismtx); 04257 04258 td->con= ob->constraints.first; 04259 04260 /* hack: tempolarily disable tracking and/or constraints when getting 04261 * object matrix, if tracking is on, or if constraints don't need 04262 * inverse correction to stop it from screwing up space conversion 04263 * matrix later 04264 */ 04265 constinv = constraints_list_needinv(t, &ob->constraints); 04266 04267 /* disable constraints inversion for dummy pass */ 04268 if (t->mode == TFM_DUMMY) 04269 skip_invert = 1; 04270 04271 if (skip_invert == 0 && constinv == 0) { 04272 if (constinv == 0) 04273 ob->transflag |= OB_NO_CONSTRAINTS; /* where_is_object_time checks this */ 04274 04275 where_is_object(t->scene, ob); 04276 04277 if (constinv == 0) 04278 ob->transflag &= ~OB_NO_CONSTRAINTS; 04279 } 04280 else 04281 where_is_object(t->scene, ob); 04282 04283 td->ob = ob; 04284 04285 td->loc = ob->loc; 04286 copy_v3_v3(td->iloc, td->loc); 04287 04288 if (ob->rotmode > 0) { 04289 td->ext->rot= ob->rot; 04290 td->ext->rotAxis= NULL; 04291 td->ext->rotAngle= NULL; 04292 td->ext->quat= NULL; 04293 04294 copy_v3_v3(td->ext->irot, ob->rot); 04295 copy_v3_v3(td->ext->drot, ob->drot); 04296 } 04297 else if (ob->rotmode == ROT_MODE_AXISANGLE) { 04298 td->ext->rot= NULL; 04299 td->ext->rotAxis= ob->rotAxis; 04300 td->ext->rotAngle= &ob->rotAngle; 04301 td->ext->quat= NULL; 04302 04303 td->ext->irotAngle= ob->rotAngle; 04304 copy_v3_v3(td->ext->irotAxis, ob->rotAxis); 04305 // td->ext->drotAngle= ob->drotAngle; // XXX, not implimented 04306 // copy_v3_v3(td->ext->drotAxis, ob->drotAxis); // XXX, not implimented 04307 } 04308 else { 04309 td->ext->rot= NULL; 04310 td->ext->rotAxis= NULL; 04311 td->ext->rotAngle= NULL; 04312 td->ext->quat= ob->quat; 04313 04314 copy_qt_qt(td->ext->iquat, ob->quat); 04315 copy_qt_qt(td->ext->dquat, ob->dquat); 04316 } 04317 td->ext->rotOrder=ob->rotmode; 04318 04319 td->ext->size = ob->size; 04320 copy_v3_v3(td->ext->isize, ob->size); 04321 copy_v3_v3(td->ext->dscale, ob->dscale); 04322 04323 copy_v3_v3(td->center, ob->obmat[3]); 04324 04325 copy_m4_m4(td->ext->obmat, ob->obmat); 04326 04327 /* is there a need to set the global<->data space conversion matrices? */ 04328 if (ob->parent || constinv) { 04329 float totmat[3][3], obinv[3][3]; 04330 04331 /* Get the effect of parenting, and/or certain constraints. 04332 * NOTE: some Constraints, and also Tracking should never get this 04333 * done, as it doesn't work well. 04334 */ 04335 object_to_mat3(ob, obmtx); 04336 copy_m3_m4(totmat, ob->obmat); 04337 invert_m3_m3(obinv, totmat); 04338 mul_m3_m3m3(td->smtx, obmtx, obinv); 04339 invert_m3_m3(td->mtx, td->smtx); 04340 } 04341 else { 04342 /* no conversion to/from dataspace */ 04343 unit_m3(td->smtx); 04344 unit_m3(td->mtx); 04345 } 04346 04347 /* set active flag */ 04348 if (ob == OBACT) 04349 { 04350 td->flag |= TD_ACTIVE; 04351 } 04352 } 04353 04354 04355 /* sets flags in Bases to define whether they take part in transform */ 04356 /* it deselects Bases, so we have to call the clear function always after */ 04357 static void set_trans_object_base_flags(TransInfo *t) 04358 { 04359 Scene *scene = t->scene; 04360 View3D *v3d = t->view; 04361 04362 /* 04363 if Base selected and has parent selected: 04364 base->flag= BA_WAS_SEL 04365 */ 04366 Base *base; 04367 04368 /* don't do it if we're not actually going to recalculate anything */ 04369 if(t->mode == TFM_DUMMY) 04370 return; 04371 04372 /* makes sure base flags and object flags are identical */ 04373 copy_baseflags(t->scene); 04374 04375 /* handle pending update events, otherwise they got copied below */ 04376 for (base= scene->base.first; base; base= base->next) { 04377 if(base->object->recalc) 04378 object_handle_update(t->scene, base->object); 04379 } 04380 04381 for (base= scene->base.first; base; base= base->next) { 04382 base->flag &= ~BA_WAS_SEL; 04383 04384 if(TESTBASELIB_BGMODE(v3d, scene, base)) { 04385 Object *ob= base->object; 04386 Object *parsel= ob->parent; 04387 04388 /* if parent selected, deselect */ 04389 while(parsel) { 04390 if(parsel->flag & SELECT) { 04391 Base *parbase = object_in_scene(parsel, scene); 04392 if(parbase) { /* in rare cases this can fail */ 04393 if TESTBASELIB_BGMODE(v3d, scene, parbase) { 04394 break; 04395 } 04396 } 04397 } 04398 parsel= parsel->parent; 04399 } 04400 04401 if(parsel) 04402 { 04403 /* rotation around local centers are allowed to propagate */ 04404 if ((t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) && t->around == V3D_LOCAL) { 04405 base->flag |= BA_TRANSFORM_CHILD; 04406 } else { 04407 base->flag &= ~SELECT; 04408 base->flag |= BA_WAS_SEL; 04409 } 04410 } 04411 /* used for flush, depgraph will change recalcs if needed :) */ 04412 ob->recalc |= OB_RECALC_OB; 04413 } 04414 } 04415 04416 /* all recalc flags get flushed to all layers, so a layer flip later on works fine */ 04417 DAG_scene_flush_update(G.main, t->scene, -1, 0); 04418 04419 /* and we store them temporal in base (only used for transform code) */ 04420 /* this because after doing updates, the object->recalc is cleared */ 04421 for (base= scene->base.first; base; base= base->next) { 04422 if(base->object->recalc & OB_RECALC_OB) 04423 base->flag |= BA_HAS_RECALC_OB; 04424 if(base->object->recalc & OB_RECALC_DATA) 04425 base->flag |= BA_HAS_RECALC_DATA; 04426 } 04427 } 04428 04429 static int mark_children(Object *ob) 04430 { 04431 if (ob->flag & (SELECT|BA_TRANSFORM_CHILD)) 04432 return 1; 04433 04434 if (ob->parent) 04435 { 04436 if (mark_children(ob->parent)) 04437 { 04438 ob->flag |= BA_TRANSFORM_CHILD; 04439 return 1; 04440 } 04441 } 04442 04443 return 0; 04444 } 04445 04446 static int count_proportional_objects(TransInfo *t) 04447 { 04448 int total = 0; 04449 Scene *scene = t->scene; 04450 View3D *v3d = t->view; 04451 Base *base; 04452 04453 /* rotations around local centers are allowed to propagate, so we take all objects */ 04454 if (!((t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) && t->around == V3D_LOCAL)) 04455 { 04456 /* mark all parents */ 04457 for (base= scene->base.first; base; base= base->next) { 04458 if(TESTBASELIB_BGMODE(v3d, scene, base)) { 04459 Object *parent = base->object->parent; 04460 04461 /* flag all parents */ 04462 while(parent) { 04463 parent->flag |= BA_TRANSFORM_PARENT; 04464 parent = parent->parent; 04465 } 04466 } 04467 } 04468 04469 /* mark all children */ 04470 for (base= scene->base.first; base; base= base->next) { 04471 /* all base not already selected or marked that is editable */ 04472 if ( (base->object->flag & (SELECT|BA_TRANSFORM_CHILD|BA_TRANSFORM_PARENT)) == 0 && 04473 (BASE_EDITABLE_BGMODE(v3d, scene, base))) 04474 { 04475 mark_children(base->object); 04476 } 04477 } 04478 } 04479 04480 for (base= scene->base.first; base; base= base->next) { 04481 Object *ob= base->object; 04482 04483 /* if base is not selected, not a parent of selection or not a child of selection and it is editable */ 04484 if ( (ob->flag & (SELECT|BA_TRANSFORM_CHILD|BA_TRANSFORM_PARENT)) == 0 && 04485 (BASE_EDITABLE_BGMODE(v3d, scene, base))) 04486 { 04487 04488 /* used for flush, depgraph will change recalcs if needed :) */ 04489 ob->recalc |= OB_RECALC_OB; 04490 04491 total += 1; 04492 } 04493 } 04494 04495 04496 /* all recalc flags get flushed to all layers, so a layer flip later on works fine */ 04497 DAG_scene_flush_update(G.main, t->scene, -1, 0); 04498 04499 /* and we store them temporal in base (only used for transform code) */ 04500 /* this because after doing updates, the object->recalc is cleared */ 04501 for (base= scene->base.first; base; base= base->next) { 04502 if(base->object->recalc & OB_RECALC_OB) 04503 base->flag |= BA_HAS_RECALC_OB; 04504 if(base->object->recalc & OB_RECALC_DATA) 04505 base->flag |= BA_HAS_RECALC_DATA; 04506 } 04507 04508 return total; 04509 } 04510 04511 static void clear_trans_object_base_flags(TransInfo *t) 04512 { 04513 Scene *sce = t->scene; 04514 Base *base; 04515 04516 for (base= sce->base.first; base; base = base->next) 04517 { 04518 if(base->flag & BA_WAS_SEL) 04519 base->flag |= SELECT; 04520 04521 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_TEMP_TAG|BA_TRANSFORM_CHILD|BA_TRANSFORM_PARENT); 04522 } 04523 } 04524 04525 /* auto-keyframing feature - for objects 04526 * tmode: should be a transform mode 04527 */ 04528 // NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases 04529 void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, int tmode) 04530 { 04531 ID *id= &ob->id; 04532 FCurve *fcu; 04533 04534 // TODO: this should probably be done per channel instead... 04535 if (autokeyframe_cfra_can_key(scene, id)) { 04536 ReportList *reports = CTX_wm_reports(C); 04537 KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene); 04538 ListBase dsources = {NULL, NULL}; 04539 float cfra= (float)CFRA; // xxx this will do for now 04540 short flag = 0; 04541 04542 /* get flags used for inserting keyframes */ 04543 flag = ANIM_get_keyframing_flags(scene, 1); 04544 04545 /* add datasource override for the camera object */ 04546 ANIM_relative_keyingset_add_source(&dsources, id, NULL, NULL); 04547 04548 if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) { 04549 /* only insert into active keyingset 04550 * NOTE: we assume here that the active Keying Set does not need to have its iterator overridden spe 04551 */ 04552 ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra); 04553 } 04554 else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) { 04555 AnimData *adt= ob->adt; 04556 04557 /* only key on available channels */ 04558 if (adt && adt->action) { 04559 for (fcu= adt->action->curves.first; fcu; fcu= fcu->next) { 04560 fcu->flag &= ~FCURVE_SELECTED; 04561 insert_keyframe(reports, id, adt->action, 04562 (fcu->grp ? fcu->grp->name : NULL), 04563 fcu->rna_path, fcu->array_index, cfra, flag); 04564 } 04565 } 04566 } 04567 else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) { 04568 short doLoc=0, doRot=0, doScale=0; 04569 04570 /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */ 04571 if (tmode == TFM_TRANSLATION) { 04572 doLoc = 1; 04573 } 04574 else if (tmode == TFM_ROTATION) { 04575 if (v3d->around == V3D_ACTIVE) { 04576 if (ob != OBACT) 04577 doLoc = 1; 04578 } 04579 else if (v3d->around == V3D_CURSOR) 04580 doLoc = 1; 04581 04582 if ((v3d->flag & V3D_ALIGN)==0) 04583 doRot = 1; 04584 } 04585 else if (tmode == TFM_RESIZE) { 04586 if (v3d->around == V3D_ACTIVE) { 04587 if (ob != OBACT) 04588 doLoc = 1; 04589 } 04590 else if (v3d->around == V3D_CURSOR) 04591 doLoc = 1; 04592 04593 if ((v3d->flag & V3D_ALIGN)==0) 04594 doScale = 1; 04595 } 04596 04597 /* insert keyframes for the affected sets of channels using the builtin KeyingSets found */ 04598 if (doLoc) { 04599 KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID); 04600 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); 04601 } 04602 if (doRot) { 04603 KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID); 04604 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); 04605 } 04606 if (doScale) { 04607 KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID); 04608 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); 04609 } 04610 } 04611 /* insert keyframe in all (transform) channels */ 04612 else { 04613 KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID); 04614 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); 04615 } 04616 04617 /* free temp info */ 04618 BLI_freelistN(&dsources); 04619 } 04620 } 04621 04622 /* auto-keyframing feature - for poses/pose-channels 04623 * tmode: should be a transform mode 04624 * targetless_ik: has targetless ik been done on any channels? 04625 */ 04626 // NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases 04627 void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, int tmode, short targetless_ik) 04628 { 04629 ID *id= &ob->id; 04630 AnimData *adt= ob->adt; 04631 bAction *act= (adt) ? adt->action : NULL; 04632 bPose *pose= ob->pose; 04633 bPoseChannel *pchan; 04634 FCurve *fcu; 04635 04636 // TODO: this should probably be done per channel instead... 04637 if (autokeyframe_cfra_can_key(scene, id)) { 04638 ReportList *reports = CTX_wm_reports(C); 04639 KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene); 04640 float cfra= (float)CFRA; 04641 short flag= 0; 04642 04643 /* flag is initialised from UserPref keyframing settings 04644 * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get 04645 * visual keyframes even if flag not set, as it's not that useful otherwise 04646 * (for quick animation recording) 04647 */ 04648 flag = ANIM_get_keyframing_flags(scene, 1); 04649 04650 if (targetless_ik) 04651 flag |= INSERTKEY_MATRIX; 04652 04653 for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { 04654 if (pchan->bone->flag & BONE_TRANSFORM) { 04655 ListBase dsources = {NULL, NULL}; 04656 04657 /* clear any 'unkeyed' flag it may have */ 04658 pchan->bone->flag &= ~BONE_UNKEYED; 04659 04660 /* add datasource override for the camera object */ 04661 ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan); 04662 04663 /* only insert into active keyingset? */ 04664 if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) { 04665 /* run the active Keying Set on the current datasource */ 04666 ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra); 04667 } 04668 /* only insert into available channels? */ 04669 else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) { 04670 if (act) { 04671 for (fcu= act->curves.first; fcu; fcu= fcu->next) { 04672 /* only insert keyframes for this F-Curve if it affects the current bone */ 04673 if (strstr(fcu->rna_path, "bones")) { 04674 char *pchanName= BLI_getQuotedStr(fcu->rna_path, "bones["); 04675 04676 /* only if bone name matches too... 04677 * NOTE: this will do constraints too, but those are ok to do here too? 04678 */ 04679 if (pchanName && strcmp(pchanName, pchan->name) == 0) 04680 insert_keyframe(reports, id, act, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag); 04681 04682 if (pchanName) MEM_freeN(pchanName); 04683 } 04684 } 04685 } 04686 } 04687 /* only insert keyframe if needed? */ 04688 else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) { 04689 short doLoc=0, doRot=0, doScale=0; 04690 04691 /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */ 04692 if (tmode == TFM_TRANSLATION) { 04693 if (targetless_ik) 04694 doRot= 1; 04695 else 04696 doLoc = 1; 04697 } 04698 else if (tmode == TFM_ROTATION) { 04699 if (ELEM(v3d->around, V3D_CURSOR, V3D_ACTIVE)) 04700 doLoc = 1; 04701 04702 if ((v3d->flag & V3D_ALIGN)==0) 04703 doRot = 1; 04704 } 04705 else if (tmode == TFM_RESIZE) { 04706 if (ELEM(v3d->around, V3D_CURSOR, V3D_ACTIVE)) 04707 doLoc = 1; 04708 04709 if ((v3d->flag & V3D_ALIGN)==0) 04710 doScale = 1; 04711 } 04712 04713 if (doLoc) { 04714 KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID); 04715 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); 04716 } 04717 if (doRot) { 04718 KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID); 04719 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); 04720 } 04721 if (doScale) { 04722 KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID); 04723 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); 04724 } 04725 } 04726 /* insert keyframe in all (transform) channels */ 04727 else { 04728 KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID); 04729 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); 04730 } 04731 04732 /* free temp info */ 04733 BLI_freelistN(&dsources); 04734 } 04735 } 04736 04737 /* do the bone paths 04738 * - only do this when there is context info, since we need that to resolve 04739 * how to do the updates and so on... 04740 * - do not calculate unless there are paths already to update... 04741 */ 04742 if (C && (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { 04743 //ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear 04744 ED_pose_recalculate_paths(scene, ob); 04745 } 04746 } 04747 else { 04748 /* tag channels that should have unkeyed data */ 04749 for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { 04750 if (pchan->bone->flag & BONE_TRANSFORM) { 04751 /* tag this channel */ 04752 pchan->bone->flag |= BONE_UNKEYED; 04753 } 04754 } 04755 } 04756 } 04757 04758 04759 /* inserting keys, pointcache, redraw events... */ 04760 /* 04761 * note: sequencer freeing has its own function now because of a conflict with transform's order of freeing (campbell) 04762 * Order changed, the sequencer stuff should go back in here 04763 * */ 04764 void special_aftertrans_update(bContext *C, TransInfo *t) 04765 { 04766 Object *ob; 04767 // short redrawipo=0, resetslowpar=1; 04768 int cancelled= (t->state == TRANS_CANCEL); 04769 short duplicate= (t->mode == TFM_TIME_DUPLICATE); 04770 04771 /* early out when nothing happened */ 04772 if (t->total == 0 || t->mode == TFM_DUMMY) 04773 return; 04774 04775 if (t->spacetype==SPACE_VIEW3D) { 04776 if (t->obedit) { 04777 if (cancelled==0) { 04778 EM_automerge(t->scene, t->obedit, 1); 04779 } 04780 } 04781 } 04782 04783 if (t->spacetype == SPACE_SEQ) { 04784 /* freeSeqData in transform_conversions.c does this 04785 * keep here so the else at the end wont run... */ 04786 04787 SpaceSeq *sseq= (SpaceSeq *)t->sa->spacedata.first; 04788 04789 /* marker transform, not especially nice but we may want to move markers 04790 * at the same time as keyframes in the dope sheet. */ 04791 if ((sseq->flag & SEQ_MARKER_TRANS) && (cancelled == 0)) { 04792 /* cant use , TFM_TIME_EXTEND 04793 * for some reason EXTEND is changed into TRANSLATE, so use frame_side instead */ 04794 04795 if(t->mode == TFM_SEQ_SLIDE) { 04796 if(t->frame_side == 'B') 04797 ED_markers_post_apply_transform(&t->scene->markers, t->scene, TFM_TIME_TRANSLATE, t->values[0], t->frame_side); 04798 } 04799 else if (ELEM(t->frame_side, 'L', 'R')) { 04800 ED_markers_post_apply_transform(&t->scene->markers, t->scene, TFM_TIME_EXTEND, t->values[0], t->frame_side); 04801 } 04802 } 04803 04804 } 04805 else if (t->spacetype == SPACE_NODE) { 04806 SpaceNode *snode= (SpaceNode *)t->sa->spacedata.first; 04807 ED_node_update_hierarchy(C, snode->edittree); 04808 04809 if(cancelled == 0) 04810 ED_node_link_insert(t->sa); 04811 04812 /* clear link line */ 04813 ED_node_link_intersect_test(t->sa, 0); 04814 } 04815 else if (t->spacetype == SPACE_CLIP) { 04816 SpaceClip *sc= t->sa->spacedata.first; 04817 MovieClip *clip= ED_space_clip(sc); 04818 04819 if(t->scene->nodetree) { 04820 /* tracks can be used for stabilization nodes, 04821 flush update for such nodes */ 04822 nodeUpdateID(t->scene->nodetree, &clip->id); 04823 WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); 04824 } 04825 } 04826 else if (t->spacetype == SPACE_ACTION) { 04827 SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; 04828 bAnimContext ac; 04829 04830 /* initialise relevant anim-context 'context' data */ 04831 if (ANIM_animdata_get_context(C, &ac) == 0) 04832 return; 04833 04834 ob = ac.obact; 04835 04836 if (ELEM(ac.datatype, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) { 04837 ListBase anim_data = {NULL, NULL}; 04838 bAnimListElem *ale; 04839 short filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/); 04840 04841 /* get channels to work on */ 04842 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 04843 04844 /* these should all be F-Curves */ 04845 for (ale= anim_data.first; ale; ale= ale->next) { 04846 AnimData *adt= ANIM_nla_mapping_get(&ac, ale); 04847 FCurve *fcu= (FCurve *)ale->key_data; 04848 04849 /* 3 cases here for curve cleanups: 04850 * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done 04851 * 2) cancelled == 0 -> user confirmed the transform, so duplicates should be removed 04852 * 3) cancelled + duplicate -> user cancelled the transform, but we made duplicates, so get rid of these 04853 */ 04854 if ( (saction->flag & SACTION_NOTRANSKEYCULL)==0 && 04855 ((cancelled == 0) || (duplicate)) ) 04856 { 04857 if (adt) { 04858 ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1); 04859 posttrans_fcurve_clean(fcu, FALSE); /* only use handles in graph editor */ 04860 ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1); 04861 } 04862 else 04863 posttrans_fcurve_clean(fcu, FALSE); /* only use handles in graph editor */ 04864 } 04865 } 04866 04867 /* free temp memory */ 04868 BLI_freelistN(&anim_data); 04869 } 04870 else if (ac.datatype == ANIMCONT_ACTION) { // TODO: just integrate into the above... 04871 /* Depending on the lock status, draw necessary views */ 04872 // fixme... some of this stuff is not good 04873 if (ob) { 04874 if (ob->pose || ob_get_key(ob)) 04875 DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); 04876 else 04877 DAG_id_tag_update(&ob->id, OB_RECALC_OB); 04878 } 04879 04880 /* 3 cases here for curve cleanups: 04881 * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done 04882 * 2) cancelled == 0 -> user confirmed the transform, so duplicates should be removed 04883 * 3) cancelled + duplicate -> user cancelled the transform, but we made duplicates, so get rid of these 04884 */ 04885 if ( (saction->flag & SACTION_NOTRANSKEYCULL)==0 && 04886 ((cancelled == 0) || (duplicate)) ) 04887 { 04888 posttrans_action_clean(&ac, (bAction *)ac.data); 04889 } 04890 } 04891 else if (ac.datatype == ANIMCONT_GPENCIL) { 04892 /* remove duplicate frames and also make sure points are in order! */ 04893 /* 3 cases here for curve cleanups: 04894 * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done 04895 * 2) cancelled == 0 -> user confirmed the transform, so duplicates should be removed 04896 * 3) cancelled + duplicate -> user cancelled the transform, but we made duplicates, so get rid of these 04897 */ 04898 if ( (saction->flag & SACTION_NOTRANSKEYCULL)==0 && 04899 ((cancelled == 0) || (duplicate)) ) 04900 { 04901 bGPdata *gpd; 04902 04903 // XXX: BAD! this get gpencil datablocks directly from main db... 04904 // but that's how this currently works :/ 04905 for (gpd = G.main->gpencil.first; gpd; gpd = gpd->id.next) { 04906 if (ID_REAL_USERS(gpd)) 04907 posttrans_gpd_clean(gpd); 04908 } 04909 } 04910 } 04911 04912 /* marker transform, not especially nice but we may want to move markers 04913 * at the same time as keyframes in the dope sheet. 04914 */ 04915 if ((saction->flag & SACTION_MARKERS_MOVE) && (cancelled == 0)) { 04916 if (t->mode == TFM_TIME_TRANSLATE) { 04917 #if 0 04918 if (ELEM(t->frame_side, 'L', 'R')) { /* TFM_TIME_EXTEND */ 04919 /* same as below */ 04920 ED_markers_post_apply_transform(ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side); 04921 } 04922 else /* TFM_TIME_TRANSLATE */ 04923 #endif 04924 { 04925 ED_markers_post_apply_transform(ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side); 04926 } 04927 } 04928 else if (t->mode == TFM_TIME_SCALE) { 04929 ED_markers_post_apply_transform(ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side); 04930 } 04931 } 04932 04933 /* make sure all F-Curves are set correctly */ 04934 if (ac.datatype != ANIMCONT_GPENCIL) 04935 ANIM_editkeyframes_refresh(&ac); 04936 04937 /* clear flag that was set for time-slide drawing */ 04938 saction->flag &= ~SACTION_MOVING; 04939 } 04940 else if (t->spacetype == SPACE_IPO) { 04941 SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first; 04942 bAnimContext ac; 04943 const short use_handle = !(sipo->flag & SIPO_NOHANDLES); 04944 04945 /* initialise relevant anim-context 'context' data */ 04946 if (ANIM_animdata_get_context(C, &ac) == 0) 04947 return; 04948 04949 if (ac.datatype) 04950 { 04951 ListBase anim_data = {NULL, NULL}; 04952 bAnimListElem *ale; 04953 short filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE); 04954 04955 /* get channels to work on */ 04956 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 04957 04958 for (ale= anim_data.first; ale; ale= ale->next) { 04959 AnimData *adt= ANIM_nla_mapping_get(&ac, ale); 04960 FCurve *fcu= (FCurve *)ale->key_data; 04961 04962 /* 3 cases here for curve cleanups: 04963 * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done 04964 * 2) cancelled == 0 -> user confirmed the transform, so duplicates should be removed 04965 * 3) cancelled + duplicate -> user cancelled the transform, but we made duplicates, so get rid of these 04966 */ 04967 if ( (sipo->flag & SIPO_NOTRANSKEYCULL)==0 && 04968 ((cancelled == 0) || (duplicate)) ) 04969 { 04970 if (adt) { 04971 ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0); 04972 posttrans_fcurve_clean(fcu, use_handle); 04973 ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0); 04974 } 04975 else 04976 posttrans_fcurve_clean(fcu, use_handle); 04977 } 04978 } 04979 04980 /* free temp memory */ 04981 BLI_freelistN(&anim_data); 04982 } 04983 04984 /* Make sure all F-Curves are set correctly, but not if transform was 04985 * canceled, since then curves were already restored to initial state. 04986 * Note: if the refresh is really needed after cancel then some way 04987 * has to be added to not update handle types (see bug 22289). 04988 */ 04989 if(!cancelled) 04990 ANIM_editkeyframes_refresh(&ac); 04991 } 04992 else if (t->spacetype == SPACE_NLA) { 04993 bAnimContext ac; 04994 04995 /* initialise relevant anim-context 'context' data */ 04996 if (ANIM_animdata_get_context(C, &ac) == 0) 04997 return; 04998 04999 if (ac.datatype) 05000 { 05001 ListBase anim_data = {NULL, NULL}; 05002 bAnimListElem *ale; 05003 short filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT); 05004 05005 /* get channels to work on */ 05006 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 05007 05008 for (ale= anim_data.first; ale; ale= ale->next) { 05009 NlaTrack *nlt= (NlaTrack *)ale->data; 05010 05011 /* make sure strips are in order again */ 05012 BKE_nlatrack_sort_strips(nlt); 05013 05014 /* remove the temp metas */ 05015 BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); 05016 } 05017 05018 /* free temp memory */ 05019 BLI_freelistN(&anim_data); 05020 05021 /* perform after-transfrom validation */ 05022 ED_nla_postop_refresh(&ac); 05023 } 05024 } 05025 else if (t->obedit) { 05026 if (t->obedit->type == OB_MESH) 05027 { 05028 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh; 05029 /* table needs to be created for each edit command, since vertices can move etc */ 05030 mesh_octree_table(t->obedit, em, NULL, 'e'); 05031 } 05032 } 05033 else if ((t->flag & T_POSE) && (t->poseobj)) { 05034 bArmature *arm; 05035 bPoseChannel *pchan; 05036 short targetless_ik= 0; 05037 05038 ob= t->poseobj; 05039 arm= ob->data; 05040 05041 if((t->flag & T_AUTOIK) && (t->options & CTX_AUTOCONFIRM)) { 05042 /* when running transform non-interactively (operator exec), 05043 * we need to update the pose otherwise no updates get called during 05044 * transform and the auto-ik is not applied. see [#26164] */ 05045 struct Object *pose_ob=t->poseobj; 05046 where_is_pose(t->scene, pose_ob); 05047 } 05048 05049 /* set BONE_TRANSFORM flags for autokey, manipulator draw might have changed them */ 05050 if (!cancelled && (t->mode != TFM_DUMMY)) 05051 count_set_pose_transflags(&t->mode, t->around, ob); 05052 05053 /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */ 05054 if (!cancelled && t->mode==TFM_TRANSLATION) 05055 targetless_ik= apply_targetless_ik(ob); 05056 else { 05057 /* not forget to clear the auto flag */ 05058 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { 05059 bKinematicConstraint *data= has_targetless_ik(pchan); 05060 if(data) data->flag &= ~CONSTRAINT_IK_AUTO; 05061 } 05062 } 05063 05064 if (t->mode==TFM_TRANSLATION) 05065 pose_grab_with_ik_clear(ob); 05066 05067 /* automatic inserting of keys and unkeyed tagging - only if transform wasn't cancelled (or TFM_DUMMY) */ 05068 if (!cancelled && (t->mode != TFM_DUMMY)) { 05069 autokeyframe_pose_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode, targetless_ik); 05070 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 05071 } 05072 else if (arm->flag & ARM_DELAYDEFORM) { 05073 /* old optimize trick... this enforces to bypass the depgraph */ 05074 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 05075 ob->recalc= 0; // is set on OK position already by recalcData() 05076 } 05077 else 05078 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 05079 05080 } 05081 else if ( (t->scene->basact) && 05082 (ob = t->scene->basact->object) && 05083 (ob->mode & OB_MODE_PARTICLE_EDIT) && 05084 PE_get_current(t->scene, ob)) 05085 { 05086 /* do nothing */ ; 05087 } 05088 else { /* Objects */ 05089 int i, recalcObPaths=0; 05090 05091 for (i = 0; i < t->total; i++) { 05092 TransData *td = t->data + i; 05093 ListBase pidlist; 05094 PTCacheID *pid; 05095 ob = td->ob; 05096 05097 if (td->flag & TD_NOACTION) 05098 break; 05099 05100 if (td->flag & TD_SKIP) 05101 continue; 05102 05103 /* flag object caches as outdated */ 05104 BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR); 05105 for(pid=pidlist.first; pid; pid=pid->next) { 05106 if(pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */ 05107 pid->cache->flag |= PTCACHE_OUTDATED; 05108 } 05109 BLI_freelistN(&pidlist); 05110 05111 /* pointcache refresh */ 05112 if (BKE_ptcache_object_reset(t->scene, ob, PTCACHE_RESET_OUTDATED)) 05113 ob->recalc |= OB_RECALC_DATA; 05114 05115 /* Needed for proper updating of "quick cached" dynamics. */ 05116 /* Creates troubles for moving animated objects without */ 05117 /* autokey though, probably needed is an anim sys override? */ 05118 /* Please remove if some other solution is found. -jahka */ 05119 DAG_id_tag_update(&ob->id, OB_RECALC_OB); 05120 05121 /* Set autokey if necessary */ 05122 if (!cancelled) { 05123 autokeyframe_ob_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode); 05124 05125 /* only calculate paths if there are paths to be recalculated */ 05126 if (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) 05127 recalcObPaths= 1; 05128 } 05129 } 05130 05131 /* recalculate motion paths for objects (if necessary) 05132 * NOTE: only do this when there is context info 05133 */ 05134 if (C && recalcObPaths) { 05135 //ED_objects_clear_paths(C); // XXX for now, don't need to clear 05136 ED_objects_recalculate_paths(C, t->scene); 05137 05138 /* recalculating the frame positions means we loose our original transform if its not auto-keyed [#24451] 05139 * this hack re-applies it, which is annoying, only alternatives are... 05140 * - dont recalc paths. 05141 * - have an object_handle_update() which gives is the new transform without touching the objects. 05142 * - only recalc paths on auto-keying. 05143 * - ED_objects_recalculate_paths could backup/restore transforms. 05144 * - re-apply the transform which is simplest in this case. (2 lines below) 05145 */ 05146 t->redraw |= TREDRAW_HARD; 05147 transformApply(C, t); 05148 } 05149 } 05150 05151 clear_trans_object_base_flags(t); 05152 05153 05154 #if 0 // TRANSFORM_FIX_ME 05155 if(resetslowpar) 05156 reset_slowparents(); 05157 #endif 05158 } 05159 05160 static void createTransObject(bContext *C, TransInfo *t) 05161 { 05162 TransData *td = NULL; 05163 TransDataExtension *tx; 05164 int propmode = t->flag & T_PROP_EDIT; 05165 05166 set_trans_object_base_flags(t); 05167 05168 /* count */ 05169 t->total= CTX_DATA_COUNT(C, selected_objects); 05170 05171 if(!t->total) { 05172 /* clear here, main transform function escapes too */ 05173 clear_trans_object_base_flags(t); 05174 return; 05175 } 05176 05177 if (propmode) 05178 { 05179 t->total += count_proportional_objects(t); 05180 } 05181 05182 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb"); 05183 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension"); 05184 05185 CTX_DATA_BEGIN(C, Base*, base, selected_bases) 05186 { 05187 Object *ob= base->object; 05188 05189 td->flag = TD_SELECTED; 05190 td->protectflag= ob->protectflag; 05191 td->ext = tx; 05192 td->ext->rotOrder= ob->rotmode; 05193 05194 if (base->flag & BA_TRANSFORM_CHILD) 05195 { 05196 td->flag |= TD_NOCENTER; 05197 td->flag |= TD_NO_LOC; 05198 } 05199 05200 /* select linked objects, but skip them later */ 05201 if (ob->id.lib != NULL) { 05202 td->flag |= TD_SKIP; 05203 } 05204 05205 ObjectToTransData(t, td, ob); 05206 td->val = NULL; 05207 td++; 05208 tx++; 05209 } 05210 CTX_DATA_END; 05211 05212 if (propmode) 05213 { 05214 Scene *scene = t->scene; 05215 View3D *v3d = t->view; 05216 Base *base; 05217 05218 for (base= scene->base.first; base; base= base->next) { 05219 Object *ob= base->object; 05220 05221 /* if base is not selected, not a parent of selection or not a child of selection and it is editable */ 05222 if ((ob->flag & (SELECT|BA_TRANSFORM_CHILD|BA_TRANSFORM_PARENT)) == 0 && BASE_EDITABLE_BGMODE(v3d, scene, base)) 05223 { 05224 td->protectflag= ob->protectflag; 05225 td->ext = tx; 05226 td->ext->rotOrder= ob->rotmode; 05227 05228 ObjectToTransData(t, td, ob); 05229 td->val = NULL; 05230 td++; 05231 tx++; 05232 } 05233 } 05234 } 05235 } 05236 05237 /* transcribe given node into TransData2D for Transforming */ 05238 static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node) 05239 // static void NodeToTransData(bContext *C, TransInfo *t, TransData2D *td, bNode *node) 05240 { 05241 td2d->loc[0] = node->locx; /* hold original location */ 05242 td2d->loc[1] = node->locy; 05243 td2d->loc[2] = 0.0f; 05244 td2d->loc2d = &node->locx; /* current location */ 05245 05246 td->flag = 0; 05247 /* exclude nodes whose parent is also transformed */ 05248 if (node->parent && (node->parent->flag & NODE_TRANSFORM)) { 05249 td->flag |= TD_SKIP; 05250 } 05251 05252 td->loc = td2d->loc; 05253 copy_v3_v3(td->center, td->loc); 05254 copy_v3_v3(td->iloc, td->loc); 05255 05256 memset(td->axismtx, 0, sizeof(td->axismtx)); 05257 td->axismtx[2][2] = 1.0f; 05258 05259 td->ext= NULL; td->val= NULL; 05260 05261 td->flag |= TD_SELECTED; 05262 td->dist= 0.0; 05263 05264 unit_m3(td->mtx); 05265 unit_m3(td->smtx); 05266 } 05267 05268 static void createTransNodeData(bContext *C, TransInfo *t) 05269 { 05270 TransData *td; 05271 TransData2D *td2d; 05272 SpaceNode *snode= t->sa->spacedata.first; 05273 bNode *node; 05274 05275 if(!snode->edittree) { 05276 t->total= 0; 05277 return; 05278 } 05279 05280 /* set transform flags on nodes */ 05281 for (node=snode->edittree->nodes.first; node; node=node->next) { 05282 if ((node->flag & NODE_SELECT) || (node->parent && (node->parent->flag & NODE_TRANSFORM))) 05283 node->flag |= NODE_TRANSFORM; 05284 else 05285 node->flag &= ~NODE_TRANSFORM; 05286 } 05287 05288 t->total= CTX_DATA_COUNT(C, selected_nodes); 05289 05290 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransNode TransData"); 05291 td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransNode TransData2D"); 05292 05293 CTX_DATA_BEGIN(C, bNode *, selnode, selected_nodes) 05294 NodeToTransData(td++, td2d++, selnode); 05295 CTX_DATA_END 05296 } 05297 05298 /* *** CLIP EDITOR *** */ 05299 05300 typedef struct TransDataTracking { 05301 int area; 05302 float *relative, *loc; 05303 float soffset[2], srelative[2]; 05304 float offset[2]; 05305 05306 float (*smarkers)[2]; 05307 int markersnr; 05308 MovieTrackingMarker *markers; 05309 } TransDataTracking; 05310 05311 static void markerToTransDataInit(TransData *td, TransData2D *td2d, 05312 TransDataTracking *tdt, MovieTrackingTrack *track, int area, float *loc, float *rel, float *off) 05313 { 05314 int anchor = area==TRACK_AREA_POINT && off; 05315 05316 if(anchor) { 05317 td2d->loc[0] = rel[0]; /* hold original location */ 05318 td2d->loc[1] = rel[1]; 05319 05320 tdt->loc= loc; 05321 td2d->loc2d = loc; /* current location */ 05322 } else { 05323 td2d->loc[0] = loc[0]; /* hold original location */ 05324 td2d->loc[1] = loc[1]; 05325 05326 td2d->loc2d = loc; /* current location */ 05327 } 05328 td2d->loc[2] = 0.0f; 05329 05330 tdt->relative= rel; 05331 tdt->area= area; 05332 05333 tdt->markersnr= track->markersnr; 05334 tdt->markers= track->markers; 05335 05336 if(rel) { 05337 if(!anchor) { 05338 td2d->loc[0]+= rel[0]; 05339 td2d->loc[1]+= rel[1]; 05340 } 05341 05342 copy_v2_v2(tdt->srelative, rel); 05343 } 05344 05345 if(off) 05346 copy_v2_v2(tdt->soffset, off); 05347 05348 td->flag = 0; 05349 td->loc = td2d->loc; 05350 VECCOPY(td->center, td->loc); 05351 VECCOPY(td->iloc, td->loc); 05352 05353 memset(td->axismtx, 0, sizeof(td->axismtx)); 05354 td->axismtx[2][2] = 1.0f; 05355 05356 td->ext= NULL; td->val= NULL; 05357 05358 td->flag |= TD_SELECTED; 05359 td->dist= 0.0; 05360 05361 unit_m3(td->mtx); 05362 unit_m3(td->smtx); 05363 } 05364 05365 static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d, 05366 TransDataTracking *tdt, MovieTrackingTrack *track) 05367 { 05368 MovieTrackingMarker *marker= BKE_tracking_ensure_marker(track, sc->user.framenr); 05369 05370 track->transflag= marker->flag; 05371 05372 marker->flag&= ~(MARKER_DISABLED|MARKER_TRACKED); 05373 05374 markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_POINT, track->offset, marker->pos, track->offset); 05375 05376 if(track->flag&SELECT) 05377 markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_POINT, marker->pos, NULL, NULL); 05378 05379 if(track->pat_flag&SELECT) { 05380 markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, track->pat_min, marker->pos, NULL); 05381 markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, track->pat_max, marker->pos, NULL); 05382 } 05383 05384 if(track->search_flag&SELECT) { 05385 markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_SEARCH, track->search_min, marker->pos, NULL); 05386 markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_SEARCH, track->search_max, marker->pos, NULL); 05387 } 05388 } 05389 05390 static void transDataTrackingFree(TransInfo *t) 05391 { 05392 TransDataTracking *tdt= t->customData; 05393 05394 if(tdt) { 05395 if(tdt->smarkers) MEM_freeN(tdt->smarkers); 05396 MEM_freeN(tdt); 05397 } 05398 } 05399 05400 static void createTransTrackingData(bContext *C, TransInfo *t) 05401 { 05402 TransData *td; 05403 TransData2D *td2d; 05404 SpaceClip *sc = CTX_wm_space_clip(C); 05405 MovieClip *clip = ED_space_clip(sc); 05406 ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); 05407 MovieTrackingTrack *track; 05408 MovieTrackingMarker *marker; 05409 TransDataTracking *tdt; 05410 int framenr = sc->user.framenr; 05411 05412 if(!clip || !BKE_movieclip_has_frame(clip, &sc->user)) { 05413 t->total = 0; 05414 return; 05415 } 05416 05417 /* count */ 05418 t->total = 0; 05419 05420 track = tracksbase->first; 05421 while(track) { 05422 if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_LOCKED)==0) { 05423 marker= BKE_tracking_get_marker(track, framenr); 05424 05425 if(marker) { 05426 t->total++; /* offset */ 05427 05428 if(track->flag&SELECT) t->total++; 05429 if(track->pat_flag&SELECT) t->total+= 2; 05430 if(track->search_flag&SELECT) t->total+= 2; 05431 } 05432 } 05433 05434 track = track->next; 05435 } 05436 05437 if(t->total==0) 05438 return; 05439 05440 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransTracking TransData"); 05441 td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransTracking TransData2D"); 05442 tdt = t->customData = MEM_callocN(t->total*sizeof(TransDataTracking), "TransTracking TransDataTracking"); 05443 05444 t->customFree= transDataTrackingFree; 05445 05446 /* create actual data */ 05447 track = tracksbase->first; 05448 while(track) { 05449 if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_LOCKED)==0) { 05450 marker= BKE_tracking_get_marker(track, framenr); 05451 05452 trackToTransData(sc, td, td2d, tdt, track); 05453 05454 /* offset */ 05455 td++; 05456 td2d++; 05457 tdt++; 05458 05459 if((marker->flag&MARKER_DISABLED)==0) { 05460 if(track->flag&SELECT) {td++; td2d++; tdt++;} 05461 if(track->pat_flag&SELECT) {td+= 2; td2d+= 2;tdt+=2;} 05462 } 05463 05464 if(track->search_flag&SELECT) { 05465 td+= 2; 05466 td2d+= 2; 05467 tdt+= 2; 05468 05469 if(marker->flag&MARKER_DISABLED) { 05470 td+= 3; 05471 td2d+= 3; 05472 tdt+= 3; 05473 }; 05474 } 05475 } 05476 05477 track = track->next; 05478 } 05479 } 05480 05481 void flushTransTracking(TransInfo *t) 05482 { 05483 TransData *td; 05484 TransData2D *td2d; 05485 TransDataTracking *tdt; 05486 int a; 05487 05488 /* flush to 2d vector from internally used 3d vector */ 05489 for(a=0, td= t->data, td2d= t->data2d, tdt= t->customData; a<t->total; a++, td2d++, td++, tdt++) { 05490 if(t->flag&T_ALT_TRANSFORM) { 05491 if(tdt->area==TRACK_AREA_POINT && tdt->relative) { 05492 float d[2], d2[2]; 05493 05494 if(!tdt->smarkers) { 05495 tdt->smarkers= MEM_callocN(sizeof(*tdt->smarkers)*tdt->markersnr, "flushTransTracking markers"); 05496 for(a= 0; a<tdt->markersnr; a++) 05497 copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos); 05498 } 05499 05500 sub_v2_v2v2(d, td2d->loc, tdt->soffset); 05501 sub_v2_v2(d, tdt->srelative); 05502 05503 sub_v2_v2v2(d2, td2d->loc, tdt->srelative); 05504 05505 for(a= 0; a<tdt->markersnr; a++) 05506 add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2); 05507 05508 negate_v2_v2(td2d->loc2d, d); 05509 } 05510 } 05511 05512 if(tdt->area!=TRACK_AREA_POINT || tdt->relative==0) { 05513 td2d->loc2d[0] = td2d->loc[0]; 05514 td2d->loc2d[1] = td2d->loc[1]; 05515 05516 if(tdt->relative) 05517 sub_v2_v2(td2d->loc2d, tdt->relative); 05518 } 05519 } 05520 } 05521 05522 void createTransData(bContext *C, TransInfo *t) 05523 { 05524 Scene *scene = t->scene; 05525 Object *ob = OBACT; 05526 05527 if (t->options & CTX_TEXTURE) { 05528 t->flag |= T_TEXTURE; 05529 createTransTexspace(t); 05530 } 05531 else if (t->options & CTX_EDGE) { 05532 t->ext = NULL; 05533 t->flag |= T_EDIT; 05534 createTransEdge(t); 05535 if(t->data && t->flag & T_PROP_EDIT) { 05536 sort_trans_data(t); // makes selected become first in array 05537 set_prop_dist(t, 1); 05538 sort_trans_data_dist(t); 05539 } 05540 } 05541 else if (t->options == CTX_BMESH) { 05542 // TRANSFORM_FIX_ME 05543 //createTransBMeshVerts(t, G.editBMesh->bm, G.editBMesh->td); 05544 } 05545 else if (t->spacetype == SPACE_IMAGE) { 05546 t->flag |= T_POINTS|T_2D_EDIT; 05547 createTransUVs(C, t); 05548 if(t->data && (t->flag & T_PROP_EDIT)) { 05549 sort_trans_data(t); // makes selected become first in array 05550 set_prop_dist(t, 1); 05551 sort_trans_data_dist(t); 05552 } 05553 } 05554 else if (t->spacetype == SPACE_ACTION) { 05555 t->flag |= T_POINTS|T_2D_EDIT; 05556 createTransActionData(C, t); 05557 } 05558 else if (t->spacetype == SPACE_NLA) { 05559 t->flag |= T_POINTS|T_2D_EDIT; 05560 createTransNlaData(C, t); 05561 } 05562 else if (t->spacetype == SPACE_SEQ) { 05563 t->flag |= T_POINTS|T_2D_EDIT; 05564 t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point transformations */ 05565 createTransSeqData(C, t); 05566 } 05567 else if (t->spacetype == SPACE_IPO) { 05568 t->flag |= T_POINTS|T_2D_EDIT; 05569 createTransGraphEditData(C, t); 05570 #if 0 05571 if (t->data && (t->flag & T_PROP_EDIT)) { 05572 sort_trans_data(t); // makes selected become first in array 05573 set_prop_dist(t, 1); 05574 sort_trans_data_dist(t); 05575 } 05576 #endif 05577 } 05578 else if(t->spacetype == SPACE_NODE) { 05579 t->flag |= T_2D_EDIT|T_POINTS; 05580 createTransNodeData(C, t); 05581 if (t->data && (t->flag & T_PROP_EDIT)) { 05582 sort_trans_data(t); // makes selected become first in array 05583 set_prop_dist(t, 1); 05584 sort_trans_data_dist(t); 05585 } 05586 } 05587 else if (t->spacetype == SPACE_CLIP) { 05588 t->flag |= T_POINTS|T_2D_EDIT; 05589 createTransTrackingData(C, t); 05590 } 05591 else if (t->obedit) { 05592 t->ext = NULL; 05593 if (t->obedit->type == OB_MESH) { 05594 createTransEditVerts(C, t); 05595 } 05596 else if ELEM(t->obedit->type, OB_CURVE, OB_SURF) { 05597 createTransCurveVerts(C, t); 05598 } 05599 else if (t->obedit->type==OB_LATTICE) { 05600 createTransLatticeVerts(t); 05601 } 05602 else if (t->obedit->type==OB_MBALL) { 05603 createTransMBallVerts(t); 05604 } 05605 else if (t->obedit->type==OB_ARMATURE) { 05606 t->flag &= ~T_PROP_EDIT; 05607 createTransArmatureVerts(t); 05608 } 05609 else { 05610 printf("edit type not implemented!\n"); 05611 } 05612 05613 t->flag |= T_EDIT|T_POINTS; 05614 05615 if(t->data && t->flag & T_PROP_EDIT) { 05616 if (ELEM(t->obedit->type, OB_CURVE, OB_MESH)) { 05617 sort_trans_data(t); // makes selected become first in array 05618 set_prop_dist(t, 0); 05619 sort_trans_data_dist(t); 05620 } 05621 else { 05622 sort_trans_data(t); // makes selected become first in array 05623 set_prop_dist(t, 1); 05624 sort_trans_data_dist(t); 05625 } 05626 } 05627 05628 /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */ 05629 if(t->mode==TFM_BONESIZE) { 05630 t->flag &= ~(T_EDIT|T_POINTS); 05631 t->flag |= T_POSE; 05632 t->poseobj = ob; /* <- tsk tsk, this is going to give issues one day */ 05633 } 05634 } 05635 else if (ob && (ob->mode & OB_MODE_POSE)) { 05636 // XXX this is currently limited to active armature only... 05637 // XXX active-layer checking isn't done as that should probably be checked through context instead 05638 createTransPose(t, ob); 05639 } 05640 else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) { 05641 /* important that ob_armature can be set even when its not selected [#23412] 05642 * lines below just check is also visible */ 05643 Object *ob_armature= modifiers_isDeformedByArmature(ob); 05644 if(ob_armature && ob_armature->mode & OB_MODE_POSE) { 05645 Base *base_arm= object_in_scene(ob_armature, t->scene); 05646 if(base_arm) { 05647 View3D *v3d = t->view; 05648 if(BASE_VISIBLE(v3d, base_arm)) { 05649 createTransPose(t, ob_armature); 05650 } 05651 } 05652 05653 } 05654 } 05655 else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) 05656 && PE_start_edit(PE_get_current(scene, ob))) { 05657 createTransParticleVerts(C, t); 05658 t->flag |= T_POINTS; 05659 05660 if(t->data && t->flag & T_PROP_EDIT) { 05661 sort_trans_data(t); // makes selected become first in array 05662 set_prop_dist(t, 1); 05663 sort_trans_data_dist(t); 05664 } 05665 } 05666 else if (ob && (ob->mode & (OB_MODE_SCULPT|OB_MODE_TEXTURE_PAINT))) { 05667 /* sculpt mode and project paint have own undo stack 05668 * transform ops redo clears sculpt/project undo stack. 05669 * 05670 * Could use 'OB_MODE_ALL_PAINT' since there are key conflicts, 05671 * transform + paint isnt well supported. */ 05672 } 05673 else { 05674 createTransObject(C, t); 05675 t->flag |= T_OBJECT; 05676 05677 if(t->data && t->flag & T_PROP_EDIT) { 05678 // selected objects are already first, no need to presort 05679 set_prop_dist(t, 1); 05680 sort_trans_data_dist(t); 05681 } 05682 05683 if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) 05684 { 05685 View3D *v3d = t->view; 05686 RegionView3D *rv3d = CTX_wm_region_view3d(C); 05687 if(rv3d && (t->flag & T_OBJECT) && v3d->camera == OBACT && rv3d->persp==RV3D_CAMOB) 05688 { 05689 t->flag |= T_CAMERA; 05690 } 05691 } 05692 } 05693 05694 // TRANSFORM_FIX_ME 05695 // /* temporal...? */ 05696 // t->scene->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */ 05697 } 05698 05699 05700 05701