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