Blender  V2.59
transform_manipulator.c
Go to the documentation of this file.
00001 /*
00002 * $Id: transform_manipulator.c 38085 2011-07-04 13:48:18Z blendix $
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) 2005 Blender Foundation
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 <stdlib.h>
00036 #include <string.h>
00037 #include <math.h>
00038 #include <float.h>
00039 
00040 #ifndef WIN32
00041 #include <unistd.h>
00042 #else
00043 #include <io.h>
00044 #endif
00045 
00046 #include "MEM_guardedalloc.h"
00047 
00048 #include "DNA_armature_types.h"
00049 #include "DNA_curve_types.h"
00050 #include "DNA_lattice_types.h"
00051 #include "DNA_meta_types.h"
00052 #include "DNA_screen_types.h"
00053 #include "DNA_scene_types.h"
00054 #include "DNA_view3d_types.h"
00055 
00056 #include "RNA_access.h"
00057 
00058 #include "BKE_action.h"
00059 #include "BKE_context.h"
00060 #include "BKE_global.h"
00061 #include "BKE_mesh.h"
00062 #include "BKE_particle.h"
00063 #include "BKE_pointcache.h"
00064 
00065 #include "BLI_math.h"
00066 #include "BLI_editVert.h"
00067 #include "BLI_utildefines.h"
00068 
00069 #include "BIF_gl.h"
00070 
00071 #include "WM_api.h"
00072 #include "WM_types.h"
00073 
00074 #include "ED_armature.h"
00075 #include "ED_mesh.h"
00076 #include "ED_particle.h"
00077 #include "ED_view3d.h"
00078 #include "ED_curve.h" /* for ED_curve_editnurbs */
00079 
00080 #include "UI_resources.h"
00081 
00082 /* local module include */
00083 #include "transform.h"
00084 
00085 /* return codes for select, and drawing flags */
00086 
00087 #define MAN_TRANS_X             1
00088 #define MAN_TRANS_Y             2
00089 #define MAN_TRANS_Z             4
00090 #define MAN_TRANS_C             7
00091 
00092 #define MAN_ROT_X               8
00093 #define MAN_ROT_Y               16
00094 #define MAN_ROT_Z               32
00095 #define MAN_ROT_V               64
00096 #define MAN_ROT_T               128
00097 #define MAN_ROT_C               248
00098 
00099 #define MAN_SCALE_X             256
00100 #define MAN_SCALE_Y             512
00101 #define MAN_SCALE_Z             1024
00102 #define MAN_SCALE_C             1792
00103 
00104 /* color codes */
00105 
00106 #define MAN_RGB         0
00107 #define MAN_GHOST       1
00108 #define MAN_MOVECOL     2
00109 
00110 /* transform widget center calc helper for below */
00111 static void calc_tw_center(Scene *scene, float *co)
00112 {
00113         float *twcent= scene->twcent;
00114         float *min= scene->twmin;
00115         float *max= scene->twmax;
00116 
00117         DO_MINMAX(co, min, max);
00118         add_v3_v3(twcent, co);
00119 }
00120 
00121 static void protectflag_to_drawflags(short protectflag, short *drawflags)
00122 {
00123         if(protectflag & OB_LOCK_LOCX)
00124                 *drawflags &= ~MAN_TRANS_X;
00125         if(protectflag & OB_LOCK_LOCY)
00126                 *drawflags &= ~MAN_TRANS_Y;
00127         if(protectflag & OB_LOCK_LOCZ)
00128                 *drawflags &= ~MAN_TRANS_Z;
00129 
00130         if(protectflag & OB_LOCK_ROTX)
00131                 *drawflags &= ~MAN_ROT_X;
00132         if(protectflag & OB_LOCK_ROTY)
00133                 *drawflags &= ~MAN_ROT_Y;
00134         if(protectflag & OB_LOCK_ROTZ)
00135                 *drawflags &= ~MAN_ROT_Z;
00136 
00137         if(protectflag & OB_LOCK_SCALEX)
00138                 *drawflags &= ~MAN_SCALE_X;
00139         if(protectflag & OB_LOCK_SCALEY)
00140                 *drawflags &= ~MAN_SCALE_Y;
00141         if(protectflag & OB_LOCK_SCALEZ)
00142                 *drawflags &= ~MAN_SCALE_Z;
00143 }
00144 
00145 /* for pose mode */
00146 static void stats_pose(Scene *scene, RegionView3D *rv3d, bPoseChannel *pchan)
00147 {
00148         Bone *bone= pchan->bone;
00149 
00150         if(bone) {
00151                 if (bone->flag & BONE_TRANSFORM) {
00152                         calc_tw_center(scene, pchan->pose_head);
00153                         protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
00154                 }
00155         }
00156 }
00157 
00158 /* for editmode*/
00159 static void stats_editbone(RegionView3D *rv3d, EditBone *ebo)
00160 {
00161         if (ebo->flag & BONE_EDITMODE_LOCKED)
00162                 protectflag_to_drawflags(OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE, &rv3d->twdrawflag);
00163 }
00164 
00165 /* could move into BLI_math however this is only useful for display/editing purposes */
00166 static void axis_angle_to_gimbal_axis(float gmat[3][3], float axis[3], float angle)
00167 {
00168         /* X/Y are arbitrary axies, most importantly Z is the axis of rotation */
00169 
00170         float cross_vec[3];
00171         float quat[4];
00172 
00173         /* this is an un-scientific method to get a vector to cross with
00174          * XYZ intentionally YZX */
00175         cross_vec[0]= axis[1];
00176         cross_vec[1]= axis[2];
00177         cross_vec[2]= axis[0];
00178 
00179         /* X-axis */
00180         cross_v3_v3v3(gmat[0], cross_vec, axis);
00181         normalize_v3(gmat[0]);
00182         axis_angle_to_quat(quat, axis, angle);
00183         mul_qt_v3(quat, gmat[0]);
00184 
00185         /* Y-axis */
00186         axis_angle_to_quat(quat, axis, M_PI/2.0);
00187         copy_v3_v3(gmat[1], gmat[0]);
00188         mul_qt_v3(quat, gmat[1]);
00189 
00190         /* Z-axis */
00191         copy_v3_v3(gmat[2], axis);
00192 
00193         normalize_m3(gmat);
00194 }
00195 
00196 
00197 static int test_rotmode_euler(short rotmode)
00198 {
00199         return (ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT)) ? 0:1;
00200 }
00201 
00202 int gimbal_axis(Object *ob, float gmat[][3])
00203 {
00204         if (ob) {
00205                 if(ob->mode & OB_MODE_POSE)
00206                 {
00207                         bPoseChannel *pchan= get_active_posechannel(ob);
00208 
00209                         if(pchan) {
00210                                 float mat[3][3], tmat[3][3], obmat[3][3];
00211                                 if(test_rotmode_euler(pchan->rotmode)) {
00212                                         eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode);
00213                                 }
00214                                 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
00215                                         axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle);
00216                                 }
00217                                 else { /* quat */
00218                                         return 0;
00219                                 }
00220 
00221 
00222                                 /* apply bone transformation */
00223                                 mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat);
00224 
00225                                 if (pchan->parent)
00226                                 {
00227                                         float parent_mat[3][3];
00228 
00229                                         copy_m3_m4(parent_mat, pchan->parent->pose_mat);
00230                                         mul_m3_m3m3(mat, parent_mat, tmat);
00231 
00232                                         /* needed if object transformation isn't identity */
00233                                         copy_m3_m4(obmat, ob->obmat);
00234                                         mul_m3_m3m3(gmat, obmat, mat);
00235                                 }
00236                                 else
00237                                 {
00238                                         /* needed if object transformation isn't identity */
00239                                         copy_m3_m4(obmat, ob->obmat);
00240                                         mul_m3_m3m3(gmat, obmat, tmat);
00241                                 }
00242 
00243                                 normalize_m3(gmat);
00244                                 return 1;
00245                         }
00246                 }
00247                 else {
00248                         if(test_rotmode_euler(ob->rotmode)) {
00249                                 eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode);
00250                         }
00251                         else if(ob->rotmode == ROT_MODE_AXISANGLE) {
00252                                 axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle);
00253                         }
00254                         else { /* quat */
00255                                 return 0;
00256                         }
00257 
00258                         if (ob->parent)
00259                         {
00260                                 float parent_mat[3][3];
00261                                 copy_m3_m4(parent_mat, ob->parent->obmat);
00262                                 normalize_m3(parent_mat);
00263                                 mul_m3_m3m3(gmat, parent_mat, gmat);
00264                         }
00265                         return 1;
00266                 }
00267         }
00268 
00269         return 0;
00270 }
00271 
00272 
00273 /* centroid, boundbox, of selection */
00274 /* returns total items selected */
00275 int calc_manipulator_stats(const bContext *C)
00276 {
00277         ScrArea *sa= CTX_wm_area(C);
00278         ARegion *ar= CTX_wm_region(C);
00279         Scene *scene= CTX_data_scene(C);
00280         Object *obedit= CTX_data_edit_object(C);
00281         ToolSettings *ts = CTX_data_tool_settings(C);
00282         View3D *v3d= sa->spacedata.first;
00283         RegionView3D *rv3d= ar->regiondata;
00284         Base *base;
00285         Object *ob= OBACT;
00286         int a, totsel= 0;
00287 
00288         /* transform widget matrix */
00289         unit_m4(rv3d->twmat);
00290 
00291         rv3d->twdrawflag= 0xFFFF;
00292 
00293         /* transform widget centroid/center */
00294         scene->twcent[0]= scene->twcent[1]= scene->twcent[2]= 0.0f;
00295         INIT_MINMAX(scene->twmin, scene->twmax);
00296 
00297         if(obedit) {
00298                 ob= obedit;
00299                 if((ob->lay & v3d->lay)==0) return 0;
00300 
00301                 if(obedit->type==OB_MESH) {
00302                         EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
00303                         EditVert *eve;
00304                         EditSelection ese;
00305                         float vec[3]= {0,0,0};
00306 
00307                         /* USE LAST SELECTE WITH ACTIVE */
00308                         if (v3d->around==V3D_ACTIVE && EM_get_actSelection(em, &ese)) {
00309                                 EM_editselection_center(vec, &ese);
00310                                 calc_tw_center(scene, vec);
00311                                 totsel= 1;
00312                         } else {
00313                                 /* do vertices/edges/faces for center depending on selection
00314                                    mode. note we can't use just vertex selection flag because
00315                                    it is not flush down on changes */
00316                                 if(ts->selectmode & SCE_SELECT_VERTEX) {
00317                                         for(eve= em->verts.first; eve; eve= eve->next) {
00318                                                 if(eve->f & SELECT) {
00319                                                         totsel++;
00320                                                         calc_tw_center(scene, eve->co);
00321                                                 }
00322                                         }
00323                                 }
00324                                 else if(ts->selectmode & SCE_SELECT_EDGE) {
00325                                         EditEdge *eed;
00326 
00327                                         for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
00328                                         for(eed= em->edges.first; eed; eed= eed->next) {
00329                                                 if(eed->h==0 && (eed->f & SELECT)) {
00330                                                         if(!eed->v1->f1) {
00331                                                                 eed->v1->f1= 1;
00332                                                                 totsel++;
00333                                                                 calc_tw_center(scene, eed->v1->co);
00334                                                         }
00335                                                         if(!eed->v2->f1) {
00336                                                                 eed->v2->f1= 1;
00337                                                                 totsel++;
00338                                                                 calc_tw_center(scene, eed->v2->co);
00339                                                         }
00340                                                 }
00341                                         }
00342                                 }
00343                                 else {
00344                                         EditFace *efa;
00345 
00346                                         for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
00347                                         for(efa= em->faces.first; efa; efa= efa->next) {
00348                                                 if(efa->h==0 && (efa->f & SELECT)) {
00349                                                         if(!efa->v1->f1) {
00350                                                                 efa->v1->f1= 1;
00351                                                                 totsel++;
00352                                                                 calc_tw_center(scene, efa->v1->co);
00353                                                         }
00354                                                         if(!efa->v2->f1) {
00355                                                                 efa->v2->f1= 1;
00356                                                                 totsel++;
00357                                                                 calc_tw_center(scene, efa->v2->co);
00358                                                         }
00359                                                         if(!efa->v3->f1) {
00360                                                                 efa->v3->f1= 1;
00361                                                                 totsel++;
00362                                                                 calc_tw_center(scene, efa->v3->co);
00363                                                         }
00364                                                         if(efa->v4 && !efa->v4->f1) {
00365                                                                 efa->v4->f1= 1;
00366                                                                 totsel++;
00367                                                                 calc_tw_center(scene, efa->v4->co);
00368                                                         }
00369                                                 }
00370                                         }
00371                                 }
00372                         }
00373                 } /* end editmesh */
00374                 else if (obedit->type==OB_ARMATURE){
00375                         bArmature *arm= obedit->data;
00376                         EditBone *ebo;
00377                         for (ebo= arm->edbo->first; ebo; ebo=ebo->next){
00378                                 if(EBONE_VISIBLE(arm, ebo)) {
00379                                         if (ebo->flag & BONE_TIPSEL) {
00380                                                 calc_tw_center(scene, ebo->tail);
00381                                                 totsel++;
00382                                         }
00383                                         if (ebo->flag & BONE_ROOTSEL) {
00384                                                 calc_tw_center(scene, ebo->head);
00385                                                 totsel++;
00386                                         }
00387                                         if (ebo->flag & BONE_SELECTED) {
00388                                                 stats_editbone(rv3d, ebo);
00389                                         }
00390                                 }
00391                         }
00392                 }
00393                 else if ELEM(obedit->type, OB_CURVE, OB_SURF) {
00394                         Curve *cu= obedit->data;
00395                         Nurb *nu;
00396                         BezTriple *bezt;
00397                         BPoint *bp;
00398                         ListBase *nurbs= ED_curve_editnurbs(cu);
00399 
00400                         nu= nurbs->first;
00401                         while(nu) {
00402                                 if(nu->type == CU_BEZIER) {
00403                                         bezt= nu->bezt;
00404                                         a= nu->pntsu;
00405                                         while(a--) {
00406                                                 /* exceptions
00407                                                  * if handles are hidden then only check the center points.
00408                                                  * If the center knot is selected then only use this as the center point.
00409                                                  */
00410                                                 if (cu->drawflag & CU_HIDE_HANDLES) {
00411                                                         if (bezt->f2 & SELECT) {
00412                                                                 calc_tw_center(scene, bezt->vec[1]);
00413                                                                 totsel++;
00414                                                         }
00415                                                 }
00416                                                 else if (bezt->f2 & SELECT) {
00417                                                         calc_tw_center(scene, bezt->vec[1]);
00418                                                         totsel++;
00419                                                 }
00420                                                 else {
00421                                                         if(bezt->f1) {
00422                                                                 calc_tw_center(scene, bezt->vec[0]);
00423                                                                 totsel++;
00424                                                         }
00425                                                         if(bezt->f3) {
00426                                                                 calc_tw_center(scene, bezt->vec[2]);
00427                                                                 totsel++;
00428                                                         }
00429                                                 }
00430                                                 bezt++;
00431                                         }
00432                                 }
00433                                 else {
00434                                         bp= nu->bp;
00435                                         a= nu->pntsu*nu->pntsv;
00436                                         while(a--) {
00437                                                 if(bp->f1 & SELECT) {
00438                                                         calc_tw_center(scene, bp->vec);
00439                                                         totsel++;
00440                                                 }
00441                                                 bp++;
00442                                         }
00443                                 }
00444                                 nu= nu->next;
00445                         }
00446                 }
00447                 else if(obedit->type==OB_MBALL) {
00448                         MetaBall *mb = (MetaBall*)obedit->data;
00449                         MetaElem *ml, *ml_sel=NULL;
00450 
00451                         ml= mb->editelems->first;
00452                         while(ml) {
00453                                 if(ml->flag & SELECT) {
00454                                         calc_tw_center(scene, &ml->x);
00455                                         ml_sel = ml;
00456                                         totsel++;
00457                                 }
00458                                 ml= ml->next;
00459                         }
00460                 }
00461                 else if(obedit->type==OB_LATTICE) {
00462                         BPoint *bp;
00463                         Lattice *lt= obedit->data;
00464 
00465                         bp= lt->editlatt->latt->def;
00466 
00467                         a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
00468                         while(a--) {
00469                                 if(bp->f1 & SELECT) {
00470                                         calc_tw_center(scene, bp->vec);
00471                                         totsel++;
00472                                 }
00473                                 bp++;
00474                         }
00475                 }
00476 
00477                 /* selection center */
00478                 if(totsel) {
00479                         mul_v3_fl(scene->twcent, 1.0f/(float)totsel);   // centroid!
00480                         mul_m4_v3(obedit->obmat, scene->twcent);
00481                         mul_m4_v3(obedit->obmat, scene->twmin);
00482                         mul_m4_v3(obedit->obmat, scene->twmax);
00483                 }
00484         }
00485         else if(ob && (ob->mode & OB_MODE_POSE)) {
00486                 bPoseChannel *pchan;
00487                 int mode = TFM_ROTATION; // mislead counting bones... bah. We don't know the manipulator mode, could be mixed
00488 
00489                 if((ob->lay & v3d->lay)==0) return 0;
00490 
00491                 totsel = count_set_pose_transflags(&mode, 0, ob);
00492 
00493                 if(totsel) {
00494                         /* use channels to get stats */
00495                         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
00496                                 stats_pose(scene, rv3d, pchan);
00497                         }
00498 
00499                         mul_v3_fl(scene->twcent, 1.0f/(float)totsel);   // centroid!
00500                         mul_m4_v3(ob->obmat, scene->twcent);
00501                         mul_m4_v3(ob->obmat, scene->twmin);
00502                         mul_m4_v3(ob->obmat, scene->twmax);
00503                 }
00504         }
00505         else if(ob && (ob->mode & OB_MODE_ALL_PAINT)) {
00506                 ;
00507         }
00508         else if(ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
00509                 PTCacheEdit *edit= PE_get_current(scene, ob);
00510                 PTCacheEditPoint *point;
00511                 PTCacheEditKey *ek;
00512                 int k;
00513 
00514                 if(edit) {
00515                         point = edit->points;
00516                         for(a=0; a<edit->totpoint; a++,point++) {
00517                                 if(point->flag & PEP_HIDE) continue;
00518 
00519                                 for(k=0, ek=point->keys; k<point->totkey; k++, ek++) {
00520                                         if(ek->flag & PEK_SELECT) {
00521                                                 calc_tw_center(scene, ek->flag & PEK_USE_WCO ? ek->world_co : ek->co);
00522                                                 totsel++;
00523                                         }
00524                                 }
00525                         }
00526 
00527                         /* selection center */
00528                         if(totsel)
00529                                 mul_v3_fl(scene->twcent, 1.0f/(float)totsel);   // centroid!
00530                 }
00531         }
00532         else {
00533 
00534                 /* we need the one selected object, if its not active */
00535                 ob= OBACT;
00536                 if(ob && !(ob->flag & SELECT)) ob= NULL;
00537 
00538                 for(base= scene->base.first; base; base= base->next) {
00539                         if TESTBASELIB(v3d, base) {
00540                                 if(ob==NULL)
00541                                         ob= base->object;
00542                                 calc_tw_center(scene, base->object->obmat[3]);
00543                                 protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
00544                                 totsel++;
00545                         }
00546                 }
00547 
00548                 /* selection center */
00549                 if(totsel) {
00550                         mul_v3_fl(scene->twcent, 1.0f/(float)totsel);   // centroid!
00551                 }
00552         }
00553 
00554         /* global, local or normal orientation? */
00555         if(ob && totsel) {
00556 
00557                 switch(v3d->twmode) {
00558                 
00559                 case V3D_MANIP_GLOBAL:
00560                         break; /* nothing to do */
00561 
00562                 case V3D_MANIP_GIMBAL:
00563                 {
00564                         float mat[3][3];
00565                         if (gimbal_axis(ob, mat)) {
00566                                 copy_m4_m3(rv3d->twmat, mat);
00567                                 break;
00568                         }
00569                         /* if not gimbal, fall through to normal */
00570                 }
00571                 case V3D_MANIP_NORMAL:
00572                         if(obedit || ob->mode & OB_MODE_POSE) {
00573                                 float mat[3][3];
00574                                 ED_getTransformOrientationMatrix(C, mat, (v3d->around == V3D_ACTIVE));
00575                                 copy_m4_m3(rv3d->twmat, mat);
00576                                 break;
00577                         }
00578                         /* no break we define 'normal' as 'local' in Object mode */
00579                 case V3D_MANIP_LOCAL:
00580                         copy_m4_m4(rv3d->twmat, ob->obmat);
00581                         normalize_m4(rv3d->twmat);
00582                         break;
00583 
00584                 case V3D_MANIP_VIEW:
00585                         {
00586                                 float mat[3][3];
00587                                 copy_m3_m4(mat, rv3d->viewinv);
00588                                 normalize_m3(mat);
00589                                 copy_m4_m3(rv3d->twmat, mat);
00590                         }
00591                         break;
00592                 default: /* V3D_MANIP_CUSTOM */
00593                         {
00594                                 float mat[3][3];
00595                                 applyTransformOrientation(C, mat, NULL);
00596                                 copy_m4_m3(rv3d->twmat, mat);
00597                                 break;
00598                         }
00599                 }
00600 
00601         }
00602 
00603         return totsel;
00604 }
00605 
00606 /* don't draw axis perpendicular to the view */
00607 static void test_manipulator_axis(const bContext *C)
00608 {
00609         RegionView3D *rv3d= CTX_wm_region_view3d(C);
00610         float angle;
00611         float vec[3];
00612 
00613         ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], vec);
00614 
00615         angle = fabs(angle_v3v3(rv3d->twmat[0], vec));
00616         if (angle > (float)M_PI / 2.0f) {
00617                 angle = (float)M_PI - angle;
00618         }
00619         angle = rv3d->twangle[0] = RAD2DEGF(angle);
00620         if (angle < 5.0f) {
00621                 rv3d->twdrawflag &= ~(MAN_TRANS_X|MAN_SCALE_X);
00622         }
00623 
00624         angle = fabs(angle_v3v3(rv3d->twmat[1], vec));
00625         if (angle > (float)M_PI / 2.0f) {
00626                 angle = (float)M_PI - angle;
00627         }
00628         angle = rv3d->twangle[1] = RAD2DEGF(angle);
00629         if (angle < 5.0f) {
00630                 rv3d->twdrawflag &= ~(MAN_TRANS_Y|MAN_SCALE_Y);
00631         }
00632 
00633         angle = fabs(angle_v3v3(rv3d->twmat[2], vec));
00634         if (angle > (float)M_PI / 2.0f) {
00635                 angle = (float)M_PI - angle;
00636         }
00637         angle = rv3d->twangle[2] = RAD2DEGF(angle);
00638         if (angle < 5.0f) {
00639                 rv3d->twdrawflag &= ~(MAN_TRANS_Z|MAN_SCALE_Z);
00640         }
00641 }
00642 
00643 
00644 /* ******************** DRAWING STUFFIES *********** */
00645 
00646 static float screen_aligned(RegionView3D *rv3d, float mat[][4])
00647 {
00648         glTranslatef(mat[3][0], mat[3][1], mat[3][2]);
00649 
00650         /* sets view screen aligned */
00651         glRotatef( -360.0f*saacos(rv3d->viewquat[0])/(float)M_PI, rv3d->viewquat[1], rv3d->viewquat[2], rv3d->viewquat[3]);
00652 
00653         return len_v3(mat[0]); /* draw scale */
00654 }
00655 
00656 
00657 /* radring = radius of donut rings
00658    radhole = radius hole
00659    start = starting segment (based on nrings)
00660    end   = end segment
00661    nsides = amount of points in ring
00662    nrigns = amount of rings
00663 */
00664 static void partial_donut(float radring, float radhole, int start, int end, int nsides, int nrings)
00665 {
00666         float theta, phi, theta1;
00667         float cos_theta, sin_theta;
00668         float cos_theta1, sin_theta1;
00669         float ring_delta, side_delta;
00670         int i, j, docaps= 1;
00671 
00672         if(start==0 && end==nrings) docaps= 0;
00673 
00674         ring_delta= 2.0f*(float)M_PI/(float)nrings;
00675         side_delta= 2.0f*(float)M_PI/(float)nsides;
00676 
00677         theta= (float)M_PI+0.5f*ring_delta;
00678         cos_theta= (float)cos(theta);
00679         sin_theta= (float)sin(theta);
00680 
00681         for(i= nrings - 1; i >= 0; i--) {
00682                 theta1= theta + ring_delta;
00683                 cos_theta1= (float)cos(theta1);
00684                 sin_theta1= (float)sin(theta1);
00685 
00686                 if(docaps && i==start) {        // cap
00687                         glBegin(GL_POLYGON);
00688                         phi= 0.0;
00689                         for(j= nsides; j >= 0; j--) {
00690                                 float cos_phi, sin_phi, dist;
00691 
00692                                 phi += side_delta;
00693                                 cos_phi= (float)cos(phi);
00694                                 sin_phi= (float)sin(phi);
00695                                 dist= radhole + radring * cos_phi;
00696 
00697                                 glVertex3f(cos_theta1 * dist, -sin_theta1 * dist,  radring * sin_phi);
00698                         }
00699                         glEnd();
00700                 }
00701                 if(i>=start && i<=end) {
00702                         glBegin(GL_QUAD_STRIP);
00703                         phi= 0.0;
00704                         for(j= nsides; j >= 0; j--) {
00705                                 float cos_phi, sin_phi, dist;
00706 
00707                                 phi += side_delta;
00708                                 cos_phi= (float)cos(phi);
00709                                 sin_phi= (float)sin(phi);
00710                                 dist= radhole + radring * cos_phi;
00711 
00712                                 glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi);
00713                                 glVertex3f(cos_theta * dist, -sin_theta * dist,  radring * sin_phi);
00714                         }
00715                         glEnd();
00716                 }
00717 
00718                 if(docaps && i==end) {  // cap
00719                         glBegin(GL_POLYGON);
00720                         phi= 0.0;
00721                         for(j= nsides; j >= 0; j--) {
00722                                 float cos_phi, sin_phi, dist;
00723 
00724                                 phi -= side_delta;
00725                                 cos_phi= (float)cos(phi);
00726                                 sin_phi= (float)sin(phi);
00727                                 dist= radhole + radring * cos_phi;
00728 
00729                                 glVertex3f(cos_theta * dist, -sin_theta * dist,  radring * sin_phi);
00730                         }
00731                         glEnd();
00732                 }
00733 
00734 
00735                 theta= theta1;
00736                 cos_theta= cos_theta1;
00737                 sin_theta= sin_theta1;
00738         }
00739 }
00740 
00741 static char axisBlendAngle(float angle)
00742 {
00743         if (angle > 20)
00744                 return 255;
00745 
00746         if (angle < 5)
00747                 return 0;
00748 
00749         return (char)(255.0f * (angle - 5) / 15.0f);
00750 }
00751 
00752 /* three colors can be set;
00753    grey for ghosting
00754    moving: in transform theme color
00755    else the red/green/blue
00756 */
00757 static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned char alpha)
00758 {
00759         unsigned char col[4]= {0};
00760         col[3]= alpha;
00761 
00762         if(colcode==MAN_GHOST) {
00763                 col[3]= 70;
00764         }
00765         else if(colcode==MAN_MOVECOL) {
00766                 UI_GetThemeColor3ubv(TH_TRANSFORM, col);
00767         }
00768         else {
00769                 switch(axis) {
00770                 case 'C':
00771                         UI_GetThemeColor3ubv(TH_TRANSFORM, col);
00772                         if(v3d->twmode == V3D_MANIP_LOCAL) {
00773                                 col[0]= col[0]>200?255:col[0]+55;
00774                                 col[1]= col[1]>200?255:col[1]+55;
00775                                 col[2]= col[2]>200?255:col[2]+55;
00776                         }
00777                         else if(v3d->twmode == V3D_MANIP_NORMAL) {
00778                                 col[0]= col[0]<55?0:col[0]-55;
00779                                 col[1]= col[1]<55?0:col[1]-55;
00780                                 col[2]= col[2]<55?0:col[2]-55;
00781                         }
00782                         break;
00783                 case 'X':
00784                         col[0]= 220;
00785                         break;
00786                 case 'Y':
00787                         col[1]= 220;
00788                         break;
00789                 case 'Z':
00790                         col[0]= 30;
00791                         col[1]= 30;
00792                         col[2]= 220;
00793                         break;
00794                 default:
00795                         BLI_assert(!"invalid axis arg");
00796                 }
00797         }
00798 
00799         glColor4ubv(col);
00800 }
00801 
00802 /* viewmatrix should have been set OK, also no shademode! */
00803 static void draw_manipulator_axes(View3D *v3d, RegionView3D *rv3d, int colcode, int flagx, int flagy, int flagz)
00804 {
00805 
00806         /* axes */
00807         if(flagx) {
00808                 manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
00809                 if(flagx & MAN_SCALE_X) glLoadName(MAN_SCALE_X);
00810                 else if(flagx & MAN_TRANS_X) glLoadName(MAN_TRANS_X);
00811                 glBegin(GL_LINES);
00812                 glVertex3f(0.2f, 0.0f, 0.0f);
00813                 glVertex3f(1.0f, 0.0f, 0.0f);
00814                 glEnd();
00815         }
00816         if(flagy) {
00817                 if(flagy & MAN_SCALE_Y) glLoadName(MAN_SCALE_Y);
00818                 else if(flagy & MAN_TRANS_Y) glLoadName(MAN_TRANS_Y);
00819                 manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
00820                 glBegin(GL_LINES);
00821                 glVertex3f(0.0f, 0.2f, 0.0f);
00822                 glVertex3f(0.0f, 1.0f, 0.0f);
00823                 glEnd();
00824         }
00825         if(flagz) {
00826                 if(flagz & MAN_SCALE_Z) glLoadName(MAN_SCALE_Z);
00827                 else if(flagz & MAN_TRANS_Z) glLoadName(MAN_TRANS_Z);
00828                 manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
00829                 glBegin(GL_LINES);
00830                 glVertex3f(0.0f, 0.0f, 0.2f);
00831                 glVertex3f(0.0f, 0.0f, 1.0f);
00832                 glEnd();
00833         }
00834 }
00835 
00836 static void preOrthoFront(int ortho, float twmat[][4], int axis)
00837 {
00838         if (ortho == 0) {
00839                 float omat[4][4];
00840                 copy_m4_m4(omat, twmat);
00841                 orthogonalize_m4(omat, axis);
00842                 glPushMatrix();
00843                 glMultMatrixf(omat);
00844                 glFrontFace(is_negative_m4(omat) ? GL_CW:GL_CCW);
00845         }
00846 }
00847 
00848 static void postOrtho(int ortho)
00849 {
00850         if (ortho == 0) {
00851                 glPopMatrix();
00852         }
00853 }
00854 
00855 static void draw_manipulator_rotate(View3D *v3d, RegionView3D *rv3d, int moving, int drawflags, int combo)
00856 {
00857         GLUquadricObj *qobj;
00858         double plane[4];
00859         float matt[4][4];
00860         float size, unitmat[4][4];
00861         float cywid= 0.33f*0.01f*(float)U.tw_handlesize;
00862         float cusize= cywid*0.65f;
00863         int arcs= (G.rt!=2);
00864         int colcode;
00865         int ortho;
00866 
00867         if(moving) colcode= MAN_MOVECOL;
00868         else colcode= MAN_RGB;
00869 
00870         /* when called while moving in mixed mode, do not draw when... */
00871         if((drawflags & MAN_ROT_C)==0) return;
00872 
00873         /* Init stuff */
00874         glDisable(GL_DEPTH_TEST);
00875         unit_m4(unitmat);
00876 
00877         qobj= gluNewQuadric();
00878         gluQuadricDrawStyle(qobj, GLU_FILL);
00879 
00880         /* prepare for screen aligned draw */
00881         size= len_v3(rv3d->twmat[0]);
00882         glPushMatrix();
00883         glTranslatef(rv3d->twmat[3][0], rv3d->twmat[3][1], rv3d->twmat[3][2]);
00884 
00885         if(arcs) {
00886                 /* clipplane makes nice handles, calc here because of multmatrix but with translate! */
00887                 VECCOPY(plane, rv3d->viewinv[2]);
00888                 plane[3]= -0.02f*size; // clip just a bit more
00889                 glClipPlane(GL_CLIP_PLANE0, plane);
00890         }
00891         /* sets view screen aligned */
00892         glRotatef( -360.0f*saacos(rv3d->viewquat[0])/(float)M_PI, rv3d->viewquat[1], rv3d->viewquat[2], rv3d->viewquat[3]);
00893 
00894         /* Screen aligned help circle */
00895         if(arcs) {
00896                 if((G.f & G_PICKSEL)==0) {
00897                         UI_ThemeColorShade(TH_BACK, -30);
00898                         drawcircball(GL_LINE_LOOP, unitmat[3], size, unitmat);
00899                 }
00900         }
00901 
00902         /* Screen aligned trackball rot circle */
00903         if(drawflags & MAN_ROT_T) {
00904                 if(G.f & G_PICKSEL) glLoadName(MAN_ROT_T);
00905 
00906                 UI_ThemeColor(TH_TRANSFORM);
00907                 drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f*size, unitmat);
00908         }
00909 
00910         /* Screen aligned view rot circle */
00911         if(drawflags & MAN_ROT_V) {
00912                 if(G.f & G_PICKSEL) glLoadName(MAN_ROT_V);
00913                 UI_ThemeColor(TH_TRANSFORM);
00914                 drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f*size, unitmat);
00915 
00916                 if(moving) {
00917                         float vec[3];
00918                         vec[0]= 0; // XXX (float)(t->imval[0] - t->center2d[0]);
00919                         vec[1]= 0; // XXX (float)(t->imval[1] - t->center2d[1]);
00920                         vec[2]= 0.0f;
00921                         normalize_v3(vec);
00922                         mul_v3_fl(vec, 1.2f*size);
00923                         glBegin(GL_LINES);
00924                         glVertex3f(0.0f, 0.0f, 0.0f);
00925                         glVertex3fv(vec);
00926                         glEnd();
00927                 }
00928         }
00929         glPopMatrix();
00930 
00931 
00932         ortho = is_orthogonal_m4(rv3d->twmat);
00933         
00934         /* apply the transform delta */
00935         if(moving) {
00936                 copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
00937                 // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat);
00938                 if (ortho) {
00939                         glMultMatrixf(matt);
00940                         glFrontFace(is_negative_m4(matt) ? GL_CW:GL_CCW);
00941                 }
00942         }
00943         else {
00944                 if (ortho) {
00945                         glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW:GL_CCW);
00946                         glMultMatrixf(rv3d->twmat);
00947                 }
00948         }
00949 
00950         /* axes */
00951         if(arcs==0) {
00952                 if(!(G.f & G_PICKSEL)) {
00953                         if( (combo & V3D_MANIP_SCALE)==0) {
00954                                 /* axis */
00955                                 if( (drawflags & MAN_ROT_X) || (moving && (drawflags & MAN_ROT_Z)) ) {
00956                                         preOrthoFront(ortho, rv3d->twmat, 2);
00957                                         manipulator_setcolor(v3d, 'X', colcode, 255);
00958                                         glBegin(GL_LINES);
00959                                         glVertex3f(0.2f, 0.0f, 0.0f);
00960                                         glVertex3f(1.0f, 0.0f, 0.0f);
00961                                         glEnd();
00962                                         postOrtho(ortho);
00963                                 }
00964                                 if( (drawflags & MAN_ROT_Y) || (moving && (drawflags & MAN_ROT_X)) ) {
00965                                         preOrthoFront(ortho, rv3d->twmat, 0);
00966                                         manipulator_setcolor(v3d, 'Y', colcode, 255);
00967                                         glBegin(GL_LINES);
00968                                         glVertex3f(0.0f, 0.2f, 0.0f);
00969                                         glVertex3f(0.0f, 1.0f, 0.0f);
00970                                         glEnd();
00971                                         postOrtho(ortho);
00972                                 }
00973                                 if( (drawflags & MAN_ROT_Z) || (moving && (drawflags & MAN_ROT_Y)) ) {
00974                                         preOrthoFront(ortho, rv3d->twmat, 1);
00975                                         manipulator_setcolor(v3d, 'Z', colcode, 255);
00976                                         glBegin(GL_LINES);
00977                                         glVertex3f(0.0f, 0.0f, 0.2f);
00978                                         glVertex3f(0.0f, 0.0f, 1.0f);
00979                                         glEnd();
00980                                         postOrtho(ortho);
00981                                 }
00982                         }
00983                 }
00984         }
00985 
00986         if(arcs==0 && moving) {
00987 
00988                 /* Z circle */
00989                 if(drawflags & MAN_ROT_Z) {
00990                         preOrthoFront(ortho, matt, 2);
00991                         if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
00992                         manipulator_setcolor(v3d, 'Z', colcode, 255);
00993                         drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
00994                         postOrtho(ortho);
00995                 }
00996                 /* X circle */
00997                 if(drawflags & MAN_ROT_X) {
00998                         preOrthoFront(ortho, matt, 0);
00999                         if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
01000                         glRotatef(90.0, 0.0, 1.0, 0.0);
01001                         manipulator_setcolor(v3d, 'X', colcode, 255);
01002                         drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
01003                         glRotatef(-90.0, 0.0, 1.0, 0.0);
01004                         postOrtho(ortho);
01005                 }
01006                 /* Y circle */
01007                 if(drawflags & MAN_ROT_Y) {
01008                         preOrthoFront(ortho, matt, 1);
01009                         if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
01010                         glRotatef(-90.0, 1.0, 0.0, 0.0);
01011                         manipulator_setcolor(v3d, 'Y', colcode, 255);
01012                         drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
01013                         glRotatef(90.0, 1.0, 0.0, 0.0);
01014                         postOrtho(ortho);
01015                 }
01016 
01017                 if(arcs) glDisable(GL_CLIP_PLANE0);
01018         }
01019         // donut arcs
01020         if(arcs) {
01021                 glEnable(GL_CLIP_PLANE0);
01022 
01023                 /* Z circle */
01024                 if(drawflags & MAN_ROT_Z) {
01025                         preOrthoFront(ortho, rv3d->twmat, 2);
01026                         if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
01027                         manipulator_setcolor(v3d, 'Z', colcode, 255);
01028                         partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
01029                         postOrtho(ortho);
01030                 }
01031                 /* X circle */
01032                 if(drawflags & MAN_ROT_X) {
01033                         preOrthoFront(ortho, rv3d->twmat, 0);
01034                         if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
01035                         glRotatef(90.0, 0.0, 1.0, 0.0);
01036                         manipulator_setcolor(v3d, 'X', colcode, 255);
01037                         partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
01038                         glRotatef(-90.0, 0.0, 1.0, 0.0);
01039                         postOrtho(ortho);
01040                 }
01041                 /* Y circle */
01042                 if(drawflags & MAN_ROT_Y) {
01043                         preOrthoFront(ortho, rv3d->twmat, 1);
01044                         if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
01045                         glRotatef(-90.0, 1.0, 0.0, 0.0);
01046                         manipulator_setcolor(v3d, 'Y', colcode, 255);
01047                         partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
01048                         glRotatef(90.0, 1.0, 0.0, 0.0);
01049                         postOrtho(ortho);
01050                 }
01051 
01052                 glDisable(GL_CLIP_PLANE0);
01053         }
01054 
01055         if(arcs==0) {
01056 
01057                 /* Z handle on X axis */
01058                 if(drawflags & MAN_ROT_Z) {
01059                         preOrthoFront(ortho, rv3d->twmat, 2);
01060                         glPushMatrix();
01061                         if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
01062                         manipulator_setcolor(v3d, 'Z', colcode, 255);
01063 
01064                         partial_donut(0.7f*cusize, 1.0f, 31, 33, 8, 64);
01065 
01066                         glPopMatrix();
01067                         postOrtho(ortho);
01068                 }
01069 
01070                 /* Y handle on X axis */
01071                 if(drawflags & MAN_ROT_Y) {
01072                         preOrthoFront(ortho, rv3d->twmat, 1);
01073                         glPushMatrix();
01074                         if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
01075                         manipulator_setcolor(v3d, 'Y', colcode, 255);
01076 
01077                         glRotatef(90.0, 1.0, 0.0, 0.0);
01078                         glRotatef(90.0, 0.0, 0.0, 1.0);
01079                         partial_donut(0.7f*cusize, 1.0f, 31, 33, 8, 64);
01080 
01081                         glPopMatrix();
01082                         postOrtho(ortho);
01083                 }
01084 
01085                 /* X handle on Z axis */
01086                 if(drawflags & MAN_ROT_X) {
01087                         preOrthoFront(ortho, rv3d->twmat, 0);
01088                         glPushMatrix();
01089                         if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
01090                         manipulator_setcolor(v3d, 'X', colcode, 255);
01091 
01092                         glRotatef(-90.0, 0.0, 1.0, 0.0);
01093                         glRotatef(90.0, 0.0, 0.0, 1.0);
01094                         partial_donut(0.7f*cusize, 1.0f, 31, 33, 8, 64);
01095 
01096                         glPopMatrix();
01097                         postOrtho(ortho);
01098                 }
01099 
01100         }
01101 
01102         /* restore */
01103         glLoadMatrixf(rv3d->viewmat);
01104         gluDeleteQuadric(qobj);
01105         if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
01106 
01107 }
01108 
01109 static void drawsolidcube(float size)
01110 {
01111         static float cube[8][3] = {
01112         {-1.0, -1.0, -1.0},
01113         {-1.0, -1.0,  1.0},
01114         {-1.0,  1.0,  1.0},
01115         {-1.0,  1.0, -1.0},
01116         { 1.0, -1.0, -1.0},
01117         { 1.0, -1.0,  1.0},
01118         { 1.0,  1.0,  1.0},
01119         { 1.0,  1.0, -1.0},     };
01120         float n[3];
01121 
01122         glPushMatrix();
01123         glScalef(size, size, size);
01124 
01125         n[0]=0; n[1]=0; n[2]=0;
01126         glBegin(GL_QUADS);
01127         n[0]= -1.0;
01128         glNormal3fv(n);
01129         glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
01130         n[0]=0;
01131         glEnd();
01132 
01133         glBegin(GL_QUADS);
01134         n[1]= -1.0;
01135         glNormal3fv(n);
01136         glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
01137         n[1]=0;
01138         glEnd();
01139 
01140         glBegin(GL_QUADS);
01141         n[0]= 1.0;
01142         glNormal3fv(n);
01143         glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
01144         n[0]=0;
01145         glEnd();
01146 
01147         glBegin(GL_QUADS);
01148         n[1]= 1.0;
01149         glNormal3fv(n);
01150         glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
01151         n[1]=0;
01152         glEnd();
01153 
01154         glBegin(GL_QUADS);
01155         n[2]= 1.0;
01156         glNormal3fv(n);
01157         glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
01158         n[2]=0;
01159         glEnd();
01160 
01161         glBegin(GL_QUADS);
01162         n[2]= -1.0;
01163         glNormal3fv(n);
01164         glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
01165         glEnd();
01166 
01167         glPopMatrix();
01168 }
01169 
01170 
01171 static void draw_manipulator_scale(View3D *v3d, RegionView3D *rv3d, int moving, int drawflags, int combo, int colcode)
01172 {
01173         float cywid= 0.25f*0.01f*(float)U.tw_handlesize;
01174         float cusize= cywid*0.75f, dz;
01175 
01176         /* when called while moving in mixed mode, do not draw when... */
01177         if((drawflags & MAN_SCALE_C)==0) return;
01178 
01179         glDisable(GL_DEPTH_TEST);
01180 
01181         /* not in combo mode */
01182         if( (combo & (V3D_MANIP_TRANSLATE|V3D_MANIP_ROTATE))==0) {
01183                 float size, unitmat[4][4];
01184                 int shift= 0; // XXX
01185 
01186                 /* center circle, do not add to selection when shift is pressed (planar constraint)  */
01187                 if( (G.f & G_PICKSEL) && shift==0) glLoadName(MAN_SCALE_C);
01188 
01189                 manipulator_setcolor(v3d, 'C', colcode, 255);
01190                 glPushMatrix();
01191                 size= screen_aligned(rv3d, rv3d->twmat);
01192                 unit_m4(unitmat);
01193                 drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f*size, unitmat);
01194                 glPopMatrix();
01195 
01196                 dz= 1.0;
01197         }
01198         else dz= 1.0f-4.0f*cusize;
01199 
01200         if(moving) {
01201                 float matt[4][4];
01202 
01203                 copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
01204                 // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat);
01205                 glMultMatrixf(matt);
01206                 glFrontFace(is_negative_m4(matt) ? GL_CW:GL_CCW);
01207         }
01208         else {
01209                 glMultMatrixf(rv3d->twmat);
01210                 glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW:GL_CCW);
01211         }
01212 
01213         /* axis */
01214 
01215         /* in combo mode, this is always drawn as first type */
01216         draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z);
01217 
01218         /* Z cube */
01219         glTranslatef(0.0, 0.0, dz);
01220         if(drawflags & MAN_SCALE_Z) {
01221                 if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_Z);
01222                 manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
01223                 drawsolidcube(cusize);
01224         }
01225         /* X cube */
01226         glTranslatef(dz, 0.0, -dz);
01227         if(drawflags & MAN_SCALE_X) {
01228                 if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_X);
01229                 manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
01230                 drawsolidcube(cusize);
01231         }
01232         /* Y cube */
01233         glTranslatef(-dz, dz, 0.0);
01234         if(drawflags & MAN_SCALE_Y) {
01235                 if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_Y);
01236                 manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
01237                 drawsolidcube(cusize);
01238         }
01239 
01240         /* if shiftkey, center point as last, for selectbuffer order */
01241         if(G.f & G_PICKSEL) {
01242                 int shift= 0; // XXX
01243 
01244                 if(shift) {
01245                         glTranslatef(0.0, -dz, 0.0);
01246                         glLoadName(MAN_SCALE_C);
01247                         glBegin(GL_POINTS);
01248                         glVertex3f(0.0, 0.0, 0.0);
01249                         glEnd();
01250                 }
01251         }
01252 
01253         /* restore */
01254         glLoadMatrixf(rv3d->viewmat);
01255 
01256         if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
01257         glFrontFace(GL_CCW);
01258 }
01259 
01260 
01261 static void draw_cone(GLUquadricObj *qobj, float len, float width)
01262 {
01263         glTranslatef(0.0, 0.0, -0.5f*len);
01264         gluCylinder(qobj, width, 0.0, len, 8, 1);
01265         gluQuadricOrientation(qobj, GLU_INSIDE);
01266         gluDisk(qobj, 0.0, width, 8, 1);
01267         gluQuadricOrientation(qobj, GLU_OUTSIDE);
01268         glTranslatef(0.0, 0.0, 0.5f*len);
01269 }
01270 
01271 static void draw_cylinder(GLUquadricObj *qobj, float len, float width)
01272 {
01273 
01274         width*= 0.8f;   // just for beauty
01275 
01276         glTranslatef(0.0, 0.0, -0.5f*len);
01277         gluCylinder(qobj, width, width, len, 8, 1);
01278         gluQuadricOrientation(qobj, GLU_INSIDE);
01279         gluDisk(qobj, 0.0, width, 8, 1);
01280         gluQuadricOrientation(qobj, GLU_OUTSIDE);
01281         glTranslatef(0.0, 0.0, len);
01282         gluDisk(qobj, 0.0, width, 8, 1);
01283         glTranslatef(0.0, 0.0, -0.5f*len);
01284 }
01285 
01286 
01287 static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int UNUSED(moving), int drawflags, int combo, int colcode)
01288 {
01289         GLUquadricObj *qobj;
01290         float cylen= 0.01f*(float)U.tw_handlesize;
01291         float cywid= 0.25f*cylen, dz, size;
01292         float unitmat[4][4];
01293         int shift= 0; // XXX
01294 
01295         /* when called while moving in mixed mode, do not draw when... */
01296         if((drawflags & MAN_TRANS_C)==0) return;
01297 
01298         // XXX if(moving) glTranslatef(t->vec[0], t->vec[1], t->vec[2]);
01299         glDisable(GL_DEPTH_TEST);
01300 
01301         qobj= gluNewQuadric();
01302         gluQuadricDrawStyle(qobj, GLU_FILL);
01303 
01304         /* center circle, do not add to selection when shift is pressed (planar constraint) */
01305         if( (G.f & G_PICKSEL) && shift==0) glLoadName(MAN_TRANS_C);
01306 
01307         manipulator_setcolor(v3d, 'C', colcode, 255);
01308         glPushMatrix();
01309         size= screen_aligned(rv3d, rv3d->twmat);
01310         unit_m4(unitmat);
01311         drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f*size, unitmat);
01312         glPopMatrix();
01313 
01314         /* and now apply matrix, we move to local matrix drawing */
01315         glMultMatrixf(rv3d->twmat);
01316 
01317         /* axis */
01318         glLoadName(-1);
01319 
01320         // translate drawn as last, only axis when no combo with scale, or for ghosting
01321         if((combo & V3D_MANIP_SCALE)==0 || colcode==MAN_GHOST)
01322                 draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z);
01323 
01324 
01325         /* offset in combo mode, for rotate a bit more */
01326         if(combo & (V3D_MANIP_ROTATE)) dz= 1.0f+2.0f*cylen;
01327         else if(combo & (V3D_MANIP_SCALE)) dz= 1.0f+0.5f*cylen;
01328         else dz= 1.0f;
01329 
01330         /* Z Cone */
01331         glTranslatef(0.0, 0.0, dz);
01332         if(drawflags & MAN_TRANS_Z) {
01333                 if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_Z);
01334                 manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
01335                 draw_cone(qobj, cylen, cywid);
01336         }
01337         /* X Cone */
01338         glTranslatef(dz, 0.0, -dz);
01339         if(drawflags & MAN_TRANS_X) {
01340                 if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_X);
01341                 glRotatef(90.0, 0.0, 1.0, 0.0);
01342                 manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
01343                 draw_cone(qobj, cylen, cywid);
01344                 glRotatef(-90.0, 0.0, 1.0, 0.0);
01345         }
01346         /* Y Cone */
01347         glTranslatef(-dz, dz, 0.0);
01348         if(drawflags & MAN_TRANS_Y) {
01349                 if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_Y);
01350                 glRotatef(-90.0, 1.0, 0.0, 0.0);
01351                 manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
01352                 draw_cone(qobj, cylen, cywid);
01353         }
01354 
01355         gluDeleteQuadric(qobj);
01356         glLoadMatrixf(rv3d->viewmat);
01357 
01358         if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
01359 
01360 }
01361 
01362 static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int moving, int drawflags, int combo, int colcode)
01363 {
01364         GLUquadricObj *qobj;
01365         float size;
01366         float cylen= 0.01f*(float)U.tw_handlesize;
01367         float cywid= 0.25f*cylen;
01368 
01369         /* when called while moving in mixed mode, do not draw when... */
01370         if((drawflags & MAN_ROT_C)==0) return;
01371 
01372         /* prepare for screen aligned draw */
01373         glPushMatrix();
01374         size= screen_aligned(rv3d, rv3d->twmat);
01375 
01376         glDisable(GL_DEPTH_TEST);
01377 
01378         qobj= gluNewQuadric();
01379 
01380         /* Screen aligned view rot circle */
01381         if(drawflags & MAN_ROT_V) {
01382                 float unitmat[4][4]= MAT4_UNITY;
01383 
01384                 if(G.f & G_PICKSEL) glLoadName(MAN_ROT_V);
01385                 UI_ThemeColor(TH_TRANSFORM);
01386                 drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f*size, unitmat);
01387 
01388                 if(moving) {
01389                         float vec[3];
01390                         vec[0]= 0; // XXX (float)(t->imval[0] - t->center2d[0]);
01391                         vec[1]= 0; // XXX (float)(t->imval[1] - t->center2d[1]);
01392                         vec[2]= 0.0f;
01393                         normalize_v3(vec);
01394                         mul_v3_fl(vec, 1.2f*size);
01395                         glBegin(GL_LINES);
01396                         glVertex3f(0.0, 0.0, 0.0);
01397                         glVertex3fv(vec);
01398                         glEnd();
01399                 }
01400         }
01401         glPopMatrix();
01402 
01403         /* apply the transform delta */
01404         if(moving) {
01405                 float matt[4][4];
01406                 copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
01407                 // XXX          if (t->flag & T_USES_MANIPULATOR) {
01408                 // XXX                  mul_m4_m3m4(matt, t->mat, rv3d->twmat);
01409                 // XXX }
01410                 glMultMatrixf(matt);
01411         }
01412         else {
01413                 glMultMatrixf(rv3d->twmat);
01414         }
01415 
01416         glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW:GL_CCW);
01417 
01418         /* axis */
01419         if( (G.f & G_PICKSEL)==0 ) {
01420 
01421                 // only draw axis when combo didn't draw scale axes
01422                 if((combo & V3D_MANIP_SCALE)==0)
01423                         draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z);
01424 
01425                 /* only has to be set when not in picking */
01426                 gluQuadricDrawStyle(qobj, GLU_FILL);
01427         }
01428 
01429         /* Z cyl */
01430         glTranslatef(0.0, 0.0, 1.0);
01431         if(drawflags & MAN_ROT_Z) {
01432                 if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
01433                 manipulator_setcolor(v3d, 'Z', colcode, 255);
01434                 draw_cylinder(qobj, cylen, cywid);
01435         }
01436         /* X cyl */
01437         glTranslatef(1.0, 0.0, -1.0);
01438         if(drawflags & MAN_ROT_X) {
01439                 if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
01440                 glRotatef(90.0, 0.0, 1.0, 0.0);
01441                 manipulator_setcolor(v3d, 'X', colcode, 255);
01442                 draw_cylinder(qobj, cylen, cywid);
01443                 glRotatef(-90.0, 0.0, 1.0, 0.0);
01444         }
01445         /* Y cylinder */
01446         glTranslatef(-1.0, 1.0, 0.0);
01447         if(drawflags & MAN_ROT_Y) {
01448                 if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
01449                 glRotatef(-90.0, 1.0, 0.0, 0.0);
01450                 manipulator_setcolor(v3d, 'Y', colcode, 255);
01451                 draw_cylinder(qobj, cylen, cywid);
01452         }
01453 
01454         /* restore */
01455 
01456         gluDeleteQuadric(qobj);
01457         glLoadMatrixf(rv3d->viewmat);
01458 
01459         if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
01460 
01461 }
01462 
01463 
01464 /* ********************************************* */
01465 
01466 /* main call, does calc centers & orientation too */
01467 /* uses global G.moving */
01468 static int drawflags= 0xFFFF;           // only for the calls below, belongs in scene...?
01469 
01470 void BIF_draw_manipulator(const bContext *C)
01471 {
01472         ScrArea *sa= CTX_wm_area(C);
01473         ARegion *ar= CTX_wm_region(C);
01474         Scene *scene= CTX_data_scene(C);
01475         View3D *v3d= sa->spacedata.first;
01476         RegionView3D *rv3d= ar->regiondata;
01477         int totsel;
01478 
01479         if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return;
01480 //      if(G.moving && (G.moving & G_TRANSFORM_MANIP)==0) return;
01481 
01482 //      if(G.moving==0) {
01483         {
01484                 v3d->twflag &= ~V3D_DRAW_MANIPULATOR;
01485 
01486                 totsel= calc_manipulator_stats(C);
01487                 if(totsel==0) return;
01488 
01489                 v3d->twflag |= V3D_DRAW_MANIPULATOR;
01490 
01491                 /* now we can define center */
01492                 switch(v3d->around) {
01493                 case V3D_CENTER:
01494                 case V3D_ACTIVE:
01495                         rv3d->twmat[3][0]= (scene->twmin[0] + scene->twmax[0])/2.0f;
01496                         rv3d->twmat[3][1]= (scene->twmin[1] + scene->twmax[1])/2.0f;
01497                         rv3d->twmat[3][2]= (scene->twmin[2] + scene->twmax[2])/2.0f;
01498                         if(v3d->around==V3D_ACTIVE && scene->obedit==NULL) {
01499                                 Object *ob= OBACT;
01500                                 if(ob && !(ob->mode & OB_MODE_POSE))
01501                                         VECCOPY(rv3d->twmat[3], ob->obmat[3]);
01502                         }
01503                         break;
01504                 case V3D_LOCAL:
01505                 case V3D_CENTROID:
01506                         VECCOPY(rv3d->twmat[3], scene->twcent);
01507                         break;
01508                 case V3D_CURSOR:
01509                         VECCOPY(rv3d->twmat[3], give_cursor(scene, v3d));
01510                         break;
01511                 }
01512 
01513                 mul_mat3_m4_fl(rv3d->twmat, ED_view3d_pixel_size(rv3d, rv3d->twmat[3]) * U.tw_size * 5.0f);
01514         }
01515 
01516         test_manipulator_axis(C);
01517         drawflags= rv3d->twdrawflag;    /* set in calc_manipulator_stats */
01518 
01519         if(v3d->twflag & V3D_DRAW_MANIPULATOR) {
01520 
01521                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
01522                 glEnable(GL_BLEND);
01523                 if(v3d->twtype & V3D_MANIP_ROTATE) {
01524 
01525                         if(G.rt==3) {
01526                                 if(G.moving) draw_manipulator_rotate_cyl(v3d, rv3d, 1, drawflags, v3d->twtype, MAN_MOVECOL);
01527                                 else draw_manipulator_rotate_cyl(v3d, rv3d, 0, drawflags, v3d->twtype, MAN_RGB);
01528                         }
01529                         else
01530                                 draw_manipulator_rotate(v3d, rv3d, 0 /* G.moving*/, drawflags, v3d->twtype);
01531                 }
01532                 if(v3d->twtype & V3D_MANIP_SCALE) {
01533                         draw_manipulator_scale(v3d, rv3d, 0, drawflags, v3d->twtype, MAN_RGB);
01534                 }
01535                 if(v3d->twtype & V3D_MANIP_TRANSLATE) {
01536                         draw_manipulator_translate(v3d, rv3d, 0, drawflags, v3d->twtype, MAN_RGB);
01537                 }
01538 
01539                 glDisable(GL_BLEND);
01540         }
01541 }
01542 
01543 static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], float hotspot)
01544 {
01545         View3D *v3d= sa->spacedata.first;
01546         RegionView3D *rv3d= ar->regiondata;
01547         rctf rect;
01548         GLuint buffer[64];              // max 4 items per select, so large enuf
01549         short hits;
01550         extern void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect); // XXX check a bit later on this... (ton)
01551 
01552         G.f |= G_PICKSEL;
01553 
01554         rect.xmin= mval[0]-hotspot;
01555         rect.xmax= mval[0]+hotspot;
01556         rect.ymin= mval[1]-hotspot;
01557         rect.ymax= mval[1]+hotspot;
01558 
01559         setwinmatrixview3d(ar, v3d, &rect);
01560         mul_m4_m4m4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
01561 
01562         glSelectBuffer( 64, buffer);
01563         glRenderMode(GL_SELECT);
01564         glInitNames();  /* these two calls whatfor? It doesnt work otherwise */
01565         glPushName(-2);
01566 
01567         /* do the drawing */
01568         if(v3d->twtype & V3D_MANIP_ROTATE) {
01569                 if(G.rt==3) draw_manipulator_rotate_cyl(v3d, rv3d, 0, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB);
01570                 else draw_manipulator_rotate(v3d, rv3d, 0, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype);
01571         }
01572         if(v3d->twtype & V3D_MANIP_SCALE)
01573                 draw_manipulator_scale(v3d, rv3d, 0, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB);
01574         if(v3d->twtype & V3D_MANIP_TRANSLATE)
01575                 draw_manipulator_translate(v3d, rv3d, 0, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB);
01576 
01577         glPopName();
01578         hits= glRenderMode(GL_RENDER);
01579 
01580         G.f &= ~G_PICKSEL;
01581         setwinmatrixview3d(ar, v3d, NULL);
01582         mul_m4_m4m4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
01583 
01584         if(hits==1) return buffer[3];
01585         else if(hits>1) {
01586                 GLuint val, dep, mindep=0, mindeprot=0, minval=0, minvalrot=0;
01587                 int a;
01588 
01589                 /* we compare the hits in buffer, but value centers highest */
01590                 /* we also store the rotation hits separate (because of arcs) and return hits on other widgets if there are */
01591 
01592                 for(a=0; a<hits; a++) {
01593                         dep= buffer[4*a + 1];
01594                         val= buffer[4*a + 3];
01595 
01596                         if(val==MAN_TRANS_C) return MAN_TRANS_C;
01597                         else if(val==MAN_SCALE_C) return MAN_SCALE_C;
01598                         else {
01599                                 if(val & MAN_ROT_C) {
01600                                         if(minvalrot==0 || dep<mindeprot) {
01601                                                 mindeprot= dep;
01602                                                 minvalrot= val;
01603                                         }
01604                                 }
01605                                 else {
01606                                         if(minval==0 || dep<mindep) {
01607                                                 mindep= dep;
01608                                                 minval= val;
01609                                         }
01610                                 }
01611                         }
01612                 }
01613 
01614                 if(minval)
01615                         return minval;
01616                 else
01617                         return minvalrot;
01618         }
01619         return 0;
01620 }
01621 
01622 
01623 /* return 0; nothing happened */
01624 int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op)
01625 {
01626         ScrArea *sa= CTX_wm_area(C);
01627         View3D *v3d= sa->spacedata.first;
01628         ARegion *ar= CTX_wm_region(C);
01629         int constraint_axis[3] = {0, 0, 0};
01630         int val;
01631         int shift = event->shift;
01632 
01633         if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return 0;
01634         if(!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return 0;
01635 
01636         /* Force orientation */
01637         RNA_enum_set(op->ptr, "constraint_orientation", v3d->twmode);
01638 
01639         // find the hotspots first test narrow hotspot
01640         val= manipulator_selectbuf(sa, ar, event->mval, 0.5f*(float)U.tw_hotspot);
01641         if(val) {
01642 
01643                 // drawflags still global, for drawing call above
01644                 drawflags= manipulator_selectbuf(sa, ar, event->mval, 0.2f*(float)U.tw_hotspot);
01645                 if(drawflags==0) drawflags= val;
01646 
01647                 if (drawflags & MAN_TRANS_C) {
01648                         switch(drawflags) {
01649                         case MAN_TRANS_C:
01650                                 break;
01651                         case MAN_TRANS_X:
01652                                 if(shift) {
01653                                         constraint_axis[1] = 1;
01654                                         constraint_axis[2] = 1;
01655                                 }
01656                                 else
01657                                         constraint_axis[0] = 1;
01658                                 break;
01659                         case MAN_TRANS_Y:
01660                                 if(shift) {
01661                                         constraint_axis[0] = 1;
01662                                         constraint_axis[2] = 1;
01663                                 }
01664                                 else
01665                                         constraint_axis[1] = 1;
01666                                 break;
01667                         case MAN_TRANS_Z:
01668                                 if(shift) {
01669                                         constraint_axis[0] = 1;
01670                                         constraint_axis[1] = 1;
01671                                 }
01672                                 else
01673                                         constraint_axis[2] = 1;
01674                                 break;
01675                         }
01676                         RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
01677                         WM_operator_name_call(C, "TRANSFORM_OT_translate", WM_OP_INVOKE_DEFAULT, op->ptr);
01678                         //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_translate", 0), event, op->ptr, NULL, FALSE);
01679                 }
01680                 else if (drawflags & MAN_SCALE_C) {
01681                         switch(drawflags) {
01682                         case MAN_SCALE_X:
01683                                 if(shift) {
01684                                         constraint_axis[1] = 1;
01685                                         constraint_axis[2] = 1;
01686                                 }
01687                                 else
01688                                         constraint_axis[0] = 1;
01689                                 break;
01690                         case MAN_SCALE_Y:
01691                                 if(shift) {
01692                                         constraint_axis[0] = 1;
01693                                         constraint_axis[2] = 1;
01694                                 }
01695                                 else
01696                                         constraint_axis[1] = 1;
01697                                 break;
01698                         case MAN_SCALE_Z:
01699                                 if(shift) {
01700                                         constraint_axis[0] = 1;
01701                                         constraint_axis[1] = 1;
01702                                 }
01703                                 else
01704                                         constraint_axis[2] = 1;
01705                                 break;
01706                         }
01707                         RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
01708                         WM_operator_name_call(C, "TRANSFORM_OT_resize", WM_OP_INVOKE_DEFAULT, op->ptr);
01709                         //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_resize", 0), event, op->ptr, NULL, FALSE);
01710                 }
01711                 else if (drawflags == MAN_ROT_T) { /* trackball need special case, init is different */
01712                         WM_operator_name_call(C, "TRANSFORM_OT_trackball", WM_OP_INVOKE_DEFAULT, op->ptr);
01713                         //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_trackball", 0), event, op->ptr, NULL, FALSE);
01714                 }
01715                 else if (drawflags & MAN_ROT_C) {
01716                         switch(drawflags) {
01717                         case MAN_ROT_X:
01718                                 constraint_axis[0] = 1;
01719                                 break;
01720                         case MAN_ROT_Y:
01721                                 constraint_axis[1] = 1;
01722                                 break;
01723                         case MAN_ROT_Z:
01724                                 constraint_axis[2] = 1;
01725                                 break;
01726                         }
01727                         RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
01728                         WM_operator_name_call(C, "TRANSFORM_OT_rotate", WM_OP_INVOKE_DEFAULT, op->ptr);
01729                         //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_rotate", 0), event, op->ptr, NULL, FALSE);
01730                 }
01731         }
01732         /* after transform, restore drawflags */
01733         drawflags= 0xFFFF;
01734 
01735         return val;
01736 }
01737