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 #include <string.h> 00034 #include <math.h> 00035 00036 #include "MEM_guardedalloc.h" 00037 00038 #include "BLO_sys_types.h" // for intptr_t support 00039 00040 #include "DNA_anim_types.h" 00041 #include "DNA_armature_types.h" 00042 #include "DNA_lattice_types.h" 00043 #include "DNA_screen_types.h" 00044 #include "DNA_space_types.h" 00045 #include "DNA_scene_types.h" 00046 #include "DNA_object_types.h" 00047 #include "DNA_meshdata_types.h" 00048 #include "DNA_view3d_types.h" 00049 #include "DNA_modifier_types.h" 00050 #include "DNA_movieclip_types.h" 00051 00052 #include "RNA_access.h" 00053 00054 //#include "BIF_screen.h" 00055 //#include "BIF_mywindow.h" 00056 #include "BIF_gl.h" 00057 #include "BIF_glutil.h" 00058 //#include "BIF_editmesh.h" 00059 //#include "BIF_editsima.h" 00060 //#include "BIF_editparticle.h" 00061 //#include "BIF_meshtools.h" 00062 00063 #include "BKE_animsys.h" 00064 #include "BKE_action.h" 00065 #include "BKE_armature.h" 00066 #include "BKE_curve.h" 00067 #include "BKE_depsgraph.h" 00068 #include "BKE_displist.h" 00069 #include "BKE_fcurve.h" 00070 #include "BKE_lattice.h" 00071 #include "BKE_mesh.h" 00072 #include "BKE_nla.h" 00073 #include "BKE_context.h" 00074 #include "BKE_tracking.h" 00075 00076 #include "ED_anim_api.h" 00077 #include "ED_armature.h" 00078 #include "ED_image.h" 00079 #include "ED_keyframing.h" 00080 #include "ED_markers.h" 00081 #include "ED_mesh.h" 00082 #include "ED_particle.h" 00083 #include "ED_screen_types.h" 00084 #include "ED_space_api.h" 00085 #include "ED_uvedit.h" 00086 #include "ED_view3d.h" 00087 #include "ED_curve.h" /* for curve_editnurbs */ 00088 #include "ED_clip.h" 00089 00090 //#include "BDR_unwrapper.h" 00091 00092 #include "BLI_math.h" 00093 #include "BLI_blenlib.h" 00094 #include "BLI_editVert.h" 00095 #include "BLI_rand.h" 00096 #include "BLI_utildefines.h" 00097 00098 #include "WM_types.h" 00099 #include "WM_api.h" 00100 00101 #include "UI_resources.h" 00102 00103 //#include "blendef.h" 00104 // 00105 //#include "mydevice.h" 00106 00107 #include "transform.h" 00108 00109 extern ListBase editelems; 00110 00111 /* ************************** Functions *************************** */ 00112 00113 void getViewVector(TransInfo *t, float coord[3], float vec[3]) 00114 { 00115 if (t->persp != RV3D_ORTHO) 00116 { 00117 float p1[4], p2[4]; 00118 00119 copy_v3_v3(p1, coord); 00120 p1[3] = 1.0f; 00121 copy_v3_v3(p2, p1); 00122 p2[3] = 1.0f; 00123 mul_m4_v4(t->viewmat, p2); 00124 00125 p2[0] = 2.0f * p2[0]; 00126 p2[1] = 2.0f * p2[1]; 00127 p2[2] = 2.0f * p2[2]; 00128 00129 mul_m4_v4(t->viewinv, p2); 00130 00131 sub_v3_v3v3(vec, p1, p2); 00132 } 00133 else { 00134 copy_v3_v3(vec, t->viewinv[2]); 00135 } 00136 normalize_v3(vec); 00137 } 00138 00139 /* ************************** GENERICS **************************** */ 00140 00141 static void clipMirrorModifier(TransInfo *t, Object *ob) 00142 { 00143 ModifierData *md= ob->modifiers.first; 00144 float tolerance[3] = {0.0f, 0.0f, 0.0f}; 00145 int axis = 0; 00146 00147 for (; md; md=md->next) { 00148 if ((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) { 00149 MirrorModifierData *mmd = (MirrorModifierData*) md; 00150 00151 if(mmd->flag & MOD_MIR_CLIPPING) { 00152 axis = 0; 00153 if(mmd->flag & MOD_MIR_AXIS_X) { 00154 axis |= 1; 00155 tolerance[0] = mmd->tolerance; 00156 } 00157 if(mmd->flag & MOD_MIR_AXIS_Y) { 00158 axis |= 2; 00159 tolerance[1] = mmd->tolerance; 00160 } 00161 if(mmd->flag & MOD_MIR_AXIS_Z) { 00162 axis |= 4; 00163 tolerance[2] = mmd->tolerance; 00164 } 00165 if (axis) { 00166 float mtx[4][4], imtx[4][4]; 00167 int i; 00168 TransData *td = t->data; 00169 00170 if (mmd->mirror_ob) { 00171 float obinv[4][4]; 00172 00173 invert_m4_m4(obinv, mmd->mirror_ob->obmat); 00174 mult_m4_m4m4(mtx, obinv, ob->obmat); 00175 invert_m4_m4(imtx, mtx); 00176 } 00177 00178 for(i = 0 ; i < t->total; i++, td++) { 00179 int clip; 00180 float loc[3], iloc[3]; 00181 00182 if (td->flag & TD_NOACTION) 00183 break; 00184 if (td->loc==NULL) 00185 break; 00186 00187 if (td->flag & TD_SKIP) 00188 continue; 00189 00190 copy_v3_v3(loc, td->loc); 00191 copy_v3_v3(iloc, td->iloc); 00192 00193 if (mmd->mirror_ob) { 00194 mul_m4_v3(mtx, loc); 00195 mul_m4_v3(mtx, iloc); 00196 } 00197 00198 clip = 0; 00199 if(axis & 1) { 00200 if(fabsf(iloc[0])<=tolerance[0] || 00201 loc[0]*iloc[0]<0.0f) 00202 { 00203 loc[0]= 0.0f; 00204 clip = 1; 00205 } 00206 } 00207 00208 if(axis & 2) { 00209 if(fabs(iloc[1])<=tolerance[1] || 00210 loc[1]*iloc[1]<0.0f) 00211 { 00212 loc[1]= 0.0f; 00213 clip = 1; 00214 } 00215 } 00216 if(axis & 4) { 00217 if(fabs(iloc[2])<=tolerance[2] || 00218 loc[2]*iloc[2]<0.0f) 00219 { 00220 loc[2]= 0.0f; 00221 clip = 1; 00222 } 00223 } 00224 if (clip) { 00225 if (mmd->mirror_ob) { 00226 mul_m4_v3(imtx, loc); 00227 } 00228 copy_v3_v3(td->loc, loc); 00229 } 00230 } 00231 } 00232 00233 } 00234 } 00235 } 00236 } 00237 00238 /* assumes obedit set to mesh object */ 00239 static void editmesh_apply_to_mirror(TransInfo *t) 00240 { 00241 TransData *td = t->data; 00242 EditVert *eve; 00243 int i; 00244 00245 for(i = 0 ; i < t->total; i++, td++) { 00246 if (td->flag & TD_NOACTION) 00247 break; 00248 if (td->loc==NULL) 00249 break; 00250 if (td->flag & TD_SKIP) 00251 continue; 00252 00253 eve = td->extra; 00254 if (eve) { 00255 eve->co[0]= -td->loc[0]; 00256 eve->co[1]= td->loc[1]; 00257 eve->co[2]= td->loc[2]; 00258 } 00259 00260 if (td->flag & TD_MIRROR_EDGE) 00261 { 00262 td->loc[0] = 0; 00263 } 00264 } 00265 } 00266 00267 /* for the realtime animation recording feature, handle overlapping data */ 00268 static void animrecord_check_state (Scene *scene, ID *id, wmTimer *animtimer) 00269 { 00270 ScreenAnimData *sad= (animtimer) ? animtimer->customdata : NULL; 00271 00272 /* sanity checks */ 00273 if ELEM3(NULL, scene, id, sad) 00274 return; 00275 00276 /* check if we need a new strip if: 00277 * - if animtimer is running 00278 * - we're not only keying for available channels 00279 * - the option to add new actions for each round is not enabled 00280 */ 00281 if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)==0 && (scene->toolsettings->autokey_flag & ANIMRECORD_FLAG_WITHNLA)) { 00282 /* if playback has just looped around, we need to add a new NLA track+strip to allow a clean pass to occur */ 00283 if ((sad) && (sad->flag & ANIMPLAY_FLAG_JUMPED)) { 00284 AnimData *adt= BKE_animdata_from_id(id); 00285 00286 /* perform push-down manually with some differences 00287 * NOTE: BKE_nla_action_pushdown() sync warning... 00288 */ 00289 if ((adt->action) && !(adt->flag & ADT_NLA_EDIT_ON)) { 00290 float astart, aend; 00291 00292 /* only push down if action is more than 1-2 frames long */ 00293 calc_action_range(adt->action, &astart, &aend, 1); 00294 if (aend > astart+2.0f) { 00295 NlaStrip *strip= add_nlastrip_to_stack(adt, adt->action); 00296 00297 /* clear reference to action now that we've pushed it onto the stack */ 00298 adt->action->id.us--; 00299 adt->action= NULL; 00300 00301 /* adjust blending + extend so that they will behave correctly */ 00302 strip->extendmode= NLASTRIP_EXTEND_NOTHING; 00303 strip->flag &= ~(NLASTRIP_FLAG_AUTO_BLENDS|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_ACTIVE); 00304 00305 /* also, adjust the AnimData's action extend mode to be on 00306 * 'nothing' so that previous result still play 00307 */ 00308 adt->act_extendmode= NLASTRIP_EXTEND_NOTHING; 00309 } 00310 } 00311 } 00312 } 00313 } 00314 00315 static int fcu_test_selected(FCurve *fcu) 00316 { 00317 BezTriple *bezt= fcu->bezt; 00318 unsigned int i; 00319 00320 if (bezt==NULL) /* ignore baked */ 00321 return 0; 00322 00323 for (i=0; i < fcu->totvert; i++, bezt++) { 00324 if (BEZSELECTED(bezt)) return 1; 00325 } 00326 00327 return 0; 00328 } 00329 00330 /* helper for recalcData() - for Action Editor transforms */ 00331 static void recalcData_actedit(TransInfo *t) 00332 { 00333 Scene *scene= t->scene; 00334 SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; 00335 00336 bAnimContext ac= {NULL}; 00337 ListBase anim_data = {NULL, NULL}; 00338 bAnimListElem *ale; 00339 int filter; 00340 00341 /* initialise relevant anim-context 'context' data from TransInfo data */ 00342 /* NOTE: sync this with the code in ANIM_animdata_get_context() */ 00343 ac.scene= t->scene; 00344 ac.obact= OBACT; 00345 ac.sa= t->sa; 00346 ac.ar= t->ar; 00347 ac.sl= (t->sa)? t->sa->spacedata.first : NULL; 00348 ac.spacetype= (t->sa)? t->sa->spacetype : 0; 00349 ac.regiontype= (t->ar)? t->ar->regiontype : 0; 00350 00351 ANIM_animdata_context_getdata(&ac); 00352 00353 /* perform flush */ 00354 if (ac.datatype == ANIMCONT_GPENCIL) { 00355 /* flush transform values back to actual coordinates */ 00356 flushTransGPactionData(t); 00357 } 00358 else { 00359 /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */ 00360 filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA); 00361 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 00362 00363 /* just tag these animdata-blocks to recalc, assuming that some data there changed 00364 * BUT only do this if realtime updates are enabled 00365 */ 00366 if ((saction->flag & SACTION_NOREALTIMEUPDATES) == 0) { 00367 for (ale= anim_data.first; ale; ale= ale->next) { 00368 /* set refresh tags for objects using this animation */ 00369 ANIM_list_elem_update(t->scene, ale); 00370 } 00371 } 00372 00373 /* now free temp channels */ 00374 BLI_freelistN(&anim_data); 00375 } 00376 } 00377 00378 /* helper for recalcData() - for Graph Editor transforms */ 00379 static void recalcData_graphedit(TransInfo *t) 00380 { 00381 SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first; 00382 Scene *scene; 00383 00384 ListBase anim_data = {NULL, NULL}; 00385 bAnimContext ac= {NULL}; 00386 int filter; 00387 00388 bAnimListElem *ale; 00389 int dosort = 0; 00390 00391 00392 /* initialise relevant anim-context 'context' data from TransInfo data */ 00393 /* NOTE: sync this with the code in ANIM_animdata_get_context() */ 00394 scene= ac.scene= t->scene; 00395 ac.obact= OBACT; 00396 ac.sa= t->sa; 00397 ac.ar= t->ar; 00398 ac.sl= (t->sa)? t->sa->spacedata.first : NULL; 00399 ac.spacetype= (t->sa)? t->sa->spacetype : 0; 00400 ac.regiontype= (t->ar)? t->ar->regiontype : 0; 00401 00402 ANIM_animdata_context_getdata(&ac); 00403 00404 /* do the flush first */ 00405 flushTransGraphData(t); 00406 00407 /* get curves to check if a re-sort is needed */ 00408 filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE); 00409 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); 00410 00411 /* now test if there is a need to re-sort */ 00412 for (ale= anim_data.first; ale; ale= ale->next) { 00413 FCurve *fcu= (FCurve *)ale->key_data; 00414 00415 /* ignore unselected fcurves */ 00416 if (!fcu_test_selected(fcu)) 00417 continue; 00418 00419 // fixme: only do this for selected verts... 00420 ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, ANIM_UNITCONV_ONLYSEL|ANIM_UNITCONV_SELVERTS|ANIM_UNITCONV_RESTORE); 00421 00422 00423 /* watch it: if the time is wrong: do not correct handles yet */ 00424 if (test_time_fcurve(fcu)) 00425 dosort++; 00426 else 00427 calchandles_fcurve(fcu); 00428 00429 /* set refresh tags for objects using this animation, 00430 * BUT only if realtime updates are enabled 00431 */ 00432 if ((sipo->flag & SIPO_NOREALTIMEUPDATES) == 0) 00433 ANIM_list_elem_update(t->scene, ale); 00434 } 00435 00436 /* do resort and other updates? */ 00437 if (dosort) remake_graph_transdata(t, &anim_data); 00438 00439 /* now free temp channels */ 00440 BLI_freelistN(&anim_data); 00441 } 00442 00443 /* helper for recalcData() - for NLA Editor transforms */ 00444 static void recalcData_nla(TransInfo *t) 00445 { 00446 TransDataNla *tdn= (TransDataNla *)t->customData; 00447 SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first; 00448 Scene *scene= t->scene; 00449 double secf= FPS; 00450 int i; 00451 00452 /* for each strip we've got, perform some additional validation of the values that got set before 00453 * using RNA to set the value (which does some special operations when setting these values to make 00454 * sure that everything works ok) 00455 */ 00456 for (i = 0; i < t->total; i++, tdn++) { 00457 NlaStrip *strip= tdn->strip; 00458 PointerRNA strip_ptr; 00459 short pExceeded, nExceeded, iter; 00460 int delta_y1, delta_y2; 00461 00462 /* if this tdn has no handles, that means it is just a dummy that should be skipped */ 00463 if (tdn->handle == 0) 00464 continue; 00465 00466 /* set refresh tags for objects using this animation, 00467 * BUT only if realtime updates are enabled 00468 */ 00469 if ((snla->flag & SNLA_NOREALTIMEUPDATES) == 0) 00470 ANIM_id_update(t->scene, tdn->id); 00471 00472 /* if cancelling transform, just write the values without validating, then move on */ 00473 if (t->state == TRANS_CANCEL) { 00474 /* clear the values by directly overwriting the originals, but also need to restore 00475 * endpoints of neighboring transition-strips 00476 */ 00477 00478 /* start */ 00479 strip->start= tdn->h1[0]; 00480 00481 if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) 00482 strip->prev->end= tdn->h1[0]; 00483 00484 /* end */ 00485 strip->end= tdn->h2[0]; 00486 00487 if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION)) 00488 strip->next->start= tdn->h2[0]; 00489 00490 /* flush transforms to child strips (since this should be a meta) */ 00491 BKE_nlameta_flush_transforms(strip); 00492 00493 /* restore to original track (if needed) */ 00494 if (tdn->oldTrack != tdn->nlt) { 00495 /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */ 00496 BLI_remlink(&tdn->nlt->strips, strip); 00497 BLI_addtail(&tdn->oldTrack->strips, strip); 00498 } 00499 00500 continue; 00501 } 00502 00503 /* firstly, check if the proposed transform locations would overlap with any neighbouring strips 00504 * (barring transitions) which are absolute barriers since they are not being moved 00505 * 00506 * this is done as a iterative procedure (done 5 times max for now) 00507 */ 00508 for (iter=0; iter < 5; iter++) { 00509 pExceeded= ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h1[0] < strip->prev->end)); 00510 nExceeded= ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h2[0] > strip->next->start)); 00511 00512 if ((pExceeded && nExceeded) || (iter == 4) ) { 00513 /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise) 00514 * - simply crop strip to fit within the bounds of the strips bounding it 00515 * - if there were no neighbours, clear the transforms (make it default to the strip's current values) 00516 */ 00517 if (strip->prev && strip->next) { 00518 tdn->h1[0]= strip->prev->end; 00519 tdn->h2[0]= strip->next->start; 00520 } 00521 else { 00522 tdn->h1[0]= strip->start; 00523 tdn->h2[0]= strip->end; 00524 } 00525 } 00526 else if (nExceeded) { 00527 /* move backwards */ 00528 float offset= tdn->h2[0] - strip->next->start; 00529 00530 tdn->h1[0] -= offset; 00531 tdn->h2[0] -= offset; 00532 } 00533 else if (pExceeded) { 00534 /* more forwards */ 00535 float offset= strip->prev->end - tdn->h1[0]; 00536 00537 tdn->h1[0] += offset; 00538 tdn->h2[0] += offset; 00539 } 00540 else /* all is fine and well */ 00541 break; 00542 } 00543 00544 /* handle auto-snapping */ 00545 switch (snla->autosnap) { 00546 case SACTSNAP_FRAME: /* snap to nearest frame/time */ 00547 if (snla->flag & SNLA_DRAWTIME) { 00548 tdn->h1[0]= (float)( floor((tdn->h1[0]/secf) + 0.5f) * secf ); 00549 tdn->h2[0]= (float)( floor((tdn->h2[0]/secf) + 0.5f) * secf ); 00550 } 00551 else { 00552 tdn->h1[0]= (float)( floor(tdn->h1[0]+0.5f) ); 00553 tdn->h2[0]= (float)( floor(tdn->h2[0]+0.5f) ); 00554 } 00555 break; 00556 00557 case SACTSNAP_MARKER: /* snap to nearest marker */ 00558 tdn->h1[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]); 00559 tdn->h2[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]); 00560 break; 00561 } 00562 00563 /* use RNA to write the values... */ 00564 // TODO: do we need to write in 2 passes to make sure that no truncation goes on? 00565 RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); 00566 00567 RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]); 00568 RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]); 00569 00570 /* flush transforms to child strips (since this should be a meta) */ 00571 BKE_nlameta_flush_transforms(strip); 00572 00573 00574 /* now, check if we need to try and move track 00575 * - we need to calculate both, as only one may have been altered by transform if only 1 handle moved 00576 */ 00577 delta_y1= ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex); 00578 delta_y2= ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex); 00579 00580 if (delta_y1 || delta_y2) { 00581 NlaTrack *track; 00582 int delta = (delta_y2) ? delta_y2 : delta_y1; 00583 int n; 00584 00585 /* move in the requested direction, checking at each layer if there's space for strip to pass through, 00586 * stopping on the last track available or that we're able to fit in 00587 */ 00588 if (delta > 0) { 00589 for (track=tdn->nlt->next, n=0; (track) && (n < delta); track=track->next, n++) { 00590 /* check if space in this track for the strip */ 00591 if (BKE_nlatrack_has_space(track, strip->start, strip->end)) { 00592 /* move strip to this track */ 00593 BLI_remlink(&tdn->nlt->strips, strip); 00594 BKE_nlatrack_add_strip(track, strip); 00595 00596 tdn->nlt= track; 00597 tdn->trackIndex++; 00598 } 00599 else /* can't move any further */ 00600 break; 00601 } 00602 } 00603 else { 00604 /* make delta 'positive' before using it, since we now know to go backwards */ 00605 delta= -delta; 00606 00607 for (track=tdn->nlt->prev, n=0; (track) && (n < delta); track=track->prev, n++) { 00608 /* check if space in this track for the strip */ 00609 if (BKE_nlatrack_has_space(track, strip->start, strip->end)) { 00610 /* move strip to this track */ 00611 BLI_remlink(&tdn->nlt->strips, strip); 00612 BKE_nlatrack_add_strip(track, strip); 00613 00614 tdn->nlt= track; 00615 tdn->trackIndex--; 00616 } 00617 else /* can't move any further */ 00618 break; 00619 } 00620 } 00621 } 00622 } 00623 } 00624 00625 /* helper for recalcData() - for Image Editor transforms */ 00626 static void recalcData_image(TransInfo *t) 00627 { 00628 if (t->obedit && t->obedit->type == OB_MESH) { 00629 SpaceImage *sima= t->sa->spacedata.first; 00630 00631 flushTransUVs(t); 00632 if(sima->flag & SI_LIVE_UNWRAP) 00633 ED_uvedit_live_unwrap_re_solve(); 00634 00635 DAG_id_tag_update(t->obedit->data, 0); 00636 } 00637 } 00638 00639 /* helper for recalcData() - for Movie Clip transforms */ 00640 static void recalcData_clip(TransInfo *t) 00641 { 00642 SpaceClip *sc= t->sa->spacedata.first; 00643 MovieClip *clip= ED_space_clip(sc); 00644 ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); 00645 MovieTrackingTrack *track; 00646 00647 if(t->state == TRANS_CANCEL) { 00648 track= tracksbase->first; 00649 while(track) { 00650 if(TRACK_VIEW_SELECTED(sc, track)) { 00651 MovieTrackingMarker *marker= BKE_tracking_ensure_marker(track, sc->user.framenr); 00652 00653 marker->flag= track->transflag; 00654 } 00655 00656 track= track->next; 00657 } 00658 } 00659 00660 flushTransTracking(t); 00661 00662 track= tracksbase->first; 00663 while(track) { 00664 if(TRACK_VIEW_SELECTED(sc, track)) { 00665 if (t->mode == TFM_TRANSLATION) { 00666 if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) 00667 BKE_tracking_clamp_track(track, CLAMP_PAT_POS); 00668 if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) 00669 BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS); 00670 } 00671 else if (t->mode == TFM_RESIZE) { 00672 if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) 00673 BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); 00674 if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) 00675 BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); 00676 } 00677 } 00678 00679 track= track->next; 00680 } 00681 00682 DAG_id_tag_update(&clip->id, 0); 00683 } 00684 00685 /* helper for recalcData() - for 3d-view transforms */ 00686 static void recalcData_view3d(TransInfo *t) 00687 { 00688 Base *base = t->scene->basact; 00689 00690 if (t->obedit) { 00691 if ELEM(t->obedit->type, OB_CURVE, OB_SURF) { 00692 Curve *cu= t->obedit->data; 00693 ListBase *nurbs= curve_editnurbs(cu); 00694 Nurb *nu= nurbs->first; 00695 00696 if(t->state != TRANS_CANCEL) { 00697 clipMirrorModifier(t, t->obedit); 00698 applyProject(t); 00699 } 00700 00701 DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ 00702 00703 if (t->state == TRANS_CANCEL) { 00704 while(nu) { 00705 calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */ 00706 nu= nu->next; 00707 } 00708 } 00709 else { 00710 /* Normal updating */ 00711 while(nu) { 00712 test2DNurb(nu); 00713 calchandlesNurb(nu); 00714 nu= nu->next; 00715 } 00716 } 00717 } 00718 else if(t->obedit->type==OB_LATTICE) { 00719 Lattice *la= t->obedit->data; 00720 00721 if(t->state != TRANS_CANCEL) { 00722 applyProject(t); 00723 } 00724 00725 DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ 00726 00727 if(la->editlatt->latt->flag & LT_OUTSIDE) outside_lattice(la->editlatt->latt); 00728 } 00729 else if (t->obedit->type == OB_MESH) { 00730 EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh; 00731 /* mirror modifier clipping? */ 00732 if(t->state != TRANS_CANCEL) { 00733 /* apply clipping after so we never project past the clip plane [#25423] */ 00734 applyProject(t); 00735 clipMirrorModifier(t, t->obedit); 00736 } 00737 if((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR)) 00738 editmesh_apply_to_mirror(t); 00739 00740 DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ 00741 00742 recalc_editnormals(em); 00743 } 00744 else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */ 00745 bArmature *arm= t->obedit->data; 00746 ListBase *edbo = arm->edbo; 00747 EditBone *ebo; 00748 TransData *td = t->data; 00749 int i; 00750 00751 if(t->state != TRANS_CANCEL) { 00752 applyProject(t); 00753 } 00754 00755 /* Ensure all bones are correctly adjusted */ 00756 for (ebo = edbo->first; ebo; ebo = ebo->next){ 00757 00758 if ((ebo->flag & BONE_CONNECTED) && ebo->parent){ 00759 /* If this bone has a parent tip that has been moved */ 00760 if (ebo->parent->flag & BONE_TIPSEL){ 00761 copy_v3_v3 (ebo->head, ebo->parent->tail); 00762 if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail; 00763 } 00764 /* If this bone has a parent tip that has NOT been moved */ 00765 else{ 00766 copy_v3_v3 (ebo->parent->tail, ebo->head); 00767 if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head; 00768 } 00769 } 00770 00771 /* on extrude bones, oldlength==0.0f, so we scale radius of points */ 00772 ebo->length= len_v3v3(ebo->head, ebo->tail); 00773 if(ebo->oldlength==0.0f) { 00774 ebo->rad_head= 0.25f*ebo->length; 00775 ebo->rad_tail= 0.10f*ebo->length; 00776 ebo->dist= 0.25f*ebo->length; 00777 if(ebo->parent) { 00778 if(ebo->rad_head > ebo->parent->rad_tail) 00779 ebo->rad_head= ebo->parent->rad_tail; 00780 } 00781 } 00782 else if(t->mode!=TFM_BONE_ENVELOPE) { 00783 /* if bones change length, lets do that for the deform distance as well */ 00784 ebo->dist*= ebo->length/ebo->oldlength; 00785 ebo->rad_head*= ebo->length/ebo->oldlength; 00786 ebo->rad_tail*= ebo->length/ebo->oldlength; 00787 ebo->oldlength= ebo->length; 00788 } 00789 } 00790 00791 00792 if (t->mode != TFM_BONE_ROLL) 00793 { 00794 /* fix roll */ 00795 for(i = 0; i < t->total; i++, td++) 00796 { 00797 if (td->extra) 00798 { 00799 float vec[3], up_axis[3]; 00800 float qrot[4]; 00801 00802 ebo = td->extra; 00803 copy_v3_v3(up_axis, td->axismtx[2]); 00804 00805 if (t->mode != TFM_ROTATION) 00806 { 00807 sub_v3_v3v3(vec, ebo->tail, ebo->head); 00808 normalize_v3(vec); 00809 rotation_between_vecs_to_quat(qrot, td->axismtx[1], vec); 00810 mul_qt_v3(qrot, up_axis); 00811 } 00812 else 00813 { 00814 mul_m3_v3(t->mat, up_axis); 00815 } 00816 00817 ebo->roll = ED_rollBoneToVector(ebo, up_axis, FALSE); 00818 } 00819 } 00820 } 00821 00822 if(arm->flag & ARM_MIRROR_EDIT) 00823 transform_armature_mirror_update(t->obedit); 00824 00825 } 00826 else 00827 { 00828 if(t->state != TRANS_CANCEL) { 00829 applyProject(t); 00830 } 00831 DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */ 00832 } 00833 } 00834 else if( (t->flag & T_POSE) && t->poseobj) { 00835 Object *ob= t->poseobj; 00836 bArmature *arm= ob->data; 00837 00838 /* if animtimer is running, and the object already has animation data, 00839 * check if the auto-record feature means that we should record 'samples' 00840 * (i.e. uneditable animation values) 00841 * 00842 * context is needed for keying set poll() functions. 00843 */ 00844 // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes? 00845 if ((t->animtimer) && (t->context) && IS_AUTOKEY_ON(t->scene)) { 00846 int targetless_ik= (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet! 00847 00848 animrecord_check_state(t->scene, &ob->id, t->animtimer); 00849 autokeyframe_pose_cb_func(t->context, t->scene, (View3D *)t->view, ob, t->mode, targetless_ik); 00850 } 00851 00852 /* old optimize trick... this enforces to bypass the depgraph */ 00853 if (!(arm->flag & ARM_DELAYDEFORM)) { 00854 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */ 00855 } 00856 else 00857 where_is_pose(t->scene, ob); 00858 } 00859 else if(base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, base->object)) { 00860 if(t->state != TRANS_CANCEL) { 00861 applyProject(t); 00862 } 00863 flushTransParticles(t); 00864 } 00865 else { 00866 int i; 00867 00868 if(t->state != TRANS_CANCEL) { 00869 applyProject(t); 00870 } 00871 00872 for (i = 0; i < t->total; i++) { 00873 TransData *td = t->data + i; 00874 Object *ob = td->ob; 00875 00876 if (td->flag & TD_NOACTION) 00877 break; 00878 00879 if (td->flag & TD_SKIP) 00880 continue; 00881 00882 /* if animtimer is running, and the object already has animation data, 00883 * check if the auto-record feature means that we should record 'samples' 00884 * (i.e. uneditable animation values) 00885 */ 00886 // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes? 00887 if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) { 00888 animrecord_check_state(t->scene, &ob->id, t->animtimer); 00889 autokeyframe_ob_cb_func(t->context, t->scene, (View3D *)t->view, ob, t->mode); 00890 } 00891 00892 /* sets recalc flags fully, instead of flushing existing ones 00893 * otherwise proxies don't function correctly 00894 */ 00895 DAG_id_tag_update(&ob->id, OB_RECALC_OB); 00896 } 00897 } 00898 } 00899 00900 /* called for updating while transform acts, once per redraw */ 00901 void recalcData(TransInfo *t) 00902 { 00903 if (t->spacetype==SPACE_NODE) { 00904 flushTransNodes(t); 00905 } 00906 else if (t->spacetype==SPACE_SEQ) { 00907 flushTransSeq(t); 00908 } 00909 else if (t->spacetype == SPACE_ACTION) { 00910 recalcData_actedit(t); 00911 } 00912 else if (t->spacetype == SPACE_IPO) { 00913 recalcData_graphedit(t); 00914 } 00915 else if (t->spacetype == SPACE_NLA) { 00916 recalcData_nla(t); 00917 } 00918 else if (t->spacetype == SPACE_IMAGE) { 00919 recalcData_image(t); 00920 } 00921 else if (t->spacetype == SPACE_VIEW3D) { 00922 recalcData_view3d(t); 00923 } 00924 else if (t->spacetype == SPACE_CLIP) { 00925 recalcData_clip(t); 00926 } 00927 } 00928 00929 void drawLine(TransInfo *t, float *center, float *dir, char axis, short options) 00930 { 00931 float v1[3], v2[3], v3[3]; 00932 unsigned char col[3], col2[3]; 00933 00934 if (t->spacetype == SPACE_VIEW3D) 00935 { 00936 View3D *v3d = t->view; 00937 00938 glPushMatrix(); 00939 00940 //if(t->obedit) glLoadMatrixf(t->obedit->obmat); // sets opengl viewing 00941 00942 00943 copy_v3_v3(v3, dir); 00944 mul_v3_fl(v3, v3d->far); 00945 00946 sub_v3_v3v3(v2, center, v3); 00947 add_v3_v3v3(v1, center, v3); 00948 00949 if (options & DRAWLIGHT) { 00950 col[0] = col[1] = col[2] = 220; 00951 } 00952 else { 00953 UI_GetThemeColor3ubv(TH_GRID, col); 00954 } 00955 UI_make_axis_color(col, col2, axis); 00956 glColor3ubv(col2); 00957 00958 setlinestyle(0); 00959 glBegin(GL_LINE_STRIP); 00960 glVertex3fv(v1); 00961 glVertex3fv(v2); 00962 glEnd(); 00963 00964 glPopMatrix(); 00965 } 00966 } 00967 00968 void resetTransRestrictions(TransInfo *t) 00969 { 00970 t->flag &= ~T_ALL_RESTRICTIONS; 00971 } 00972 00973 /* the *op can be NULL */ 00974 int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) 00975 { 00976 Scene *sce = CTX_data_scene(C); 00977 ToolSettings *ts = CTX_data_tool_settings(C); 00978 ARegion *ar = CTX_wm_region(C); 00979 ScrArea *sa = CTX_wm_area(C); 00980 Object *obedit = CTX_data_edit_object(C); 00981 00982 /* moving: is shown in drawobject() (transform color) */ 00983 // TRANSFORM_FIX_ME 00984 // if(obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT; 00985 // else if(G.f & G_PARTICLEEDIT) G.moving= G_TRANSFORM_PARTICLE; 00986 // else G.moving= G_TRANSFORM_OBJ; 00987 00988 t->scene = sce; 00989 t->sa = sa; 00990 t->ar = ar; 00991 t->obedit = obedit; 00992 t->settings = ts; 00993 00994 t->data = NULL; 00995 t->ext = NULL; 00996 00997 t->helpline = HLP_NONE; 00998 00999 t->flag = 0; 01000 01001 t->redraw = 1; /* redraw first time */ 01002 01003 if (event) 01004 { 01005 copy_v2_v2_int(t->imval, event->mval); 01006 t->event_type = event->type; 01007 } 01008 else 01009 { 01010 t->imval[0] = 0; 01011 t->imval[1] = 0; 01012 } 01013 01014 t->con.imval[0] = t->imval[0]; 01015 t->con.imval[1] = t->imval[1]; 01016 01017 t->mval[0] = t->imval[0]; 01018 t->mval[1] = t->imval[1]; 01019 01020 t->transform = NULL; 01021 t->handleEvent = NULL; 01022 01023 t->total = 0; 01024 01025 t->val = 0.0f; 01026 01027 t->vec[0] = 01028 t->vec[1] = 01029 t->vec[2] = 0.0f; 01030 01031 t->center[0] = 01032 t->center[1] = 01033 t->center[2] = 0.0f; 01034 01035 unit_m3(t->mat); 01036 01037 /* if there's an event, we're modal */ 01038 if (event) { 01039 t->flag |= T_MODAL; 01040 } 01041 01042 /* Crease needs edge flag */ 01043 if (t->mode == TFM_CREASE) { 01044 t->options |= CTX_EDGE; 01045 } 01046 01047 01048 /* Assign the space type, some exceptions for running in different mode */ 01049 if(sa == NULL) { 01050 /* background mode */ 01051 t->spacetype= SPACE_EMPTY; 01052 } 01053 else if ((ar == NULL) && (sa->spacetype == SPACE_VIEW3D)) { 01054 /* running in the text editor */ 01055 t->spacetype= SPACE_EMPTY; 01056 } 01057 else { 01058 /* normal operation */ 01059 t->spacetype= sa->spacetype; 01060 } 01061 01062 01063 if(t->spacetype == SPACE_VIEW3D) 01064 { 01065 View3D *v3d = sa->spacedata.first; 01066 01067 t->view = v3d; 01068 t->animtimer= CTX_wm_screen(C)->animtimer; 01069 01070 /* turn manipulator off during transform */ 01071 // FIXME: but don't do this when USING the manipulator... 01072 if (t->flag & T_MODAL) { 01073 t->twtype = v3d->twtype; 01074 v3d->twtype = 0; 01075 } 01076 01077 if(v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN; 01078 t->around = v3d->around; 01079 01080 if (op && RNA_struct_find_property(op->ptr, "constraint_orientation") && RNA_struct_property_is_set(op->ptr, "constraint_orientation")) 01081 { 01082 t->current_orientation = RNA_enum_get(op->ptr, "constraint_orientation"); 01083 01084 if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) 01085 { 01086 t->current_orientation = V3D_MANIP_GLOBAL; 01087 } 01088 } 01089 else 01090 { 01091 t->current_orientation = v3d->twmode; 01092 } 01093 01094 /* exceptional case */ 01095 if(t->around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) { 01096 if(ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) { 01097 t->options |= CTX_NO_PET; 01098 } 01099 } 01100 01101 /* initialize UV transform from */ 01102 if (op && RNA_struct_find_property(op->ptr, "correct_uv")) { 01103 if(RNA_struct_property_is_set(op->ptr, "correct_uv")) { 01104 if(RNA_boolean_get(op->ptr, "correct_uv")) { 01105 t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT; 01106 } 01107 else { 01108 t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT; 01109 } 01110 } 01111 else { 01112 RNA_boolean_set(op->ptr, "correct_uv", t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT); 01113 } 01114 } 01115 01116 } 01117 else if(t->spacetype==SPACE_IMAGE) 01118 { 01119 SpaceImage *sima = sa->spacedata.first; 01120 // XXX for now, get View2D from the active region 01121 t->view = &ar->v2d; 01122 t->around = sima->around; 01123 } 01124 else if(t->spacetype==SPACE_NODE) 01125 { 01126 // XXX for now, get View2D from the active region 01127 t->view = &ar->v2d; 01128 t->around = V3D_CENTER; 01129 } 01130 else if(t->spacetype==SPACE_IPO) 01131 { 01132 SpaceIpo *sipo= sa->spacedata.first; 01133 t->view = &ar->v2d; 01134 t->around = sipo->around; 01135 } 01136 else 01137 { 01138 if(ar) { 01139 // XXX for now, get View2D from the active region 01140 t->view = &ar->v2d; 01141 // XXX for now, the center point is the midpoint of the data 01142 } 01143 else { 01144 t->view= NULL; 01145 } 01146 t->around = V3D_CENTER; 01147 } 01148 01149 if (op && RNA_struct_property_is_set(op->ptr, "release_confirm")) 01150 { 01151 if (RNA_boolean_get(op->ptr, "release_confirm")) 01152 { 01153 t->flag |= T_RELEASE_CONFIRM; 01154 } 01155 } 01156 else 01157 { 01158 if (U.flag & USER_RELEASECONFIRM) 01159 { 01160 t->flag |= T_RELEASE_CONFIRM; 01161 } 01162 } 01163 01164 if (op && RNA_struct_find_property(op->ptr, "mirror") && RNA_struct_property_is_set(op->ptr, "mirror")) 01165 { 01166 if (RNA_boolean_get(op->ptr, "mirror")) 01167 { 01168 t->flag |= T_MIRROR; 01169 t->mirror = 1; 01170 } 01171 } 01172 // Need stuff to take it from edit mesh or whatnot here 01173 else if (t->spacetype == SPACE_VIEW3D) 01174 { 01175 if (t->obedit && t->obedit->type == OB_MESH && (((Mesh *)t->obedit->data)->editflag & ME_EDIT_MIRROR_X)) 01176 { 01177 t->flag |= T_MIRROR; 01178 t->mirror = 1; 01179 } 01180 } 01181 01182 /* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */ 01183 if (op && RNA_struct_find_property(op->ptr, "proportional")) 01184 { 01185 if (RNA_struct_property_is_set(op->ptr, "proportional")) 01186 { 01187 switch(RNA_enum_get(op->ptr, "proportional")) 01188 { 01189 case PROP_EDIT_CONNECTED: 01190 t->flag |= T_PROP_CONNECTED; 01191 case PROP_EDIT_ON: 01192 t->flag |= T_PROP_EDIT; 01193 break; 01194 } 01195 } 01196 else 01197 { 01198 /* use settings from scene only if modal */ 01199 if (t->flag & T_MODAL) 01200 { 01201 if ((t->options & CTX_NO_PET) == 0) 01202 { 01203 if (t->obedit && ts->proportional != PROP_EDIT_OFF) 01204 { 01205 t->flag |= T_PROP_EDIT; 01206 01207 if(ts->proportional == PROP_EDIT_CONNECTED) 01208 t->flag |= T_PROP_CONNECTED; 01209 } 01210 else if (t->obedit == NULL && ts->proportional_objects) 01211 { 01212 t->flag |= T_PROP_EDIT; 01213 } 01214 } 01215 } 01216 } 01217 01218 if (op && RNA_struct_find_property(op->ptr, "proportional_size") && RNA_struct_property_is_set(op->ptr, "proportional_size")) 01219 { 01220 t->prop_size = RNA_float_get(op->ptr, "proportional_size"); 01221 } 01222 else 01223 { 01224 t->prop_size = ts->proportional_size; 01225 } 01226 01227 01228 /* TRANSFORM_FIX_ME rna restrictions */ 01229 if (t->prop_size <= 0.00001f) 01230 { 01231 printf("Proportional size (%f) under 0.00001, reseting to 1!\n", t->prop_size); 01232 t->prop_size = 1.0f; 01233 } 01234 01235 if (op && RNA_struct_find_property(op->ptr, "proportional_edit_falloff") && RNA_struct_property_is_set(op->ptr, "proportional_edit_falloff")) 01236 { 01237 t->prop_mode = RNA_enum_get(op->ptr, "proportional_edit_falloff"); 01238 } 01239 else 01240 { 01241 t->prop_mode = ts->prop_mode; 01242 } 01243 } 01244 else /* add not pet option to context when not available */ 01245 { 01246 t->options |= CTX_NO_PET; 01247 } 01248 01249 // Mirror is not supported with PET, turn it off. 01250 if (t->flag & T_PROP_EDIT) 01251 { 01252 t->flag &= ~T_MIRROR; 01253 } 01254 01255 setTransformViewMatrices(t); 01256 initNumInput(&t->num); 01257 01258 return 1; 01259 } 01260 01261 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */ 01262 void postTrans (bContext *C, TransInfo *t) 01263 { 01264 TransData *td; 01265 01266 if (t->draw_handle_view) 01267 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_view); 01268 if (t->draw_handle_apply) 01269 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_apply); 01270 if (t->draw_handle_pixel) 01271 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_pixel); 01272 if (t->draw_handle_cursor) 01273 WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor); 01274 01275 if (t->customFree) { 01276 /* Can take over freeing t->data and data2d etc... */ 01277 t->customFree(t); 01278 } 01279 else if (t->customData) { 01280 MEM_freeN(t->customData); 01281 } 01282 01283 /* postTrans can be called when nothing is selected, so data is NULL already */ 01284 if (t->data) { 01285 int a; 01286 01287 /* free data malloced per trans-data */ 01288 for(a=0, td= t->data; a<t->total; a++, td++) { 01289 if (td->flag & TD_BEZTRIPLE) 01290 MEM_freeN(td->hdata); 01291 } 01292 MEM_freeN(t->data); 01293 } 01294 01295 BLI_freelistN(&t->tsnap.points); 01296 01297 if (t->ext) MEM_freeN(t->ext); 01298 if (t->data2d) { 01299 MEM_freeN(t->data2d); 01300 t->data2d= NULL; 01301 } 01302 01303 if(t->spacetype==SPACE_IMAGE) { 01304 SpaceImage *sima= t->sa->spacedata.first; 01305 if(sima->flag & SI_LIVE_UNWRAP) 01306 ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL); 01307 } 01308 else if(t->spacetype==SPACE_VIEW3D) { 01309 View3D *v3d = t->sa->spacedata.first; 01310 /* restore manipulator */ 01311 if (t->flag & T_MODAL) { 01312 v3d->twtype = t->twtype; 01313 } 01314 } 01315 01316 if (t->mouse.data) 01317 { 01318 MEM_freeN(t->mouse.data); 01319 } 01320 } 01321 01322 void applyTransObjects(TransInfo *t) 01323 { 01324 TransData *td; 01325 01326 for (td = t->data; td < t->data + t->total; td++) { 01327 copy_v3_v3(td->iloc, td->loc); 01328 if (td->ext->rot) { 01329 copy_v3_v3(td->ext->irot, td->ext->rot); 01330 } 01331 if (td->ext->size) { 01332 copy_v3_v3(td->ext->isize, td->ext->size); 01333 } 01334 } 01335 recalcData(t); 01336 } 01337 01338 static void restoreElement(TransData *td) 01339 { 01340 /* TransData for crease has no loc */ 01341 if (td->loc) { 01342 copy_v3_v3(td->loc, td->iloc); 01343 } 01344 if (td->val) { 01345 *td->val = td->ival; 01346 } 01347 01348 if (td->ext && (td->flag&TD_NO_EXT)==0) { 01349 if (td->ext->rot) { 01350 copy_v3_v3(td->ext->rot, td->ext->irot); 01351 } 01352 if(td->ext->rotAngle) { 01353 *td->ext->rotAngle= td->ext->irotAngle; 01354 } 01355 if(td->ext->rotAxis) { 01356 copy_v3_v3(td->ext->rotAxis, td->ext->irotAxis); 01357 } 01358 /* XXX, drotAngle & drotAxis not used yet */ 01359 if (td->ext->size) { 01360 copy_v3_v3(td->ext->size, td->ext->isize); 01361 } 01362 if (td->ext->quat) { 01363 copy_qt_qt(td->ext->quat, td->ext->iquat); 01364 } 01365 } 01366 01367 if (td->flag & TD_BEZTRIPLE) { 01368 *(td->hdata->h1) = td->hdata->ih1; 01369 *(td->hdata->h2) = td->hdata->ih2; 01370 } 01371 } 01372 01373 void restoreTransObjects(TransInfo *t) 01374 { 01375 TransData *td; 01376 TransData2D *td2d; 01377 01378 for (td = t->data; td < t->data + t->total; td++) { 01379 restoreElement(td); 01380 } 01381 01382 for (td2d=t->data2d; t->data2d && td2d < t->data2d + t->total; td2d++) { 01383 if (td2d->h1) { 01384 td2d->h1[0] = td2d->ih1[0]; 01385 td2d->h1[1] = td2d->ih1[1]; 01386 } 01387 if (td2d->h2) { 01388 td2d->h2[0] = td2d->ih2[0]; 01389 td2d->h2[1] = td2d->ih2[1]; 01390 } 01391 } 01392 01393 unit_m3(t->mat); 01394 01395 recalcData(t); 01396 } 01397 01398 void calculateCenter2D(TransInfo *t) 01399 { 01400 if (t->flag & (T_EDIT|T_POSE)) { 01401 Object *ob= t->obedit?t->obedit:t->poseobj; 01402 float vec[3]; 01403 01404 copy_v3_v3(vec, t->center); 01405 mul_m4_v3(ob->obmat, vec); 01406 projectIntView(t, vec, t->center2d); 01407 } 01408 else { 01409 projectIntView(t, t->center, t->center2d); 01410 } 01411 } 01412 01413 void calculateCenterCursor(TransInfo *t) 01414 { 01415 float *cursor; 01416 01417 cursor = give_cursor(t->scene, t->view); 01418 copy_v3_v3(t->center, cursor); 01419 01420 /* If edit or pose mode, move cursor in local space */ 01421 if (t->flag & (T_EDIT|T_POSE)) { 01422 Object *ob = t->obedit?t->obedit:t->poseobj; 01423 float mat[3][3], imat[3][3]; 01424 01425 sub_v3_v3v3(t->center, t->center, ob->obmat[3]); 01426 copy_m3_m4(mat, ob->obmat); 01427 invert_m3_m3(imat, mat); 01428 mul_m3_v3(imat, t->center); 01429 } 01430 01431 calculateCenter2D(t); 01432 } 01433 01434 void calculateCenterCursor2D(TransInfo *t) 01435 { 01436 float aspx=1.0, aspy=1.0; 01437 float *cursor= NULL; 01438 01439 if(t->spacetype==SPACE_IMAGE) { 01440 SpaceImage *sima= (SpaceImage *)t->sa->spacedata.first; 01441 /* only space supported right now but may change */ 01442 ED_space_image_uv_aspect(sima, &aspx, &aspy); 01443 cursor = sima->cursor; 01444 } 01445 01446 if (cursor) { 01447 t->center[0] = cursor[0] * aspx; 01448 t->center[1] = cursor[1] * aspy; 01449 } 01450 01451 calculateCenter2D(t); 01452 } 01453 01454 static void calculateCenterCursorGraph2D(TransInfo *t) 01455 { 01456 SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first; 01457 Scene *scene= t->scene; 01458 01459 /* cursor is combination of current frame, and graph-editor cursor value */ 01460 t->center[0]= (float)(scene->r.cfra); 01461 t->center[1]= sipo->cursorVal; 01462 01463 calculateCenter2D(t); 01464 } 01465 01466 void calculateCenterMedian(TransInfo *t) 01467 { 01468 float partial[3] = {0.0f, 0.0f, 0.0f}; 01469 int total = 0; 01470 int i; 01471 01472 for(i = 0; i < t->total; i++) { 01473 if (t->data[i].flag & TD_SELECTED) { 01474 if (!(t->data[i].flag & TD_NOCENTER)) 01475 { 01476 add_v3_v3(partial, t->data[i].center); 01477 total++; 01478 } 01479 } 01480 else { 01481 /* 01482 All the selected elements are at the head of the array 01483 which means we can stop when it finds unselected data 01484 */ 01485 break; 01486 } 01487 } 01488 if(i) 01489 mul_v3_fl(partial, 1.0f / total); 01490 copy_v3_v3(t->center, partial); 01491 01492 calculateCenter2D(t); 01493 } 01494 01495 void calculateCenterBound(TransInfo *t) 01496 { 01497 float max[3]; 01498 float min[3]; 01499 int i; 01500 for(i = 0; i < t->total; i++) { 01501 if (i) { 01502 if (t->data[i].flag & TD_SELECTED) { 01503 if (!(t->data[i].flag & TD_NOCENTER)) 01504 minmax_v3v3_v3(min, max, t->data[i].center); 01505 } 01506 else { 01507 /* 01508 All the selected elements are at the head of the array 01509 which means we can stop when it finds unselected data 01510 */ 01511 break; 01512 } 01513 } 01514 else { 01515 copy_v3_v3(max, t->data[i].center); 01516 copy_v3_v3(min, t->data[i].center); 01517 } 01518 } 01519 add_v3_v3v3(t->center, min, max); 01520 mul_v3_fl(t->center, 0.5); 01521 01522 calculateCenter2D(t); 01523 } 01524 01525 void calculateCenter(TransInfo *t) 01526 { 01527 switch(t->around) { 01528 case V3D_CENTER: 01529 calculateCenterBound(t); 01530 break; 01531 case V3D_CENTROID: 01532 calculateCenterMedian(t); 01533 break; 01534 case V3D_CURSOR: 01535 if(t->spacetype==SPACE_IMAGE) 01536 calculateCenterCursor2D(t); 01537 else if(t->spacetype==SPACE_IPO) 01538 calculateCenterCursorGraph2D(t); 01539 else 01540 calculateCenterCursor(t); 01541 break; 01542 case V3D_LOCAL: 01543 /* Individual element center uses median center for helpline and such */ 01544 calculateCenterMedian(t); 01545 break; 01546 case V3D_ACTIVE: 01547 { 01548 /* set median, and if if if... do object center */ 01549 01550 /* EDIT MODE ACTIVE EDITMODE ELEMENT */ 01551 01552 if (t->obedit) { 01553 if(t->obedit->type == OB_MESH) { 01554 EditSelection ese; 01555 EditMesh *em = BKE_mesh_get_editmesh(t->obedit->data); 01556 01557 if (EM_get_actSelection(em, &ese)) { 01558 EM_editselection_center(t->center, &ese); 01559 calculateCenter2D(t); 01560 break; 01561 } 01562 } 01563 else if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) { 01564 float center[3]; 01565 Curve *cu= (Curve *)t->obedit->data; 01566 01567 if (ED_curve_actSelection(cu, center)) { 01568 copy_v3_v3(t->center, center); 01569 calculateCenter2D(t); 01570 break; 01571 } 01572 } 01573 } /* END EDIT MODE ACTIVE ELEMENT */ 01574 01575 calculateCenterMedian(t); 01576 if((t->flag & (T_EDIT|T_POSE))==0) 01577 { 01578 Scene *scene = t->scene; 01579 Object *ob= OBACT; 01580 if(ob) 01581 { 01582 copy_v3_v3(t->center, ob->obmat[3]); 01583 projectIntView(t, t->center, t->center2d); 01584 } 01585 } 01586 01587 } 01588 } 01589 01590 /* setting constraint center */ 01591 copy_v3_v3(t->con.center, t->center); 01592 if(t->flag & (T_EDIT|T_POSE)) 01593 { 01594 Object *ob= t->obedit?t->obedit:t->poseobj; 01595 mul_m4_v3(ob->obmat, t->con.center); 01596 } 01597 01598 /* for panning from cameraview */ 01599 if(t->flag & T_OBJECT) 01600 { 01601 if(t->spacetype==SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) 01602 { 01603 View3D *v3d = t->view; 01604 Scene *scene = t->scene; 01605 RegionView3D *rv3d = t->ar->regiondata; 01606 01607 if(v3d->camera == OBACT && rv3d->persp==RV3D_CAMOB) 01608 { 01609 float axis[3]; 01610 /* persinv is nasty, use viewinv instead, always right */ 01611 copy_v3_v3(axis, t->viewinv[2]); 01612 normalize_v3(axis); 01613 01614 /* 6.0 = 6 grid units */ 01615 axis[0]= t->center[0]- 6.0f*axis[0]; 01616 axis[1]= t->center[1]- 6.0f*axis[1]; 01617 axis[2]= t->center[2]- 6.0f*axis[2]; 01618 01619 projectIntView(t, axis, t->center2d); 01620 01621 /* rotate only needs correct 2d center, grab needs initgrabz() value */ 01622 if(t->mode==TFM_TRANSLATION) 01623 { 01624 copy_v3_v3(t->center, axis); 01625 copy_v3_v3(t->con.center, t->center); 01626 } 01627 } 01628 } 01629 } 01630 01631 if(t->spacetype==SPACE_VIEW3D) 01632 { 01633 /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d_delta() */ 01634 if(t->flag & (T_EDIT|T_POSE)) { 01635 Object *ob= t->obedit?t->obedit:t->poseobj; 01636 float vec[3]; 01637 01638 copy_v3_v3(vec, t->center); 01639 mul_m4_v3(ob->obmat, vec); 01640 initgrabz(t->ar->regiondata, vec[0], vec[1], vec[2]); 01641 } 01642 else { 01643 initgrabz(t->ar->regiondata, t->center[0], t->center[1], t->center[2]); 01644 } 01645 } 01646 } 01647 01648 void calculatePropRatio(TransInfo *t) 01649 { 01650 TransData *td = t->data; 01651 int i; 01652 float dist; 01653 short connected = t->flag & T_PROP_CONNECTED; 01654 01655 if (t->flag & T_PROP_EDIT) { 01656 for(i = 0 ; i < t->total; i++, td++) { 01657 if (td->flag & TD_SELECTED) { 01658 td->factor = 1.0f; 01659 } 01660 else if (t->flag & T_MIRROR && td->loc[0] * t->mirror < -0.00001f) 01661 { 01662 td->flag |= TD_SKIP; 01663 td->factor = 0.0f; 01664 restoreElement(td); 01665 } 01666 else if ((connected && 01667 (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size)) 01668 || 01669 (connected == 0 && 01670 td->rdist > t->prop_size)) { 01671 /* 01672 The elements are sorted according to their dist member in the array, 01673 that means we can stop when it finds one element outside of the propsize. 01674 */ 01675 td->flag |= TD_NOACTION; 01676 td->factor = 0.0f; 01677 restoreElement(td); 01678 } 01679 else { 01680 /* Use rdist for falloff calculations, it is the real distance */ 01681 td->flag &= ~TD_NOACTION; 01682 01683 if (connected) 01684 dist= (t->prop_size-td->dist)/t->prop_size; 01685 else 01686 dist= (t->prop_size-td->rdist)/t->prop_size; 01687 01688 /* 01689 * Clamp to positive numbers. 01690 * Certain corner cases with connectivity and individual centers 01691 * can give values of rdist larger than propsize. 01692 */ 01693 if (dist < 0.0f) 01694 dist = 0.0f; 01695 01696 switch(t->prop_mode) { 01697 case PROP_SHARP: 01698 td->factor= dist*dist; 01699 break; 01700 case PROP_SMOOTH: 01701 td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist; 01702 break; 01703 case PROP_ROOT: 01704 td->factor = (float)sqrt(dist); 01705 break; 01706 case PROP_LIN: 01707 td->factor = dist; 01708 break; 01709 case PROP_CONST: 01710 td->factor = 1.0f; 01711 break; 01712 case PROP_SPHERE: 01713 td->factor = (float)sqrt(2*dist - dist * dist); 01714 break; 01715 case PROP_RANDOM: 01716 BLI_srand( BLI_rand() ); /* random seed */ 01717 td->factor = BLI_frand()*dist; 01718 break; 01719 default: 01720 td->factor = 1; 01721 } 01722 } 01723 } 01724 switch(t->prop_mode) { 01725 case PROP_SHARP: 01726 strcpy(t->proptext, "(Sharp)"); 01727 break; 01728 case PROP_SMOOTH: 01729 strcpy(t->proptext, "(Smooth)"); 01730 break; 01731 case PROP_ROOT: 01732 strcpy(t->proptext, "(Root)"); 01733 break; 01734 case PROP_LIN: 01735 strcpy(t->proptext, "(Linear)"); 01736 break; 01737 case PROP_CONST: 01738 strcpy(t->proptext, "(Constant)"); 01739 break; 01740 case PROP_SPHERE: 01741 strcpy(t->proptext, "(Sphere)"); 01742 break; 01743 case PROP_RANDOM: 01744 strcpy(t->proptext, "(Random)"); 01745 break; 01746 default: 01747 t->proptext[0]= '\0'; 01748 } 01749 } 01750 else { 01751 for(i = 0 ; i < t->total; i++, td++) { 01752 td->factor = 1.0; 01753 } 01754 t->proptext[0]= '\0'; 01755 } 01756 }