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