~ubuntu-branches/ubuntu/gutsy/blender/gutsy-security

« back to all changes in this revision

Viewing changes to source/blender/src/transform_manipulator.c

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ernst
  • Date: 2005-11-06 12:40:03 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051106124003-3pgs7tcg5rox96xg
Tags: 2.37a-1.1
* Non-maintainer upload.
* Split out parts of 01_SConstruct_debian.dpatch again: root_build_dir
  really needs to get adjusted before the clean target runs - closes: #333958,
  see #288882 for reference

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
* $Id:
 
3
 *
 
4
 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version 2
 
9
 * of the License, or (at your option) any later version. The Blender
 
10
 * Foundation also sells licenses for use in proprietary software under
 
11
 * the Blender License.  See http://www.blender.org/BL/ for information
 
12
 * about this.
 
13
 *
 
14
 * This program is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with this program; if not, write to the Free Software Foundation,
 
21
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
22
 *
 
23
 * The Original Code is Copyright (C) 2005 Blender Foundation
 
24
 * All rights reserved.
 
25
 *
 
26
 * The Original Code is: all of this file.
 
27
 *
 
28
 * Contributor(s): none yet.
 
29
 *
 
30
 * ***** END GPL/BL DUAL LICENSE BLOCK *****
 
31
 */
 
32
 
 
33
#include <stdlib.h>
 
34
#include <string.h>
 
35
#include <math.h>
 
36
 
 
37
#ifdef HAVE_CONFIG_H
 
38
#include <config.h>
 
39
#endif
 
40
 
 
41
#ifndef WIN32
 
42
#include <unistd.h>
 
43
#else
 
44
#include <io.h>
 
45
#endif
 
46
 
 
47
#include "MEM_guardedalloc.h"
 
48
 
 
49
#include "DNA_armature_types.h"
 
50
#include "DNA_curve_types.h"
 
51
#include "DNA_lattice_types.h"
 
52
#include "DNA_mesh_types.h"
 
53
#include "DNA_meta_types.h"
 
54
#include "DNA_object_types.h"
 
55
#include "DNA_screen_types.h"
 
56
#include "DNA_scene_types.h"
 
57
#include "DNA_space_types.h"
 
58
#include "DNA_userdef_types.h"
 
59
#include "DNA_view3d_types.h"
 
60
 
 
61
#include "BKE_armature.h"
 
62
#include "BKE_DerivedMesh.h"
 
63
#include "BKE_global.h"
 
64
#include "BKE_lattice.h"
 
65
#include "BKE_object.h"
 
66
#include "BKE_utildefines.h"
 
67
 
 
68
#include "BLI_arithb.h"
 
69
#include "BLI_editVert.h"
 
70
 
 
71
#include "BIF_editarmature.h"
 
72
#include "BIF_gl.h"
 
73
#include "BIF_mywindow.h"
 
74
#include "BIF_resources.h"
 
75
#include "BIF_screen.h"
 
76
#include "BIF_space.h"
 
77
#include "BIF_transform.h"
 
78
 
 
79
#include "BSE_edit.h"
 
80
#include "BSE_view.h"
 
81
#include "BDR_drawobject.h"
 
82
 
 
83
#include "blendef.h"
 
84
#include "transform.h"
 
85
 
 
86
/* return codes for select, and drawing flags */
 
87
 
 
88
#define MAN_TRANS_X             1
 
89
#define MAN_TRANS_Y             2
 
90
#define MAN_TRANS_Z             4
 
91
#define MAN_TRANS_C             7
 
92
 
 
93
#define MAN_ROT_X               8
 
94
#define MAN_ROT_Y               16
 
95
#define MAN_ROT_Z               32
 
96
#define MAN_ROT_V               64
 
97
#define MAN_ROT_T               128
 
98
#define MAN_ROT_C               248
 
99
 
 
100
#define MAN_SCALE_X             256
 
101
#define MAN_SCALE_Y             512
 
102
#define MAN_SCALE_Z             1024
 
103
#define MAN_SCALE_C             1792
 
104
 
 
105
/* color codes */
 
106
 
 
107
#define MAN_RGB         0
 
108
#define MAN_GHOST       1
 
109
#define MAN_MOVECOL     2
 
110
 
 
111
/* GLOBAL VARIABLE THAT SHOULD MOVED TO SCREEN MEMBER OR SOMETHING  */
 
112
extern TransInfo Trans;
 
113
 
 
114
 
 
115
static int is_mat4_flipped(float mat[][4])
 
116
{
 
117
        float vec[3];
 
118
        
 
119
        Crossf(vec, mat[0], mat[1]);
 
120
        if( Inpf(vec, mat[2]) < 0.0 ) return 1;
 
121
        return 0;
 
122
}       
 
123
 
 
124
/* transform widget center calc helper for below */
 
125
static void calc_tw_center(float *co)
 
126
{
 
127
        float *twcent= G.scene->twcent;
 
128
        float *min= G.scene->twmin;
 
129
        float *max= G.scene->twmax;
 
130
        
 
131
        DO_MINMAX(co, min, max);
 
132
        VecAddf(twcent, twcent, co);
 
133
}
 
134
 
 
135
/* callback */
 
136
static void stats_pose(ListBase *lb, float *normal, float *plane)
 
137
{
 
138
        Bone *bone;
 
139
        float vec[3], mat[4][4];
 
140
        
 
141
        for(bone= lb->first; bone; bone= bone->next) {
 
142
                if (bone->flag & BONE_SELECTED) {
 
143
                        /* We don't let IK children get "grabbed" */
 
144
                        /* ALERT! abusive global Trans here */
 
145
                        if ( (Trans.mode!=TFM_TRANSLATION) || (bone->flag & BONE_IK_TOPARENT)==0 ) {
 
146
                                
 
147
                                get_bone_root_pos (bone, vec, 1);
 
148
                                
 
149
                                calc_tw_center(vec);
 
150
                                where_is_bone(G.obpose, bone);
 
151
                                get_objectspace_bone_matrix(bone, mat, 1, 1);   // points in negative Y o_O
 
152
                                        
 
153
                                VecAddf(normal, normal, mat[2]);
 
154
                                VecAddf(plane, plane, mat[1]);
 
155
                                
 
156
                                return; // see above function
 
157
                        }
 
158
                }
 
159
                stats_pose(&bone->childbase, normal, plane);
 
160
        }
 
161
}
 
162
 
 
163
 
 
164
/* centroid, boundbox, of selection */
 
165
/* returns total items selected */
 
166
int calc_manipulator_stats(ScrArea *sa)
 
