Blender V2.61 - r43446

transform_generics.c

Go to the documentation of this file.
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 }