167
{
 
168
        extern ListBase editNurb;
 
169
        View3D *v3d= sa->spacedata.first;
 
170
        Base *base;
 
171
        Object *ob=NULL;
 
172
        float normal[3]={0.0, 0.0, 0.0};
 
173
        float plane[3]={0.0, 0.0, 0.0};
 
174
        int a, totsel=0;
 
175
        
 
176
        /* transform widget matrix */
 
177
        Mat4One(v3d->twmat);
 
178
        
 
179
        /* transform widget centroid/center */
 
180
        G.scene->twcent[0]= G.scene->twcent[1]= G.scene->twcent[2]= 0.0f;
 
181
        INIT_MINMAX(G.scene->twmin, G.scene->twmax);
 
182
        
 
183
        if(G.obedit) {
 
184
                ob= G.obedit;
 
185
                if((ob->lay & G.vd->lay)==0) return 0;
 
186
 
 
187
                if(G.obedit->type==OB_MESH) {
 
188
                        int dmNeedsFree;
 
189
                        DerivedMesh *dm = mesh_get_cage_derived(G.obedit, &dmNeedsFree);
 
190
                        EditMesh *em = G.editMesh;
 
191
                        EditVert *eve;
 
192
                        float vec[3];
 
193
                        int no_faces= 1;
 
194
                        
 
195
                        if(v3d->twmode == V3D_MANIP_NORMAL) {
 
196
                                EditFace *efa;
 
197
                                
 
198
                                for(efa= em->faces.first; efa; efa= efa->next) {
 
199
                                        if(efa->f & SELECT) {
 
200
                                                no_faces= 0;
 
201
                                                VECADD(normal, normal, efa->n);
 
202
                                                VecSubf(vec, efa->v2->co, efa->v1->co);
 
203
                                                VECADD(plane, plane, vec);
 
204
                                        }
 
205
                                }
 
206
                        }
 
207
                        
 
208
                        /* do vertices for center, and if still no normal found, use vertex normals */
 
209
                        for(eve= em->verts.first; eve; eve= eve->next) {
 
210
                                if(eve->f & SELECT) {
 
211
                                        if(no_faces) VECADD(normal, normal, eve->no);
 
212
                                        
 
213
                                        totsel++;
 
214
                                        dm->getMappedVertCoEM(dm, eve, vec);
 
215
                                        calc_tw_center(vec);
 
216
                                }
 
217
                        }
 
218
                        /* the edge case... */
 
219
                        if(no_faces && v3d->twmode == V3D_MANIP_NORMAL) {
 
220
                                EditEdge *eed;
 
221
                                
 
222
                                for(eed= em->edges.first; eed; eed= eed->next) {
 
223
                                        if(eed->f & SELECT) {
 
224
                                                /* ok we got an edge, only use one, and as normal */
 
225
                                                VECCOPY(plane, normal);
 
226
                                                VecSubf(normal, eed->v2->co, eed->v1->co);
 
227
                                                break;
 
228
                                        }
 
229
                                }
 
230
                        }
 
231
                        if (dmNeedsFree) {
 
232
                                dm->release(dm);
 
233
                        }
 
234
                }
 
235
                else if (G.obedit->type==OB_ARMATURE){
 
236
                        EditBone *ebo;
 
237
                        for (ebo=G.edbo.first;ebo;ebo=ebo->next){
 
238
                                
 
239
                                //      If this is an IK child and it's parent is being moved, don't count as selected
 
240
                                if ((ebo->flag & BONE_IK_TOPARENT)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL));
 
241
                                else {
 
242
                                        if (ebo->flag & BONE_TIPSEL) {
 
243
                                                calc_tw_center(ebo->tail);
 
244
                                                totsel++;
 
245
                                        }
 
246
                                        if (ebo->flag & BONE_ROOTSEL) {
 
247
                                                calc_tw_center(ebo->head);
 
248
                                                totsel++;
 
249
                                        }
 
250
                                }
 
251
                        }
 
252
                }
 
253
                else if ELEM3(G.obedit->type, OB_CURVE, OB_SURF, OB_FONT) {
 
254
                        Nurb *nu;
 
255
                        BezTriple *bezt;
 
256
                        BPoint *bp;
 
257
                        
 
258
                        nu= editNurb.first;
 
259
                        while(nu) {
 
260
                                if((nu->type & 7)==CU_BEZIER) {
 
261
                                        bezt= nu->bezt;
 
262
                                        a= nu->pntsu;
 
263
                                        while(a--) {
 
264
                                                if(bezt->f1) {
 
265
                                                        calc_tw_center(bezt->vec[0]);
 
266
                                                        totsel++;
 
267
                                                }
 
268
                                                if(bezt->f2) {
 
269
                                                        calc_tw_center(bezt->vec[1]);
 
270
                                                        totsel++;
 
271
                                                }
 
272
                                                if(bezt->f3) {
 
273
                                                        calc_tw_center(bezt->vec[2]);
 
274
                                                        totsel++;
 
275
                                                }
 
276
                                                bezt++;
 
277
                                        }
 
278
                                }
 
279
                                else {
 
280
                                        bp= nu->bp;
 
281
                                        a= nu->pntsu*nu->pntsv;
 
282
                                        while(a--) {
 
283
                                                if(bp->f1 & 1) {
 
284
                                                        calc_tw_center(bp->vec);
 
285
                                                        totsel++;
 
286
                                                }
 
287
                                                bp++;
 
288
                                        }
 
289
                                }
 
290
                                nu= nu->next;
 
291
                        }
 
292
                }
 
293
                else if(G.obedit->type==OB_MBALL) {
 
294
                        /* editmball.c */
 
295
                        extern ListBase editelems;  /* go away ! */
 
296
                        MetaElem *ml;
 
297
                
 
298
                        ml= editelems.first;
 
299
                        while(ml) {
 
300
                                if(ml->flag & SELECT) {
 
301
                                        calc_tw_center(&ml->x);
 
302
                                        totsel++;
 
303
                                }
 
304
                                ml= ml->next;
 
305
                        }
 
306
                }
 
307
                else if(G.obedit->type==OB_LATTICE) {
 
308
                        BPoint *bp;
 
309
                        bp= editLatt->def;
 
310
                        
 
311
                        a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
 
312
                        while(a--) {
 
313
                                if(bp->f1 & 1) {
 
314
                                        calc_tw_center(bp->vec);
 
315
                                        totsel++;
 
316
                                }
 
317
                                bp++;
 
318
                        }
 
319
                }
 
320
                
 
321
                /* selection center */
 
322
                if(totsel) {
 
323
                        VecMulf(G.scene->twcent, 1.0f/(float)totsel);   // centroid!
 
324
                        Mat4MulVecfl(G.obedit->obmat, G.scene->twcent);
 
325
                        Mat4MulVecfl(G.obedit->obmat, G.scene->twmin);
 
326
                        Mat4MulVecfl(G.obedit->obmat, G.scene->twmax);
 
327
                }
 
328
        }
 
329
        else if(G.obpose) {
 
330
                bArmature *arm= G.obpose->data;
 
331
                
 
332
                ob= G.obpose;
 
333
                if((ob->lay & G.vd->lay)==0) return 0;
 
334
                
 
335
                Trans.mode= TFM_ROTATION;       // mislead counting bones... bah
 
336
                
 
337
                /* count total */
 
338
                count_bone_select(&Trans, &arm->bonebase, &totsel);
 
339
                if(totsel) {
 
340
                        /* recursive get stats */
 
341
                        stats_pose(&arm->bonebase, normal, plane);
 
342
                        
 
343
                        //VecMulf(normal, -1.0);
 
344
                        VecMulf(plane, -1.0);
 
345
                        
 
346
                        VecMulf(G.scene->twcent, 1.0f/(float)totsel);   // centroid!
 
347
                        Mat4MulVecfl(G.obpose->obmat, G.scene->twcent);
 
348
                        Mat4MulVecfl(G.obpose->obmat, G.scene->twmin);
 
349
                        Mat4MulVecfl(G.obpose->obmat, G.scene->twmax);
 
350
                }
 
351
        }
 
352
        else if(G.f & (G_FACESELECT + G_VERTEXPAINT + G_TEXTUREPAINT +G_WEIGHTPAINT)) {
 
353
                ;
 
354
        }
 
355
        else {
 
356
                
 
357
                /* we need the one selected object, if its not active */
 
358
                ob= OBACT;
 
359
                if(ob && !(ob->flag & SELECT)) ob= NULL;
 
360
                
 
361
                base= (G.scene->base.first);
 
362
                while(base) {
 
363
                        if TESTBASELIB(base) {
 
364
                                if(ob==NULL) ob= base->object;
 
365
                                calc_tw_center(base->object->obmat[3]);
 
366
                                totsel++;
 
367
                        }
 
368
                        base= base->next;
 
369
                }
 
370
                
 
371
                /* selection center */
 
372
                if(totsel) {
 
373
                        VecMulf(G.scene->twcent, 1.0f/(float)totsel);   // centroid!
 
374
                }
 
375
        }
 
376
        
 
377
        /* global, local or normal orientation? */
 
378
        if(ob && totsel) {
 
379
                
 
380
                switch(v3d->twmode) {
 
381
                case V3D_MANIP_GLOBAL:
 
382
                        break;
 
383
                        
 
384
                case V3D_MANIP_NORMAL:
 
385
                        if(G.obedit || G.obpose) {
 
386
                                if(normal[0]!=0.0 || normal[1]!=0.0 || normal[2]!=0.0) {
 
387
                                        float imat[3][3], mat[3][3];
 
388
                                        
 
389
                                        /* we need the transpose of the inverse for a normal... */
 
390
                                        Mat3CpyMat4(imat, ob->obmat);
 
391
                                        
 
392
                                        Mat3Inv(mat, imat);
 
393
                                        Mat3Transp(mat);
 
394
                                        Mat3MulVecfl(mat, normal);
 
395
                                        Mat3MulVecfl(mat, plane);
 
396
 
 
397
                                        Normalise(normal);
 
398
                                        if(0.0==Normalise(plane)) VECCOPY(plane, mat[1]);
 
399
                                        
 
400
                                        VECCOPY(mat[2], normal);
 
401
                                        Crossf(mat[0], normal, plane);
 
402
                                        Crossf(mat[1], mat[2], mat[0]);
 
403
                                        
 
404
                                        Mat4CpyMat3(v3d->twmat, mat);
 
405
                                        Mat4Ortho(v3d->twmat);
 
406
                                        
 
407
                                        break;
 
408
                                }
 
409
                        }
 
410
                        /* no break we define 'normal' as 'local' in Object mode */
 
411
                case V3D_MANIP_LOCAL:
 
412
                        if(totsel==1 || v3d->around==V3D_LOCAL || G.obedit || G.obpose) {
 
413
                                Mat4CpyMat4(v3d->twmat, ob->obmat);
 
414
                                Mat4Ortho(v3d->twmat);
 
415
                        }
 
416
                        break;
 
417
                }               
 
418
        }
 
419
           
 
420
        return totsel;
 
421
}
 
422
 
 
423
/* ******************** DRAWING STUFFIES *********** */
 
424
 
 
425
static float screen_aligned(float mat[][4])
 
426
{
 
427
        float vec[3], size;
 
428
        
 
429
        VECCOPY(vec, mat[0]);
 
430
        size= Normalise(vec);
 
431
        
 
432
        glTranslatef(mat[3][0], mat[3][1], mat[3][2]);
 
433
        
 
434
        /* sets view screen aligned */
 
435
        glRotatef( -360.0f*saacos(G.vd->viewquat[0])/(float)M_PI, G.vd->viewquat[1], G.vd->viewquat[2], G.vd->viewquat[3]);
 
436
        
 
437
        return size;
 
438
}
 
439
 
 
440
 
 
441
/* radring = radius of donut rings
 
442
   radhole = radius hole
 
443
   start = starting segment (based on nrings)
 
444
   end   = end segment
 
445
   nsides = amount of points in ring
 
446
   nrigns = amount of rings
 
447
*/
 
448
static void partial_donut(float radring, float radhole, int start, int end, int nsides, int nrings)
 
449
{
 
450
        float theta, phi, theta1;
 
451
        float cos_theta, sin_theta;
 
452
        float cos_theta1, sin_theta1;
 
453
        float ring_delta, side_delta;
 
454
        int i, j, docaps= 1;
 
455
        
 
456
        if(start==0 && end==nrings) docaps= 0;
 
457
        
 
458
        ring_delta= 2.0f*(float)M_PI/(float)nrings;
 
459
        side_delta= 2.0f*(float)M_PI/(float)nsides;
 
460
        
 
461
        theta= (float)M_PI+0.5f*ring_delta;
 
462
        cos_theta= (float)cos(theta);
 
463
        sin_theta= (float)sin(theta);
 
464
        
 
465
        for(i= nrings - 1; i >= 0; i--) {
 
466
                theta1= theta + ring_delta;
 
467
                cos_theta1= (float)cos(theta1);
 
468
                sin_theta1= (float)sin(theta1);
 
469
                
 
470
                if(docaps && i==start) {        // cap
 
471
                        glBegin(GL_POLYGON);
 
472
                        phi= 0.0;
 
473
                        for(j= nsides; j >= 0; j--) {
 
474
                                float cos_phi, sin_phi, dist;
 
475
                                
 
476
                                phi += side_delta;
 
477
                                cos_phi= (float)cos(phi);
 
478
                                sin_phi= (float)sin(phi);
 
479
                                dist= radhole + radring * cos_phi;
 
480
                                
 
481
                                glVertex3f(cos_theta1 * dist, -sin_theta1 * dist,  radring * sin_phi);
 
482
                        }
 
483
                        glEnd();
 
484
                }
 
485
                if(i>=start && i<=end) {
 
486
                        glBegin(GL_QUAD_STRIP);
 
487
                        phi= 0.0;
 
488
                        for(j= nsides; j >= 0; j--) {
 
489
                                float cos_phi, sin_phi, dist;
 
490
                                
 
491
                                phi += side_delta;
 
492
                                cos_phi= (float)cos(phi);
 
493
                                sin_phi= (float)sin(phi);
 
494
                                dist= radhole + radring * cos_phi;
 
495
                                
 
496
                                glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi);
 
497
                                glVertex3f(cos_theta * dist, -sin_theta * dist,  radring * sin_phi);
 
498
                        }
 
499
                        glEnd();
 
500
                }
 
501
                
 
502
                if(docaps && i==end) {  // cap
 
503
                        glBegin(GL_POLYGON);
 
504
                        phi= 0.0;
 
505
                        for(j= nsides; j >= 0; j--) {
 
506
                                float cos_phi, sin_phi, dist;
 
507
                                
 
508
                                phi -= side_delta;
 
509
                                cos_phi= (float)cos(phi);
 
510
                                sin_phi= (float)sin(phi);
 
511
                                dist= radhole + radring * cos_phi;
 
512
                                
 
513
                                glVertex3f(cos_theta * dist, -sin_theta * dist,  radring * sin_phi);
 
514
                        }
 
515
                        glEnd();
 
516
                }
 
517
                
 
518
                
 
519
                theta= theta1;
 
520
                cos_theta= cos_theta1;
 
521
                sin_theta= sin_theta1;
 
522
        }
 
523
}
 
524
 
 
525
/* three colors can be set;
 
526
   grey for ghosting
 
527
   moving: in transform theme color
 
528
   else the red/green/blue
 
529
*/
 
530
static void manipulator_setcolor(char axis, int colcode)
 
531
{
 
532
        float vec[4];
 
533
        char col[4];
 
534
        
 
535
        vec[3]= 0.7f; // alpha set on 0.5, can be glEnabled or not
 
536
        
 
537
        if(colcode==MAN_GHOST) {
 
538
                glColor4ub(0, 0, 0, 70);
 
539
        }
 
540
        else if(colcode==MAN_MOVECOL) {
 
541
                BIF_GetThemeColor3ubv(TH_TRANSFORM, col);
 
542
                glColor4ub(col[0], col[1], col[2], 128);
 
543
        }
 
544
        else {
 
545
                switch(axis) {
 
546
                case 'c':
 
547
                        BIF_GetThemeColor3ubv(TH_TRANSFORM, col);
 
548
                        if(G.vd->twmode == V3D_MANIP_LOCAL) {
 
549
                                col[0]= col[0]>200?255:col[0]+55;
 
550
                                col[1]= col[1]>200?255:col[1]+55;
 
551
                                col[2]= col[2]>200?255:col[2]+55;
 
552
                        }
 
553
                        else if(G.vd->twmode == V3D_MANIP_NORMAL) {
 
554
                                col[0]= col[0]<55?0:col[0]-55;
 
555
                                col[1]= col[1]<55?0:col[1]-55;
 
556
                                col[2]= col[2]<55?0:col[2]-55;
 
557
                        }
 
558
                        glColor4ub(col[0], col[1], col[2], 128);
 
559
                        break;
 
560
                case 'x':
 
561
                        glColor4ub(220, 0, 0, 128);
 
562
                        break;
 
563
                case 'y':
 
564
                        glColor4ub(0, 220, 0, 128);
 
565
                        break;
 
566
                case 'z':
 
567
                        glColor4ub(30, 30, 220, 128);
 
568
                        break;
 
569
                }
 
570
        }
 
571
}
 
572
 
 
573
/* viewmatrix should have been set OK, also no shademode! */
 
574
static void draw_manipulator_axes(int colcode, int flagx, int flagy, int flagz)
 
575
{
 
576
        
 
577
        /* axes */
 
578
        if(flagx) {
 
579
                manipulator_setcolor('x', colcode);
 
580
                if(flagx & MAN_SCALE_X) glLoadName(MAN_SCALE_X);
 
581
                else if(flagx & MAN_TRANS_X) glLoadName(MAN_TRANS_X);
 
582
                glBegin(GL_LINES);
 
583
                glVertex3f(0.2, 0.0, 0.0);
 
584
                glVertex3f(1.0, 0.0, 0.0);
 
585
                glEnd();
 
586
        }               
 
587
        if(flagy) {
 
588
                if(flagy & MAN_SCALE_Y) glLoadName(MAN_SCALE_Y);
 
589
                else if(flagy & MAN_TRANS_Y) glLoadName(MAN_TRANS_Y);
 
590
                manipulator_setcolor('y', colcode);
 
591
                glBegin(GL_LINES);
 
592
                glVertex3f(0.0, 0.2, 0.0);
 
593
                glVertex3f(0.0, 1.0, 0.0);
 
594
                glEnd();
 
595
        }               
 
596
        if(flagz) {
 
597
                if(flagz & MAN_SCALE_Z) glLoadName(MAN_SCALE_Z);
 
598
                else if(flagz & MAN_TRANS_Z) glLoadName(MAN_TRANS_Z);
 
599
                manipulator_setcolor('z', colcode);
 
600
                glBegin(GL_LINES);
 
601
                glVertex3f(0.0, 0.0, 0.2);
 
602
                glVertex3f(0.0, 0.0, 1.0);
 
603
                glEnd();
 
604
        }
 
605
}
 
606
 
 
607
/* only called while G.moving */
 
608
static void draw_manipulator_rotate_ghost(float mat[][4], int drawflags)
 
609
{
 
610
        GLUquadricObj *qobj= gluNewQuadric(); 
 
611
        float size, phi, startphi, vec[3], svec[3], matt[4][4], cross[3], tmat[3][3];
 
612
        int arcs= (G.rt!=2);
 
613
        
 
614
        glDisable(GL_DEPTH_TEST);
 
615
        gluQuadricDrawStyle(qobj, GLU_FILL); 
 
616
        
 
617
        glColor4ub(0,0,0,64);
 
618
        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
 
619
        glEnable(GL_BLEND);
 
620
                
 
621
        /* we need both [4][4] transforms, Trans.mat seems to be premul, not post for mat[][4] */
 
622
        Mat4CpyMat4(matt, mat); // to copy the parts outside of [3][3]
 
623
        Mat4MulMat34(matt, Trans.mat, mat);
 
624
 
 
625
        /* Screen aligned view rot circle */
 
626
        if(drawflags & MAN_ROT_V) {
 
627
                
 
628
                /* prepare for screen aligned draw */
 
629
                glPushMatrix();
 
630
                size= screen_aligned(mat);
 
631
        
 
632
                vec[0]= (float)(Trans.con.imval[0] - Trans.center2d[0]);
 
633
                vec[1]= (float)(Trans.con.imval[1] - Trans.center2d[1]);
 
634
                vec[2]= 0.0f;
 
635
                Normalise(vec);
 
636
                
 
637
                startphi= saacos( vec[1] );
 
638
                if(vec[0]<0.0) startphi= -startphi;
 
639
                
 
640
                phi= (float)fmod(180.0*Trans.val/M_PI, 360.0);
 
641
                if(phi > 180.0) phi-= 360.0;
 
642
                else if(phi<-180.0) phi+= 360.0;
 
643
                
 
644
                gluPartialDisk(qobj, 0.0, size, 32, 1, 180.0*startphi/M_PI, phi);
 
645
                
 
646
                glPopMatrix();
 
647
        }
 
648
        else if(arcs) {
 
649
                float imat[3][3], ivmat[3][3];
 
650
                /* try to get the start rotation */
 
651
                
 
652
                svec[0]= (float)(Trans.con.imval[0] - Trans.center2d[0]);
 
653
                svec[1]= (float)(Trans.con.imval[1] - Trans.center2d[1]);
 
654
                svec[2]= 0.0f;
 
655
                
 
656
                /* screen aligned vec transform back to manipulator space */
 
657
                Mat3CpyMat4(ivmat, G.vd->viewinv);
 
658
                Mat3CpyMat4(tmat, mat);
 
659
                Mat3Inv(imat, tmat);
 
660
                Mat3MulMat3(tmat, imat, ivmat);
 
661
                
 
662
                Mat3MulVecfl(tmat, svec);       // tmat is used further on
 
663
                Normalise(svec);
 
664
        }       
 
665
        
 
666
        mymultmatrix(mat);      // aligns with original widget
 
667
        
 
668
        /* Z disk */
 
669
        if(drawflags & MAN_ROT_Z) {
 
670
                if(arcs) {
 
671
                        /* correct for squeezed arc */
 
672
                        svec[0]+= tmat[2][0];
 
673
                        svec[1]+= tmat[2][1];
 
674
                        Normalise(svec);
 
675
                        
 
676
                        startphi= atan2(svec[0], svec[1]);
 
677
                }
 
678
                else startphi= 0.5*M_PI;
 
679
                
 
680
                VECCOPY(vec, mat[0]);   // use x axis to detect rotation
 
681
                Normalise(vec);
 
682
                Normalise(matt[0]);
 
683
                phi= saacos( Inpf(vec, matt[0]) );
 
684
                if(phi!=0.0) {
 
685
                        Crossf(cross, vec, matt[0]);    // results in z vector
 
686
                        if(Inpf(cross, mat[2]) > 0.0) phi= -phi;
 
687
                        gluPartialDisk(qobj, 0.0, 1.0, 32, 1, 180.0*startphi/M_PI, 180.0*(phi)/M_PI);
 
688
                }
 
689
        }
 
690
        /* X disk */
 
691
        if(drawflags & MAN_ROT_X) {
 
692
                if(arcs) {
 
693
                        /* correct for squeezed arc */
 
694
                        svec[1]+= tmat[2][1];
 
695
                        svec[2]+= tmat[2][2];
 
696
                        Normalise(svec);
 
697
                        
 
698
                        startphi= M_PI + atan2(svec[2], -svec[1]);
 
699
                }
 
700
                else startphi= 0.0;
 
701
                
 
702
                VECCOPY(vec, mat[1]);   // use y axis to detect rotation
 
703
                Normalise(vec);
 
704
                Normalise(matt[1]);
 
705
                phi= saacos( Inpf(vec, matt[1]) );
 
706
                if(phi!=0.0) {
 
707
                        Crossf(cross, vec, matt[1]);    // results in x vector
 
708
                        if(Inpf(cross, mat[0]) > 0.0) phi= -phi;
 
709
                        glRotatef(90.0, 0.0, 1.0, 0.0);
 
710
                        gluPartialDisk(qobj, 0.0, 1.0, 32, 1, 180.0*startphi/M_PI, 180.0*phi/M_PI);
 
711
                        glRotatef(-90.0, 0.0, 1.0, 0.0);
 
712
                }
 
713
        }       
 
714
        /* Y circle */
 
715
        if(drawflags & MAN_ROT_Y) {
 
716
                if(arcs) {
 
717
                        /* correct for squeezed arc */
 
718
                        svec[0]+= tmat[2][0];
 
719
                        svec[2]+= tmat[2][2];
 
720
                        Normalise(svec);
 
721
                        
 
722
                        startphi= M_PI + atan2(-svec[0], svec[2]);
 
723
                }
 
724
                else startphi= M_PI;
 
725
                
 
726
                VECCOPY(vec, mat[2]);   // use z axis to detect rotation
 
727
                Normalise(vec);
 
728
                Normalise(matt[2]);
 
729
                phi= saacos( Inpf(vec, matt[2]) );
 
730
                if(phi!=0.0) {
 
731
                        Crossf(cross, vec, matt[2]);    // results in y vector
 
732
                        if(Inpf(cross, mat[1]) > 0.0) phi= -phi;
 
733
                        glRotatef(-90.0, 1.0, 0.0, 0.0);
 
734
                        gluPartialDisk(qobj, 0.0, 1.0, 32, 1, 180.0*startphi/M_PI, 180.0*phi/M_PI);
 
735
                        glRotatef(90.0, 1.0, 0.0, 0.0);
 
736
                }
 
737
        }
 
738
        
 
739
        glDisable(GL_BLEND);
 
740
        myloadmatrix(G.vd->viewmat);
 
741
}
 
742
 
 
743
static void draw_manipulator_rotate(float mat[][4], int moving, int drawflags, int combo)
 
744
{
 
745
        GLUquadricObj *qobj= gluNewQuadric(); 
 
746
        double plane[4];
 
747
        float size, vec[3], unitmat[4][4];
 
748
        float cywid= 0.33f*0.01f*(float)U.tw_handlesize;        
 
749
        float cusize= cywid*0.65f;
 
750
        int arcs= (G.rt!=2);
 
751
        int colcode;
 
752
        
 
753
        if(moving) colcode= MAN_MOVECOL;
 
754
        else colcode= MAN_RGB;
 
755
        
 
756
        /* when called while moving in mixed mode, do not draw when... */
 
757
        if((drawflags & MAN_ROT_C)==0) return;
 
758
        
 
759
        /* Init stuff */
 
760
        glDisable(GL_DEPTH_TEST);
 
761
        Mat4One(unitmat);
 
762
        gluQuadricDrawStyle(qobj, GLU_FILL); 
 
763
        
 
764
        /* prepare for screen aligned draw */
 
765
        VECCOPY(vec, mat[0]);
 
766
        size= Normalise(vec);
 
767
        glPushMatrix();
 
768
        glTranslatef(mat[3][0], mat[3][1], mat[3][2]);
 
769
        
 
770
        if(arcs) {
 
771
                /* clipplane makes nice handles, calc here because of multmatrix but with translate! */
 
772
                VECCOPY(plane, G.vd->viewinv[2]);
 
773
                plane[3]= -0.02*size; // clip just a bit more
 
774
                glClipPlane(GL_CLIP_PLANE0, plane);
 
775
        }
 
776
        /* sets view screen aligned */
 
777
        glRotatef( -360.0f*saacos(G.vd->viewquat[0])/(float)M_PI, G.vd->viewquat[1], G.vd->viewquat[2], G.vd->viewquat[3]);
 
778
        
 
779
        /* Screen aligned help circle */
 
780
        if(arcs) {
 
781
                if((G.f & G_PICKSEL)==0) {
 
782
                        BIF_ThemeColorShade(TH_BACK, -30);
 
783
                        drawcircball(GL_LINE_LOOP, unitmat[3], size, unitmat);
 
784
                }
 
785
        }
 
786
        /* Screen aligned view rot circle */
 
787
        if(drawflags & MAN_ROT_V) {
 
788
                if(G.f & G_PICKSEL) glLoadName(MAN_ROT_V);
 
789
                BIF_ThemeColor(TH_TRANSFORM);
 
790
                drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f*size, unitmat);
 
791
                
 
792
                if(moving) {    
 
793
                        float vec[3];
 
794
                        vec[0]= (float)(Trans.imval[0] - Trans.center2d[0]);
 
795
                        vec[1]= (float)(Trans.imval[1] - Trans.center2d[1]);
 
796
                        vec[2]= 0.0f;
 
797
                        Normalise(vec);
 
798
                        VecMulf(vec, 1.2f*size);
 
799
                        glBegin(GL_LINES);
 
800
                        glVertex3f(0.0f, 0.0f, 0.0f);
 
801
                        glVertex3fv(vec);
 
802
                        glEnd();
 
803
                }
 
804
        }
 
805
        glPopMatrix();
 
806
        
 
807
        /* apply the transform delta */
 
808
        if(moving) {
 
809
                float matt[4][4];
 
810
                Mat4CpyMat4(matt, mat); // to copy the parts outside of [3][3]
 
811
                Mat4MulMat34(matt, Trans.mat, mat);
 
812
                mymultmatrix(matt);
 
813
                glFrontFace( is_mat4_flipped(matt)?GL_CW:GL_CCW);
 
814
        }
 
815
        else {
 
816
                glFrontFace( is_mat4_flipped(mat)?GL_CW:GL_CCW);
 
817
                mymultmatrix(mat);
 
818
        }
 
819
        
 
820
        /* axes */
 
821
        if(arcs==0) {
 
822
                if(!(G.f & G_PICKSEL)) {
 
823
                        if( (combo & V3D_MANIP_SCALE)==0) {
 
824
                                /* axis */
 
825
                                glBegin(GL_LINES);
 
826
                                if( (drawflags & MAN_ROT_X) || (moving && (drawflags & MAN_ROT_Z)) ) {
 
827
                                        manipulator_setcolor('x', colcode);
 
828
                                        glVertex3f(0.2, 0.0, 0.0);
 
829
                                        glVertex3f(1.0, 0.0, 0.0);
 
830
                                }               
 
831
                                if( (drawflags & MAN_ROT_Y) || (moving && (drawflags & MAN_ROT_X)) ) {
 
832
                                        manipulator_setcolor('y', colcode);
 
833
                                        glVertex3f(0.0, 0.2, 0.0);
 
834
                                        glVertex3f(0.0, 1.0, 0.0);
 
835
                                }               
 
836
                                if( (drawflags & MAN_ROT_Z) || (moving && (drawflags & MAN_ROT_Y)) ) {
 
837
                                        manipulator_setcolor('z', colcode);
 
838
                                        glVertex3f(0.0, 0.0, 0.2);
 
839
                                        glVertex3f(0.0, 0.0, 1.0);
 
840
                                }
 
841
                                glEnd();
 
842
                        }
 
843
                }
 
844
        }
 
845
        
 
846
        if(arcs==0 && moving) {
 
847
                
 
848
                if(arcs) glEnable(GL_CLIP_PLANE0);
 
849
 
 
850
                /* Z circle */
 
851
                if(drawflags & MAN_ROT_Z) {
 
852
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
 
853
                        manipulator_setcolor('z', colcode);
 
854
                        drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
 
855
                }
 
856
                /* X circle */
 
857
                if(drawflags & MAN_ROT_X) {
 
858
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
 
859
                        glRotatef(90.0, 0.0, 1.0, 0.0);
 
860
                        manipulator_setcolor('x', colcode);
 
861
                        drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
 
862
                        glRotatef(-90.0, 0.0, 1.0, 0.0);
 
863
                }       
 
864
                /* Y circle */
 
865
                if(drawflags & MAN_ROT_Y) {
 
866
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
 
867
                        glRotatef(-90.0, 1.0, 0.0, 0.0);
 
868
                        manipulator_setcolor('y', colcode);
 
869
                        drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
 
870
                        glRotatef(90.0, 1.0, 0.0, 0.0);
 
871
                }
 
872
                
 
873
                if(arcs) glDisable(GL_CLIP_PLANE0);
 
874
        }
 
875
        // donut arcs
 
876
        if(arcs) {
 
877
                glEnable(GL_CLIP_PLANE0);
 
878
                
 
879
                /* Z circle */
 
880
                if(drawflags & MAN_ROT_Z) {
 
881
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
 
882
                        manipulator_setcolor('z', colcode);
 
883
                        partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
 
884
                }
 
885
                /* X circle */
 
886
                if(drawflags & MAN_ROT_X) {
 
887
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
 
888
                        glRotatef(90.0, 0.0, 1.0, 0.0);
 
889
                        manipulator_setcolor('x', colcode);
 
890
                        partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
 
891
                        glRotatef(-90.0, 0.0, 1.0, 0.0);
 
892
                }       
 
893
                /* Y circle */
 
894
                if(drawflags & MAN_ROT_Y) {
 
895
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
 
896
                        glRotatef(-90.0, 1.0, 0.0, 0.0);
 
897
                        manipulator_setcolor('y', colcode);
 
898
                        partial_donut(cusize/4.0f, 1.0f, 0, 48, 8, 48);
 
899
                        glRotatef(90.0, 1.0, 0.0, 0.0);
 
900
                }
 
901
                
 
902
                glDisable(GL_CLIP_PLANE0);
 
903
        }
 
904
        
 
905
        if(arcs==0) {
 
906
                
 
907
                /* Z handle on X axis */
 
908
                if(drawflags & MAN_ROT_Z) {
 
909
                        glPushMatrix();
 
910
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
 
911
                        manipulator_setcolor('z', colcode);
 
912
 
 
913
                        partial_donut(0.7*cusize, 1.0, 31, 33, 8, 64);
 
914
 
 
915
                        glPopMatrix();
 
916
                }       
 
917
 
 
918
                /* Y handle on X axis */
 
919
                if(drawflags & MAN_ROT_Y) {
 
920
                        glPushMatrix();
 
921
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
 
922
                        manipulator_setcolor('y', colcode);
 
923
                        
 
924
                        glRotatef(90.0, 1.0, 0.0, 0.0);
 
925
                        glRotatef(90.0, 0.0, 0.0, 1.0);
 
926
                        partial_donut(0.7*cusize, 1.0, 31, 33, 8, 64);
 
927
                        
 
928
                        glPopMatrix();
 
929
                }
 
930
                
 
931
                /* X handle on Z axis */
 
932
                if(drawflags & MAN_ROT_X) {
 
933
                        glPushMatrix();
 
934
                        if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
 
935
                        manipulator_setcolor('x', colcode);
 
936
                        
 
937
                        glRotatef(-90.0, 0.0, 1.0, 0.0);
 
938
                        glRotatef(90.0, 0.0, 0.0, 1.0);
 
939
                        partial_donut(0.7*cusize, 1.0, 31, 33, 8, 64);
 
940
 
 
941
                        glPopMatrix();
 
942
                }
 
943
                
 
944
        }
 
945
        
 
946
        /* restore */
 
947
        myloadmatrix(G.vd->viewmat);
 
948
        gluDeleteQuadric(qobj);
 
949
        if(G.zbuf) glEnable(GL_DEPTH_TEST);             // shouldn't be global, tsk!
 
950
        
 
951
}
 
952
 
 
953
static void draw_manipulator_scale(float mat[][4], int moving, int drawflags, int combo, int colcode)
 
954
{
 
955
        float cywid= 0.25f*0.01f*(float)U.tw_handlesize;        
 
956
        float cusize= cywid*0.75f, dz;
 
957
        
 
958
        /* when called while moving in mixed mode, do not draw when... */
 
959
        if((drawflags & MAN_SCALE_C)==0) return;
 
960
        
 
961
        glDisable(GL_DEPTH_TEST);
 
962
        
 
963
        /* not in combo mode */
 
964
        if( (combo & (V3D_MANIP_TRANSLATE|V3D_MANIP_ROTATE))==0) {
 
965
                float size, unitmat[4][4];
 
966
                
 
967
                /* center circle, do not add to selection when shift is pressed (planar constraint)  */
 
968
                if( (G.f & G_PICKSEL) && (G.qual & LR_SHIFTKEY)==0) glLoadName(MAN_SCALE_C);
 
969
                
 
970
                manipulator_setcolor('c', colcode);
 
971
                glPushMatrix();
 
972
                size= screen_aligned(mat);
 
973
                Mat4One(unitmat);
 
974
                drawcircball(GL_LINE_LOOP, unitmat[3], 0.2*size, unitmat);
 
975
                glPopMatrix();
 
976
                
 
977
                dz= 1.0;
 
978
        }
 
979
        else dz= 1.0f-4.0f*cusize;
 
980
        
 
981
        if(moving) {
 
982
                float matt[4][4];
 
983
                
 
984
                Mat4CpyMat4(matt, mat); // to copy the parts outside of [3][3]
 
985
                Mat4MulMat34(matt, Trans.mat, mat);
 
986
                mymultmatrix(matt);
 
987
                glFrontFace( is_mat4_flipped(matt)?GL_CW:GL_CCW);
 
988
        }
 
989
        else {
 
990
                mymultmatrix(mat);
 
991
                glFrontFace( is_mat4_flipped(mat)?GL_CW:GL_CCW);
 
992
        }
 
993
        
 
994
        /* axis */
 
995
                
 
996
        /* in combo mode, this is always drawn as first type */
 
997
        draw_manipulator_axes(colcode, drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z);
 
998
        
 
999
        /* Z cube */
 
1000
        glTranslatef(0.0, 0.0, dz);
 
1001
        if(drawflags & MAN_SCALE_Z) {
 
1002
                if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_Z);
 
1003
                manipulator_setcolor('z', colcode);
 
1004
                drawsolidcube(cusize);
 
1005
        }       
 
1006
        /* X cube */
 
1007
        glTranslatef(dz, 0.0, -dz);
 
1008
        if(drawflags & MAN_SCALE_X) {
 
1009
                if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_X);
 
1010
                manipulator_setcolor('x', colcode);
 
1011
                drawsolidcube(cusize);
 
1012
        }       
 
1013
        /* Y cube */
 
1014
        glTranslatef(-dz, dz, 0.0);
 
1015
        if(drawflags & MAN_SCALE_Y) {
 
1016
                if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_Y);
 
1017
                manipulator_setcolor('y', colcode);
 
1018
                drawsolidcube(cusize);
 
1019
        }
 
1020
        
 
1021
        /* if shiftkey, center point as last, for selectbuffer order */
 
1022
        if(G.f & G_PICKSEL) {
 
1023
                if(G.qual & LR_SHIFTKEY) {
 
1024
                        glTranslatef(0.0, -dz, 0.0);
 
1025
                        glLoadName(MAN_SCALE_C);
 
1026
                        glBegin(GL_POINTS);
 
1027
                        glVertex3f(0.0, 0.0, 0.0);
 
1028
                        glEnd();
 
1029
                }
 
1030
        }
 
1031
        
 
1032
        /* restore */
 
1033
        myloadmatrix(G.vd->viewmat);
 
1034
        
 
1035
        if(G.zbuf) glEnable(GL_DEPTH_TEST);             // shouldn't be global, tsk!
 
1036
        glFrontFace(GL_CCW);
 
1037
}
 
1038
 
 
1039
 
 
1040
static void draw_cone(GLUquadricObj *qobj, float len, float width)
 
1041
{
 
1042
        glTranslatef(0.0, 0.0, -0.5f*len);
 
1043
        gluCylinder(qobj, width, 0.0, len, 8, 1);
 
1044
        gluQuadricOrientation(qobj, GLU_INSIDE);
 
1045
        gluDisk(qobj, 0.0, width, 8, 1); 
 
1046
        gluQuadricOrientation(qobj, GLU_OUTSIDE);
 
1047
        glTranslatef(0.0, 0.0, 0.5f*len);
 
1048
}
 
1049
 
 
1050
static void draw_cylinder(GLUquadricObj *qobj, float len, float width)
 
1051
{
 
1052
        
 
1053
        width*= 0.8f;   // just for beauty
 
1054
        
 
1055
        glTranslatef(0.0, 0.0, -0.5f*len);
 
1056
        gluCylinder(qobj, width, width, len, 8, 1);
 
1057
        gluQuadricOrientation(qobj, GLU_INSIDE);
 
1058
        gluDisk(qobj, 0.0, width, 8, 1); 
 
1059
        gluQuadricOrientation(qobj, GLU_OUTSIDE);
 
1060
        glTranslatef(0.0, 0.0, len);
 
1061
        gluDisk(qobj, 0.0, width, 8, 1); 
 
1062
        glTranslatef(0.0, 0.0, -0.5f*len);
 
1063
}
 
1064
 
 
1065
 
 
1066
static void draw_manipulator_translate(float mat[][4], int moving, int drawflags, int combo, int colcode)
 
1067
{
 
1068
        GLUquadricObj *qobj = gluNewQuadric(); 
 
1069
        float cylen= 0.01f*(float)U.tw_handlesize;
 
1070
        float cywid= 0.25f*cylen, dz, size;
 
1071
        float unitmat[4][4];
 
1072
        
 
1073
        /* when called while moving in mixed mode, do not draw when... */
 
1074
        if((drawflags & MAN_TRANS_C)==0) return;
 
1075
        
 
1076
        if(moving) glTranslatef(Trans.vec[0], Trans.vec[1], Trans.vec[2]);
 
1077
        glDisable(GL_DEPTH_TEST);
 
1078
        gluQuadricDrawStyle(qobj, GLU_FILL); 
 
1079
        
 
1080
        /* center circle, do not add to selection when shift is pressed (planar constraint) */
 
1081
        if( (G.f & G_PICKSEL) && (G.qual & LR_SHIFTKEY)==0) glLoadName(MAN_TRANS_C);
 
1082
        
 
1083
        manipulator_setcolor('c', colcode);
 
1084
        glPushMatrix();
 
1085
        size= screen_aligned(mat);
 
1086
        Mat4One(unitmat);
 
1087
        drawcircball(GL_LINE_LOOP, unitmat[3], 0.2*size, unitmat);
 
1088
        glPopMatrix();
 
1089
        
 
1090
        /* and now apply matrix, we move to local matrix drawing */
 
1091
        mymultmatrix(mat);
 
1092
        
 
1093
        /* axis */
 
1094
        glLoadName(-1);
 
1095
        
 
1096
        // translate drawn as last, only axis when no combo with scale, or for ghosting
 
1097
        if((combo & V3D_MANIP_SCALE)==0 || colcode==MAN_GHOST)
 
1098
                draw_manipulator_axes(colcode, drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z);
 
1099
 
 
1100
        
 
1101
        /* offset in combo mode, for rotate a bit more */
 
1102
        if(combo & (V3D_MANIP_ROTATE)) dz= 1.0f+2.0*cylen;
 
1103
        else if(combo & (V3D_MANIP_SCALE)) dz= 1.0f+0.5*cylen;
 
1104
        else dz= 1.0f;
 
1105
        
 
1106
        /* Z Cone */
 
1107
        glTranslatef(0.0, 0.0, dz);
 
1108
        if(drawflags & MAN_TRANS_Z) {
 
1109
                if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_Z);
 
1110
                manipulator_setcolor('z', colcode);
 
1111
                draw_cone(qobj, cylen, cywid);
 
1112
        }       
 
1113
        /* X Cone */
 
1114
        glTranslatef(dz, 0.0, -dz);
 
1115
        if(drawflags & MAN_TRANS_X) {
 
1116
                if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_X);
 
1117
                glRotatef(90.0, 0.0, 1.0, 0.0);
 
1118
                manipulator_setcolor('x', colcode);
 
1119
                draw_cone(qobj, cylen, cywid);
 
1120
                glRotatef(-90.0, 0.0, 1.0, 0.0);
 
1121
        }       
 
1122
        /* Y Cone */
 
1123
        glTranslatef(-dz, dz, 0.0);
 
1124
        if(drawflags & MAN_TRANS_Y) {
 
1125
                if(G.f & G_PICKSEL) glLoadName(MAN_TRANS_Y);
 
1126
                glRotatef(-90.0, 1.0, 0.0, 0.0);
 
1127
                manipulator_setcolor('y', colcode);
 
1128
                draw_cone(qobj, cylen, cywid);
 
1129
        }
 
1130
 
 
1131
        gluDeleteQuadric(qobj);
 
1132
        myloadmatrix(G.vd->viewmat);
 
1133
        
 
1134
        if(G.zbuf) glEnable(GL_DEPTH_TEST);             // shouldn't be global, tsk!
 
1135
        
 
1136
}
 
1137
 
 
1138
static void draw_manipulator_rotate_cyl(float mat[][4], int moving, int drawflags, int combo, int colcode)
 
1139
{
 
1140
        GLUquadricObj *qobj = gluNewQuadric(); 
 
1141
        float size;
 
1142
        float cylen= 0.01f*(float)U.tw_handlesize;
 
1143
        float cywid= 0.25f*cylen;
 
1144
        
 
1145
        /* when called while moving in mixed mode, do not draw when... */
 
1146
        if((drawflags & MAN_ROT_C)==0) return;
 
1147
        
 
1148
        /* prepare for screen aligned draw */
 
1149
        glPushMatrix();
 
1150
        size= screen_aligned(mat);
 
1151
        
 
1152
        glDisable(GL_DEPTH_TEST);
 
1153
        
 
1154
        /* Screen aligned view rot circle */
 
1155
        if(drawflags & MAN_ROT_V) {
 
1156
                float unitmat[4][4];
 
1157
                Mat4One(unitmat);
 
1158
                
 
1159
                if(G.f & G_PICKSEL) glLoadName(MAN_ROT_V);
 
1160
                BIF_ThemeColor(TH_TRANSFORM);
 
1161
                drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f*size, unitmat);
 
1162
                
 
1163
                if(moving) {
 
1164
                        float vec[3];
 
1165
                        vec[0]= (float)(Trans.imval[0] - Trans.center2d[0]);
 
1166
                        vec[1]= (float)(Trans.imval[1] - Trans.center2d[1]);
 
1167
                        vec[2]= 0.0f;
 
1168
                        Normalise(vec);
 
1169
                        VecMulf(vec, 1.2f*size);
 
1170
                        glBegin(GL_LINES);
 
1171
                        glVertex3f(0.0, 0.0, 0.0);
 
1172
                        glVertex3fv(vec);
 
1173
                        glEnd();
 
1174
                }
 
1175
        }
 
1176
        glPopMatrix();
 
1177
        
 
1178
        /* apply the transform delta */
 
1179
        if(moving) {
 
1180
                float matt[4][4];
 
1181
                Mat4CpyMat4(matt, mat); // to copy the parts outside of [3][3]
 
1182
                if (Trans.flag & T_USES_MANIPULATOR) {
 
1183
                        Mat4MulMat34(matt, Trans.mat, mat);
 
1184
                }
 
1185
                mymultmatrix(matt);
 
1186
        }
 
1187
        else {
 
1188
                mymultmatrix(mat);
 
1189
        }
 
1190
        
 
1191
        glFrontFace( is_mat4_flipped(mat)?GL_CW:GL_CCW);
 
1192
        
 
1193
        /* axis */
 
1194
        if( (G.f & G_PICKSEL)==0 ) {
 
1195
                
 
1196
                // only draw axis when combo didn't draw scale axes
 
1197
                if((combo & V3D_MANIP_SCALE)==0)
 
1198
                        draw_manipulator_axes(colcode, drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z);
 
1199
                
 
1200
                /* only has to be set when not in picking */
 
1201
                gluQuadricDrawStyle(qobj, GLU_FILL); 
 
1202
        }
 
1203
        
 
1204
        /* Z cyl */
 
1205
        glTranslatef(0.0, 0.0, 1.0);
 
1206
        if(drawflags & MAN_ROT_Z) {
 
1207
                if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
 
1208
                manipulator_setcolor('z', colcode);
 
1209
                draw_cylinder(qobj, cylen, cywid);
 
1210
        }       
 
1211
        /* X cyl */
 
1212
        glTranslatef(1.0, 0.0, -1.0);
 
1213
        if(drawflags & MAN_ROT_X) {
 
1214
                if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
 
1215
                glRotatef(90.0, 0.0, 1.0, 0.0);
 
1216
                manipulator_setcolor('x', colcode);
 
1217
                draw_cylinder(qobj, cylen, cywid);
 
1218
                glRotatef(-90.0, 0.0, 1.0, 0.0);
 
1219
        }       
 
1220
        /* Y cylinder */
 
1221
        glTranslatef(-1.0, 1.0, 0.0);
 
1222
        if(drawflags & MAN_ROT_Y) {
 
1223
                if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
 
1224
                glRotatef(-90.0, 1.0, 0.0, 0.0);
 
1225
                manipulator_setcolor('y', colcode);
 
1226
                draw_cylinder(qobj, cylen, cywid);
 
1227
        }
 
1228
        
 
1229
        /* restore */
 
1230
        
 
1231
        gluDeleteQuadric(qobj);
 
1232
        myloadmatrix(G.vd->viewmat);
 
1233
        
 
1234
        if(G.zbuf) glEnable(GL_DEPTH_TEST);             // shouldn't be global, tsk!
 
1235
        
 
1236
}
 
1237
 
 
1238
 
 
1239
/* ********************************************* */
 
1240
 
 
1241
static float get_manipulator_drawsize(ScrArea *sa)
 
1242
{
 
1243
        View3D *v3d= sa->spacedata.first;
 
1244
        float size, vec[3], len1, len2;
 
1245
        
 
1246
        /* size calculus, depending ortho/persp settings, like initgrabz() */
 
1247
        size= v3d->persmat[0][3]*v3d->twmat[3][0]+ v3d->persmat[1][3]*v3d->twmat[3][1]+ v3d->persmat[2][3]*v3d->twmat[3][2]+ v3d->persmat[3][3];
 
1248
        
 
1249
        VECCOPY(vec, v3d->persinv[0]);
 
1250
        len1= Normalise(vec);
 
1251
        VECCOPY(vec, v3d->persinv[1]);
 
1252
        len2= Normalise(vec);
 
1253
        
 
1254
        size*= (0.01f*(float)U.tw_size)*(len1>len2?len1:len2);
 
1255
 
 
1256
        /* correct for window size to make widgets appear fixed size */
 
1257
        if(sa->winx > sa->winy) size*= 1000.0f/(float)sa->winx;
 
1258
        else size*= 1000.0f/(float)sa->winy;
 
1259
 
 
1260
        return size;
 
1261
}
 
1262
 
 
1263
/* exported to transform_constraints.c */
 
1264
/* mat, vec = default orientation and location */
 
1265
/* type = transform type */
 
1266
/* axis = x, y, z, c */
 
1267
/* col: 0 = colored, 1 = moving, 2 = ghost */
 
1268
void draw_manipulator_ext(ScrArea *sa, int type, char axis, int col, float vec[3], float mat[][3])
 
1269
{
 
1270
        int drawflags= 0;
 
1271
        float mat4[4][4];
 
1272
        int colcode;
 
1273
        
 
1274
        Mat4CpyMat3(mat4, mat);
 
1275
        VECCOPY(mat4[3], vec);
 
1276
        
 
1277
        Mat4MulFloat3((float *)mat4, get_manipulator_drawsize(sa));
 
1278
        
 
1279
        glEnable(GL_BLEND);     // let's do it transparent by default
 
1280
        if(col==0) colcode= MAN_RGB;
 
1281
        else if(col==1) colcode= MAN_MOVECOL;
 
1282
        else colcode= MAN_GHOST;
 
1283
        
 
1284
        
 
1285
        if(type==TFM_ROTATION) {
 
1286
                if(axis=='x') drawflags= MAN_ROT_X;
 
1287
                else if(axis=='y') drawflags= MAN_ROT_Y;
 
1288
                else if(axis=='z') drawflags= MAN_ROT_Z;
 
1289
                else drawflags= MAN_ROT_C;
 
1290
                
 
1291
                draw_manipulator_rotate_cyl(mat4, col, drawflags, V3D_MANIP_ROTATE, colcode);
 
1292
        }       
 
1293
        else if(type==TFM_RESIZE) {
 
1294
                if(axis=='x') drawflags= MAN_SCALE_X;
 
1295
                else if(axis=='y') drawflags= MAN_SCALE_Y;
 
1296
                else if(axis=='z') drawflags= MAN_SCALE_Z;
 
1297
                else drawflags= MAN_SCALE_C;
 
1298
 
 
1299
                draw_manipulator_scale(mat4, col, drawflags, V3D_MANIP_SCALE, colcode);
 
1300
        }       
 
1301
        else {
 
1302
                if(axis=='x') drawflags= MAN_TRANS_X;
 
1303
                else if(axis=='y') drawflags= MAN_TRANS_Y;
 
1304
                else if(axis=='z') drawflags= MAN_TRANS_Z;
 
1305
                else drawflags= MAN_TRANS_C;
 
1306
 
 
1307
                draw_manipulator_translate(mat4, 0, drawflags, V3D_MANIP_TRANSLATE, colcode);
 
1308
        }       
 
1309
        
 
1310
 
 
1311
        glDisable(GL_BLEND);
 
1312
}
 
1313
 
 
1314
/* main call, does calc centers & orientation too */
 
1315
/* uses global G.moving */
 
1316
static int drawflags= 0xFFFF;           // only for the calls below, belongs in scene...?
 
1317
void BIF_draw_manipulator(ScrArea *sa)
 
1318
{
 
1319
        View3D *v3d= sa->spacedata.first;
 
1320
        int totsel;
 
1321
        
 
1322
        if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return;
 
1323
        if(G.moving && (G.moving & G_TRANSFORM_MANIP)==0) return;
 
1324
        
 
1325
        if(G.moving==0) {
 
1326
                v3d->twflag &= ~V3D_DRAW_MANIPULATOR;
 
1327
                
 
1328
                totsel= calc_manipulator_stats(sa);
 
1329
                if(totsel==0) return;
 
1330
                
 
1331
                v3d->twflag |= V3D_DRAW_MANIPULATOR;
 
1332
 
 
1333
                /* now we can define centre */
 
1334
                switch(v3d->around) {
 
1335
                case V3D_CENTRE:
 
1336
                case V3D_ACTIVE:
 
1337
                        v3d->twmat[3][0]= (G.scene->twmin[0] + G.scene->twmax[0])/2.0f;
 
1338
                        v3d->twmat[3][1]= (G.scene->twmin[1] + G.scene->twmax[1])/2.0f;
 
1339
                        v3d->twmat[3][2]= (G.scene->twmin[2] + G.scene->twmax[2])/2.0f;
 
1340
                        if(v3d->around==V3D_ACTIVE && G.obedit==NULL && G.obpose==NULL) {
 
1341
                                Object *ob= OBACT;
 
1342
                                if(ob) VECCOPY(v3d->twmat[3], ob->obmat[3]);
 
1343
                        }
 
1344
                        break;
 
1345
                case V3D_LOCAL:
 
1346
                case V3D_CENTROID:
 
1347
                        VECCOPY(v3d->twmat[3], G.scene->twcent);
 
1348
                        break;
 
1349
                case V3D_CURSOR:
 
1350
                        VECCOPY(v3d->twmat[3], give_cursor());
 
1351
                        break;
 
1352
                }
 
1353
                
 
1354
                Mat4MulFloat3((float *)v3d->twmat, get_manipulator_drawsize(sa));
 
1355
        }
 
1356
        
 
1357
        if(v3d->twflag & V3D_DRAW_MANIPULATOR) {
 
1358
                
 
1359
                if(v3d->twtype & V3D_MANIP_ROTATE) {
 
1360
                        /* rotate has special ghosting draw, for pie chart */
 
1361
                        if(G.moving) draw_manipulator_rotate_ghost(v3d->twmat, drawflags);
 
1362
                        
 
1363
                        if(G.moving) glEnable(GL_BLEND);
 
1364
                        
 
1365
                        if(G.rt==3) {
 
1366
                                if(G.moving) draw_manipulator_rotate_cyl(v3d->twmat, 1, drawflags, v3d->twtype, MAN_MOVECOL);
 
1367
                                else draw_manipulator_rotate_cyl(v3d->twmat, 0, drawflags, v3d->twtype, MAN_RGB);
 
1368
                        }
 
1369
                        else
 
1370
                                draw_manipulator_rotate(v3d->twmat, G.moving, drawflags, v3d->twtype);
 
1371
                        
 
1372
                        glDisable(GL_BLEND);
 
1373
                }
 
1374
                if(v3d->twtype & V3D_MANIP_SCALE) {
 
1375
                        if(G.moving) {
 
1376
                                glEnable(GL_BLEND);
 
1377
                                draw_manipulator_scale(v3d->twmat, 0, drawflags, v3d->twtype, MAN_GHOST);
 
1378
                                draw_manipulator_scale(v3d->twmat, 1, drawflags, v3d->twtype, MAN_MOVECOL);
 
1379
                                glDisable(GL_BLEND);
 
1380
                        }
 
1381
                        else draw_manipulator_scale(v3d->twmat, 0, drawflags, v3d->twtype, MAN_RGB);
 
1382
                }
 
1383
                if(v3d->twtype & V3D_MANIP_TRANSLATE) {
 
1384
                        if(G.moving) {
 
1385
                                glEnable(GL_BLEND);
 
1386
                                draw_manipulator_translate(v3d->twmat, 0, drawflags, v3d->twtype, MAN_GHOST);
 
1387
                                draw_manipulator_translate(v3d->twmat, 1, drawflags, v3d->twtype, MAN_MOVECOL);
 
1388
                                glDisable(GL_BLEND);
 
1389
                        }
 
1390
                        else draw_manipulator_translate(v3d->twmat, 0, drawflags, v3d->twtype, MAN_RGB);
 
1391
                }
 
1392
        }
 
1393
}
 
1394
 
 
1395
static int manipulator_selectbuf(ScrArea *sa, float hotspot)
 
1396
{
 
1397
        View3D *v3d= sa->spacedata.first;
 
1398
        rctf rect;
 
1399
        GLuint buffer[64];              // max 4 items per select, so large enuf
 
1400
        short hits, mval[2];
 
1401
        
 
1402
        G.f |= G_PICKSEL;
 
1403
        
 
1404
        getmouseco_areawin(mval);
 
1405
        rect.xmin= mval[0]-hotspot;
 
1406
        rect.xmax= mval[0]+hotspot;
 
1407
        rect.ymin= mval[1]-hotspot;
 
1408
        rect.ymax= mval[1]+hotspot;
 
1409
        
 
1410
        /* get rid of overlay button matrix */
 
1411
        persp(PERSP_VIEW);
 
1412
        
 
1413
        setwinmatrixview3d(&rect);
 
1414
        Mat4MulMat4(v3d->persmat, v3d->viewmat, sa->winmat);
 
1415
        
 
1416
        glSelectBuffer( 64, buffer);
 
1417
        glRenderMode(GL_SELECT);
 
1418
        glInitNames();  /* these two calls whatfor? It doesnt work otherwise */
 
1419
        glPushName(-2);
 
1420
        
 
1421
        /* do the drawing */
 
1422
        if(v3d->twtype & V3D_MANIP_ROTATE) {
 
1423
                if(G.rt==3) draw_manipulator_rotate_cyl(v3d->twmat, 0, MAN_ROT_C, v3d->twtype, MAN_RGB);
 
1424
                else draw_manipulator_rotate(v3d->twmat, 0, MAN_ROT_C, v3d->twtype);
 
1425
        }
 
1426
        if(v3d->twtype & V3D_MANIP_SCALE)
 
1427
                draw_manipulator_scale(v3d->twmat, 0, MAN_SCALE_C, v3d->twtype, MAN_RGB);
 
1428
        if(v3d->twtype & V3D_MANIP_TRANSLATE)
 
1429
                draw_manipulator_translate(v3d->twmat, 0, MAN_TRANS_C, v3d->twtype, MAN_RGB);
 
1430
        
 
1431
        glPopName();
 
1432
        hits= glRenderMode(GL_RENDER);
 
1433
        
 
1434
        G.f &= ~G_PICKSEL;
 
1435
        setwinmatrixview3d(0);
 
1436
        Mat4MulMat4(v3d->persmat, v3d->viewmat, sa->winmat);
 
1437
        
 
1438
        persp(PERSP_WIN);
 
1439
        
 
1440
        if(hits==1) return buffer[3];
 
1441
        else if(hits>1) {
 
1442
                GLuint mindep, minval;
 
1443
                int a;
 
1444
                
 
1445
                /* we compare the hits in buffer, but value centers highest */
 
1446
                mindep= buffer[1];
 
1447
                minval= buffer[3];
 
1448
 
 
1449
                for(a=1; a<hits; a++) {
 
1450
                        if(minval==MAN_TRANS_C || minval==MAN_SCALE_C) break;
 
1451
                        
 
1452
                        if(buffer[4*a + 3]==MAN_TRANS_C || buffer[4*a + 3]==MAN_SCALE_C || buffer[4*a + 1] < mindep) {
 
1453
                                mindep= buffer[4*a + 1];
 
1454
                                minval= buffer[4*a + 3];
 
1455
                        }
 
1456
                }
 
1457
                return minval;
 
1458
        }
 
1459
        return 0;
 
1460
}
 
1461
 
 
1462
/* return 0; nothing happened */
 
1463
int BIF_do_manipulator(ScrArea *sa)
 
1464
{
 
1465
        View3D *v3d= sa->spacedata.first;
 
1466
        int val;
 
1467
        
 
1468
        if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return 0;
 
1469
        if(!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return 0;
 
1470
        
 
1471
        // find the hotspots first test narrow hotspot
 
1472
        val= manipulator_selectbuf(sa, 0.5f*(float)U.tw_hotspot);
 
1473
        if(val) {
 
1474
                checkFirstTime(); // TEMPORARY, check this before doing any transform call.
 
1475
                // drawflags still global, for drawing call above
 
1476
                drawflags= manipulator_selectbuf(sa, 0.2f*(float)U.tw_hotspot);
 
1477
                if(drawflags==0) drawflags= val;
 
1478
                
 
1479
                switch(drawflags) {
 
1480
                case MAN_TRANS_C:
 
1481
                        ManipulatorTransform(TFM_TRANSLATION);
 
1482
                        break;
 
1483
                case MAN_TRANS_X:
 
1484
                        if(G.qual & LR_SHIFTKEY) {
 
1485
                                drawflags= MAN_TRANS_Y|MAN_TRANS_Z;
 
1486
                                BIF_setDualAxisConstraint(v3d->twmat[1], v3d->twmat[2], " Y+Z");
 
1487
                        }
 
1488
                        else
 
1489
                                BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
 
1490
                        ManipulatorTransform(TFM_TRANSLATION);
 
1491
                        break;
 
1492
                case MAN_TRANS_Y:
 
1493
                        if(G.qual & LR_SHIFTKEY) {
 
1494
                                drawflags= MAN_TRANS_X|MAN_TRANS_Z;
 
1495
                                BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[2], " X+Z");
 
1496
                        }
 
1497
                        else
 
1498
                                BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
 
1499
                        ManipulatorTransform(TFM_TRANSLATION);
 
1500
                        break;
 
1501
                case MAN_TRANS_Z:
 
1502
                        if(G.qual & LR_SHIFTKEY) {
 
1503
                                drawflags= MAN_TRANS_X|MAN_TRANS_Y;
 
1504
                                BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[1], " X+Y");
 
1505
                        }
 
1506
                        else
 
1507
                                BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
 
1508
                        ManipulatorTransform(TFM_TRANSLATION);
 
1509
                        break;
 
1510
                        
 
1511
                case MAN_SCALE_C:
 
1512
                        ManipulatorTransform(TFM_RESIZE);
 
1513
                        break;
 
1514
                case MAN_SCALE_X:
 
1515
                        if(G.qual & LR_SHIFTKEY) {
 
1516
                                drawflags= MAN_SCALE_Y|MAN_SCALE_Z;
 
1517
                                BIF_setDualAxisConstraint(v3d->twmat[1], v3d->twmat[2], " Y+Z");
 
1518
                        }
 
1519
                        else
 
1520
                                BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
 
1521
                        ManipulatorTransform(TFM_RESIZE);
 
1522
                        break;
 
1523
                case MAN_SCALE_Y:
 
1524
                        if(G.qual & LR_SHIFTKEY) {
 
1525
                                drawflags= MAN_SCALE_X|MAN_SCALE_Z;
 
1526
                                BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[2], " X+Z");
 
1527
                        }
 
1528
                        else
 
1529
                                BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
 
1530
                        ManipulatorTransform(TFM_RESIZE);
 
1531
                        break;
 
1532
                case MAN_SCALE_Z:
 
1533
                        if(G.qual & LR_SHIFTKEY) {
 
1534
                                drawflags= MAN_SCALE_X|MAN_SCALE_Y;
 
1535
                                BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[1], " X+Y");
 
1536
                        }
 
1537
                        else
 
1538
                                BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
 
1539
                        ManipulatorTransform(TFM_RESIZE);
 
1540
                        break;
 
1541
                
 
1542
                case MAN_ROT_X:
 
1543
                        BIF_setSingleAxisConstraint(v3d->twmat[0], " X");
 
1544
                        ManipulatorTransform(TFM_ROTATION);
 
1545
                        break;
 
1546
                case MAN_ROT_Y:
 
1547
                        BIF_setSingleAxisConstraint(v3d->twmat[1], " Y");
 
1548
                        ManipulatorTransform(TFM_ROTATION);
 
1549
                        break;
 
1550
                case MAN_ROT_Z:
 
1551
                        BIF_setSingleAxisConstraint(v3d->twmat[2], " Z");
 
1552
                        ManipulatorTransform(TFM_ROTATION);
 
1553
                        break;
 
1554
                case MAN_ROT_T:
 
1555
                        ManipulatorTransform(TFM_TRACKBALL);
 
1556
                        break;                  
 
1557
                case MAN_ROT_V:
 
1558
                        ManipulatorTransform(TFM_ROTATION);
 
1559
                        break;
 
1560
                }
 
1561
                
 
1562
        }
 
1563
        /* after transform, restore drawflags */
 
1564
        drawflags= 0xFFFF;
 
1565
        
 
1566
        return val;
 
1567
}
 
1568
 
 
1569