~ubuntu-branches/ubuntu/intrepid/blender/intrepid-updates

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-08-08 02:45:40 UTC
  • mfrom: (12.1.14 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080808024540-kkjp7ekfivzhuw3l
Tags: 2.46+dfsg-4
* Fix python syntax warning in import_dxf.py, which led to nasty output
  in installation/upgrade logs during byte-compilation, using a patch
  provided by the script author (Closes: #492280):
   - debian/patches/45_fix_python_syntax_warning

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**
2
 
 * $Id: transform.c,v 1.140 2006/07/08 14:24:57 khughes Exp $
 
2
 * $Id: transform.c 14868 2008-05-16 13:13:20Z theeth $
3
3
 *
4
 
 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
 
4
 * ***** BEGIN GPL LICENSE BLOCK *****
5
5
 *
6
6
 * This program is free software; you can redistribute it and/or
7
7
 * modify it under the terms of the GNU General Public License
8
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.
 
9
 * of the License, or (at your option) any later version.
13
10
 *
14
11
 * This program is distributed in the hope that it will be useful,
15
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
24
 *
28
25
 * Contributor(s): none yet.
29
26
 *
30
 
 * ***** END GPL/BL DUAL LICENSE BLOCK *****
 
27
 * ***** END GPL LICENSE BLOCK *****
31
28
 */
32
29
 
33
30
#include <stdlib.h>
48
45
#include "MEM_guardedalloc.h"
49
46
 
50
47
#include "DNA_armature_types.h"
 
48
#include "DNA_action_types.h"  /* for some special action-editor settings */
 
49
#include "DNA_constraint_types.h"
51
50
#include "DNA_ipo_types.h"              /* some silly ipo flag  */
52
51
#include "DNA_listBase.h"
53
52
#include "DNA_meshdata_types.h"
55
54
#include "DNA_object_types.h"
56
55
#include "DNA_scene_types.h"            /* PET modes                    */
57
56
#include "DNA_screen_types.h"   /* area dimensions              */
58
 
#include "DNA_scene_types.h"
59
 
#include "DNA_screen_types.h"
60
57
#include "DNA_texture_types.h"
61
58
#include "DNA_userdef_types.h"
62
59
#include "DNA_view3d_types.h"
64
61
 
65
62
#include "BIF_editview.h"               /* arrows_move_cursor   */
66
63
#include "BIF_gl.h"
 
64
#include "BIF_glutil.h"
67
65
#include "BIF_mywindow.h"
68
66
#include "BIF_resources.h"
69
67
#include "BIF_screen.h"
73
71
#include "BIF_toolbox.h"                        /* notice                               */
74
72
#include "BIF_editmesh.h"
75
73
#include "BIF_editsima.h"
 
74
#include "BIF_editparticle.h"
76
75
#include "BIF_drawimage.h"              /* uvco_to_areaco_noclip */
 
76
#include "BIF_editaction.h" 
77
77
 
 
78
#include "BKE_action.h" /* get_action_frame */
 
79
#include "BKE_bad_level_calls.h"/* popmenu and error    */
 
80
#include "BKE_bmesh.h"
 
81
#include "BKE_constraint.h"
78
82
#include "BKE_global.h"
 
83
#include "BKE_particle.h"
 
84
#include "BKE_pointcache.h"
79
85
#include "BKE_utildefines.h"
80
 
#include "BKE_bad_level_calls.h"/* popmenu and error    */
81
 
 
82
 
#include "BDR_editobject.h"             /* compatible_eul               */
83
 
 
 
86
 
 
87
#include "BSE_drawipo.h"
 
88
#include "BSE_editnla_types.h"  /* for NLAWIDTH */
 
89
#include "BSE_editaction_types.h"
 
90
#include "BSE_time.h"
84
91
#include "BSE_view.h"
85
92
 
86
93
#include "BLI_arithb.h"
99
106
TransInfo Trans = {TFM_INIT, 0};        // enforce init on first usage
100
107
 
101
108
/******************************** Helper functions ************************************/
 
109
 
 
110
/* GLOBAL Wrapper Fonctions */
 
111
 
 
112
void BIF_drawSnap()
 
113
{
 
114
        drawSnapping(&Trans);
 
115
}
 
116
 
102
117
/* ************************** Dashed help line **************************** */
103
118
 
104
119
 
135
150
                setlinestyle(0);
136
151
                
137
152
                persp(PERSP_VIEW);
138
 
                glFlush(); // flush display for frontbuffer
 
153
                bglFlush(); // flush display for frontbuffer
139
154
                glDrawBuffer(GL_BACK);
140
155
        }
141
156
}
 
157
 
 
158
 
 
159
  
142
160
/* ************************** INPUT FROM MOUSE *************************** */
143
161
 
144
162
float InputScaleRatio(TransInfo *t, short mval[2]) {
162
180
}
163
181
 
164
182
float InputHorizontalRatio(TransInfo *t, short mval[2]) {
165
 
        int y, pad;
 
183
        float x, pad;
166
184
 
167
185
        pad = curarea->winx / 10;
168
186
 
169
187
        if (t->flag & T_SHIFT_MOD) {
170
188
                /* deal with Shift key by adding motion / 10 to motion before shift press */
171
 
                y = t->shiftmval[0] + (mval[0] - t->shiftmval[0]) / 10;
 
189
                x = t->shiftmval[0] + (float)(mval[0] - t->shiftmval[0]) / 10.0f;
172
190
        }
173
191
        else {
174
 
                y = mval[0];
 
192
                x = mval[0];
175
193
        }
176
 
        return (float)(y - pad) / (float)(curarea->winx - 2 * pad);
 
194
        return (x - pad) / (curarea->winx - 2 * pad);
177
195
}
178
196
 
179
197
float InputHorizontalAbsolute(TransInfo *t, short mval[2]) {
180
198
        float vec[3];
181
199
        if(t->flag & T_SHIFT_MOD) {
182
 
                short dx = t->shiftmval[0] + (mval[0] - t->shiftmval[0]) / 10 - t->imval[0];
183
 
                short dy = t->shiftmval[1] + (mval[1] - t->shiftmval[1]) / 10 - t->imval[1];
184
 
                convertViewVec(t, t->vec, dx, dy);
 
200
                float dvec[3];
 
201
                /* calculate the main translation and the precise one separate */
 
202
                convertViewVec(t, dvec, (short)(mval[0] - t->shiftmval[0]), (short)(mval[1] - t->shiftmval[1]));
 
203
                VecMulf(dvec, 0.1f);
 
204
                convertViewVec(t, t->vec, (short)(t->shiftmval[0] - t->imval[0]), (short)(t->shiftmval[1] - t->imval[1]));
 
205
                VecAddf(t->vec, t->vec, dvec);
185
206
        }
186
207
        else {
187
208
                convertViewVec(t, t->vec, (short)(mval[0] - t->imval[0]), (short)(mval[1] - t->imval[1]));
190
211
        return Inpf(t->viewinv[0], vec) * 2.0f;
191
212
}
192
213
 
 
214
float InputVerticalRatio(TransInfo *t, short mval[2]) {
 
215
        float y, pad;
 
216
 
 
217
        pad = curarea->winy / 10;
 
218
 
 
219
        if (t->flag & T_SHIFT_MOD) {
 
220
                /* deal with Shift key by adding motion / 10 to motion before shift press */
 
221
                y = t->shiftmval[1] + (float)(mval[1] - t->shiftmval[1]) / 10.0f;
 
222
        }
 
223
        else {
 
224
                y = mval[0];
 
225
        }
 
226
        return (y - pad) / (curarea->winy - 2 * pad);
 
227
}
 
228
 
193
229
float InputVerticalAbsolute(TransInfo *t, short mval[2]) {
194
230
        float vec[3];
195
231
        if(t->flag & T_SHIFT_MOD) {
196
 
                short dx = t->shiftmval[0] + (mval[0] - t->shiftmval[0]) / 10 - t->imval[0];
197
 
                short dy = t->shiftmval[1] + (mval[1] - t->shiftmval[1]) / 10 - t->imval[1];
198
 
                convertViewVec(t, t->vec, dx, dy);
 
232
                float dvec[3];
 
233
                /* calculate the main translation and the precise one separate */
 
234
                convertViewVec(t, dvec, (short)(mval[0] - t->shiftmval[0]), (short)(mval[1] - t->shiftmval[1]));
 
235
                VecMulf(dvec, 0.1f);
 
236
                convertViewVec(t, t->vec, (short)(t->shiftmval[0] - t->imval[0]), (short)(t->shiftmval[1] - t->imval[1]));
 
237
                VecAddf(t->vec, t->vec, dvec);
199
238
        }
200
239
        else {
201
240
                convertViewVec(t, t->vec, (short)(mval[0] - t->imval[0]), (short)(mval[1] - t->imval[1]));
204
243
        return Inpf(t->viewinv[1], vec) * 2.0f;
205
244
}
206
245
 
 
246
float InputDeltaAngle(TransInfo *t, short mval[2])
 
247
{
 
248
        double dx2 = mval[0] - t->center2d[0];
 
249
        double dy2 = mval[1] - t->center2d[1];
 
250
        double B = sqrt(dx2*dx2+dy2*dy2);
 
251
 
 
252
        double dx1 = t->imval[0] - t->center2d[0];
 
253
        double dy1 = t->imval[1] - t->center2d[1];
 
254
        double A = sqrt(dx1*dx1+dy1*dy1);
 
255
 
 
256
        double dx3 = mval[0] - t->imval[0];
 
257
        double dy3 = mval[1] - t->imval[1];
 
258
 
 
259
        /* use doubles here, to make sure a "1.0" (no rotation) doesnt become 9.999999e-01, which gives 0.02 for acos */
 
260
        double deler = ((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3))
 
261
                / (2.0 * (A*B?A*B:1.0));
 
262
        /* (A*B?A*B:1.0f) this takes care of potential divide by zero errors */
 
263
 
 
264
        float dphi;
 
265
        
 
266
        dphi = saacos((float)deler);
 
267
        if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
 
268
 
 
269
        /* If the angle is zero, because of lack of precision close to the 1.0 value in acos
 
270
         * approximate the angle with the oposite side of the normalized triangle
 
271
         * This is a good approximation here since the smallest acos value seems to be around
 
272
         * 0.02 degree and lower values don't even have a 0.01% error compared to the approximation
 
273
         * */   
 
274
        if (dphi == 0)
 
275
        {
 
276
                double dx, dy;
 
277
                
 
278
                dx2 /= A;
 
279
                dy2 /= A;
 
280
                
 
281
                dx1 /= B;
 
282
                dy1 /= B;
 
283
                
 
284
                dx = dx1 - dx2;
 
285
                dy = dy1 - dy2;
 
286
                
 
287
                dphi = sqrt(dx*dx + dy*dy);
 
288
                if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
 
289
        }
 
290
        
 
291
        if(t->flag & T_SHIFT_MOD) dphi = dphi/30.0f;
 
292
        
 
293
        /* if no delta angle, don't update initial position */
 
294
        if (dphi != 0)
 
295
        {
 
296
                t->imval[0] = mval[0];
 
297
                t->imval[1] = mval[1];
 
298
        }
 
299
        
 
300
        return dphi;
 
301
}
 
302
 
207
303
/* ************************** SPACE DEPENDANT CODE **************************** */
208
304
 
209
305
void setTransformViewMatrices(TransInfo *t)
220
316
                Mat4One(t->viewinv);
221
317
                Mat4One(t->persmat);
222
318
                Mat4One(t->persinv);
223
 
                t->persp = 0; // ortho
 
319
                t->persp = V3D_ORTHO;
224
320
        }
225
321
        
226
322
        calculateCenter2D(t);
234
330
        }
235
331
        else if(t->spacetype==SPACE_IMAGE) {
236
332
                float divx, divy, aspx, aspy;
237
 
 
 
333
                
238
334
                transform_aspect_ratio_tface_uv(&aspx, &aspy);
239
 
 
 
335
                
240
336
                divx= G.v2d->mask.xmax-G.v2d->mask.xmin;
241
337
                divy= G.v2d->mask.ymax-G.v2d->mask.ymin;
242
 
 
 
338
                
243
339
                vec[0]= aspx*(G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/divx;
244
340
                vec[1]= aspy*(G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/divy;
245
341
                vec[2]= 0.0f;
246
342
        }
 
343
        else if(t->spacetype==SPACE_IPO) {
 
344
                float divx, divy;
 
345
                
 
346
                divx= G.v2d->mask.xmax-G.v2d->mask.xmin;
 
347
                divy= G.v2d->mask.ymax-G.v2d->mask.ymin;
 
348
                
 
349
                vec[0]= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx) / (divx);
 
350
                vec[1]= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy) / (divy);
 
351
                vec[2]= 0.0f;
 
352
        }
247
353
}
248
354
 
249
355
void projectIntView(TransInfo *t, float *vec, int *adr)
252
358
                project_int(vec, adr);
253
359
        else if(t->spacetype==SPACE_IMAGE) {
254
360
                float aspx, aspy, v[2];
255
 
 
 
361
                
256
362
                transform_aspect_ratio_tface_uv(&aspx, &aspy);
257
363
                v[0]= vec[0]/aspx;
258
364
                v[1]= vec[1]/aspy;
259
 
 
 
365
                
260
366
                uvco_to_areaco_noclip(v, adr);
261
367
        }
 
368
        else if(t->spacetype==SPACE_IPO) {
 
369
                short out[2] = {0.0f, 0.0f};
 
370
                
 
371
                ipoco_to_areaco(G.v2d, vec, out);
 
372
                adr[0]= out[0];
 
373
                adr[1]= out[1];
 
374
        }
262
375
}
263
376
 
264
377
void projectFloatView(TransInfo *t, float *vec, float *adr)
267
380
                project_float(vec, adr);
268
381
        else if(t->spacetype==SPACE_IMAGE) {
269
382
                int a[2];
270
 
 
 
383
                
 
384
                projectIntView(t, vec, a);
 
385
                adr[0]= a[0];
 
386
                adr[1]= a[1];
 
387
        }
 
388
        else if(t->spacetype==SPACE_IPO) {
 
389
                int a[2];
 
390
                
271
391
                projectIntView(t, vec, a);
272
392
                adr[0]= a[0];
273
393
                adr[1]= a[1];
322
442
 
323
443
static void viewRedrawForce(TransInfo *t)
324
444
{
325
 
        if(t->spacetype==SPACE_VIEW3D)
 
445
        if (t->spacetype == SPACE_VIEW3D)
326
446
                force_draw(0);
327
 
        else if(t->spacetype==SPACE_IMAGE) {
328
 
                if(G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0);
 
447
        else if (t->spacetype==SPACE_IMAGE) {
 
448
                if (G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0);
329
449
                else force_draw(0);
330
450
        }
 
451
        else if (t->spacetype == SPACE_ACTION) {
 
452
                if (G.saction->lock) {
 
453
                        short context;
 
454
                        
 
455
                        /* we ignore the pointer this function returns (not needed) */
 
456
                        get_action_context(&context);
 
457
                        
 
458
                        if (context == ACTCONT_ACTION)
 
459
                                force_draw_plus(SPACE_VIEW3D, 0);
 
460
                        else if (context == ACTCONT_SHAPEKEY) 
 
461
                                force_draw_all(0);
 
462
                        else
 
463
                                force_draw(0);
 
464
                }
 
465
                else {
 
466
                        force_draw(0);
 
467
                }
 
468
        }
 
469
        else if (t->spacetype == SPACE_NLA) {
 
470
                if (G.snla->lock)
 
471
                        force_draw_all(0);
 
472
                else
 
473
                        force_draw(0);
 
474
        }
 
475
        else if (t->spacetype == SPACE_IPO) {
 
476
                /* update realtime */
 
477
                if (G.sipo->lock) {
 
478
                        if (G.sipo->blocktype==ID_MA || G.sipo->blocktype==ID_TE)
 
479
                                force_draw_plus(SPACE_BUTS, 0);
 
480
                        else if (G.sipo->blocktype==ID_CA)
 
481
                                force_draw_plus(SPACE_VIEW3D, 0);
 
482
                        else if (G.sipo->blocktype==ID_KE)
 
483
                                force_draw_plus(SPACE_VIEW3D, 0);
 
484
                        else if (G.sipo->blocktype==ID_PO)
 
485
                                force_draw_plus(SPACE_VIEW3D, 0);
 
486
                        else if (G.sipo->blocktype==ID_OB) 
 
487
                                force_draw_plus(SPACE_VIEW3D, 0);
 
488
                        else if (G.sipo->blocktype==ID_SEQ) 
 
489
                                force_draw_plus(SPACE_SEQ, 0);
 
490
                        else 
 
491
                                force_draw(0);
 
492
                }
 
493
                else {
 
494
                        force_draw(0);
 
495
                }
 
496
        }
331
497
}
332
498
 
333
499
static void viewRedrawPost(TransInfo *t)
340
506
                allqueue(REDRAWIMAGE, 0);
341
507
                allqueue(REDRAWVIEW3D, 0);
342
508
        }
 
509
        else if(ELEM3(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_IPO)) {
 
510
                allqueue(REDRAWVIEW3D, 0);
 
511
                allqueue(REDRAWACTION, 0);
 
512
                allqueue(REDRAWNLA, 0);
 
513
                allqueue(REDRAWIPO, 0);
 
514
                allqueue(REDRAWTIME, 0);
 
515
                allqueue(REDRAWBUTSOBJECT, 0);
 
516
        }
343
517
 
344
518
        scrarea_queue_headredraw(curarea);
345
519
}
348
522
 
349
523
void BIF_selectOrientation() {
350
524
        short val;
351
 
        val= pupmenu("Orientation%t|Global|Local|Normal|View");
352
 
        if(val>0) {
353
 
                if(val==1) G.vd->twmode= V3D_MANIP_GLOBAL;
354
 
                else if(val==2) G.vd->twmode= V3D_MANIP_LOCAL;
355
 
                else if(val==3) G.vd->twmode= V3D_MANIP_NORMAL;
356
 
                else if(val==4) G.vd->twmode= V3D_MANIP_VIEW;
 
525
        char *str_menu = BIF_menustringTransformOrientation("Orientation");
 
526
        val= pupmenu(str_menu);
 
527
        MEM_freeN(str_menu);
 
528
        
 
529
        if(val >= 0) {
 
530
                G.vd->twmode = val;
357
531
        }
358
532
}
359
533
 
458
632
                        return "Trackball";
459
633
                case TFM_PUSHPULL:
460
634
                        return "Push/Pull";
 
635
                case TFM_BEVEL:
 
636
                        return "Bevel";
 
637
                case TFM_BWEIGHT:
 
638
                        return "Bevel Weight";
461
639
                case TFM_CREASE:
462
640
                        return "Crease";
463
641
                case TFM_BONESIZE:
464
642
                        return "Bone Width";
465
643
                case TFM_BONE_ENVELOPE:
466
644
                        return "Bone Envelope";
 
645
                case TFM_TIME_TRANSLATE:
 
646
                        return "Translate Anim. Data";
 
647
                case TFM_TIME_SCALE:
 
648
                        return "Scale Anim. Data";
 
649
                case TFM_TIME_SLIDE:
 
650
                        return "Time Slide";
 
651
                case TFM_BAKE_TIME:
 
652
                        return "Key Time";
 
653
                case TFM_MIRROR:
 
654
                        return "Mirror";
467
655
        }
468
656
        return "Transform";
469
657
}
488
676
                        Trans.flag |= T_SHIFT_MOD;
489
677
                        Trans.redraw = 1;
490
678
                        break;
491
 
 
 
679
                        
492
680
                case SPACEKEY:
493
681
                        if ((Trans.spacetype==SPACE_VIEW3D) && (G.qual & LR_ALTKEY)) {
494
682
                                short mval[2];
495
 
 
 
683
                                
496
684
                                getmouseco_sc(mval);
497
685
                                BIF_selectOrientation();
498
686
                                calc_manipulator_stats(curarea);
503
691
                                Trans.state = TRANS_CONFIRM;
504
692
                        }
505
693
                        break;
506
 
 
 
694
                        
507
695
                        
508
696
                case MIDDLEMOUSE:
509
697
                        if ((Trans.flag & T_NO_CONSTRAINT)==0) {
513
701
                                                setLocalConstraint(&Trans, (CON_AXIS2), "along local Z");
514
702
                                        else if (Trans.mode==TFM_ROTATION) {
515
703
                                                restoreTransObjects(&Trans);
516
 
                                                initTransModeFlags(&Trans, TFM_TRACKBALL);
517
704
                                                initTrackball(&Trans);
518
705
                                        }
519
706
                                }
550
737
                        /* only switch when... */
551
738
                        if( ELEM3(Trans.mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) { 
552
739
                                restoreTransObjects(&Trans);
553
 
                                initTransModeFlags(&Trans, TFM_TRANSLATION);
554
740
                                initTranslation(&Trans);
555
741
                                Trans.redraw = 1;
556
742
                        }
559
745
                        /* only switch when... */
560
746
                        if( ELEM3(Trans.mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL) ) { 
561
747
                                restoreTransObjects(&Trans);
562
 
                                initTransModeFlags(&Trans, TFM_RESIZE);
563
748
                                initResize(&Trans);
564
749
                                Trans.redraw = 1;
565
750
                        }
570
755
                                
571
756
                                if (Trans.mode == TFM_ROTATION) {
572
757
                                        restoreTransObjects(&Trans);
573
 
                                        initTransModeFlags(&Trans, TFM_TRACKBALL);
574
758
                                        initTrackball(&Trans);
575
759
                                }
576
760
                                else {
577
761
                                        restoreTransObjects(&Trans);
578
 
                                        initTransModeFlags(&Trans, TFM_ROTATION);
579
762
                                        initRotation(&Trans);
580
763
                                }
581
764
                                Trans.redraw = 1;
596
779
                case XKEY:
597
780
                        if ((Trans.flag & T_NO_CONSTRAINT)==0) {
598
781
                                if (cmode == 'X') {
599
 
                                        if (Trans.con.mode & CON_USER) {
 
782
                                        if (Trans.flag & T_2D_EDIT) {
600
783
                                                stopConstraint(&Trans);
601
784
                                        }
602
785
                                        else {
 
786
                                                if (Trans.con.mode & CON_USER) {
 
787
                                                        stopConstraint(&Trans);
 
788
                                                }
 
789
                                                else {
 
790
                                                        if (G.qual == 0)
 
791
                                                                setUserConstraint(&Trans, (CON_AXIS0), "along %s X");
 
792
                                                        else if (G.qual == LR_SHIFTKEY)
 
793
                                                                setUserConstraint(&Trans, (CON_AXIS1|CON_AXIS2), "locking %s X");
 
794
                                                }
 
795
                                        }
 
796
                                }
 
797
                                else {
 
798
                                        if (Trans.flag & T_2D_EDIT) {
 
799
                                                setConstraint(&Trans, mati, (CON_AXIS0), "along X axis");
 
800
                                        }
 
801
                                        else {
603
802
                                                if (G.qual == 0)
604
 
                                                        setUserConstraint(&Trans, (CON_AXIS0), "along %s X");
605
 
                                                else if ((G.qual == LR_SHIFTKEY) && ((Trans.flag & T_2D_EDIT)==0))
606
 
                                                        setUserConstraint(&Trans, (CON_AXIS1|CON_AXIS2), "locking %s X");
 
803
                                                        setConstraint(&Trans, mati, (CON_AXIS0), "along global X");
 
804
                                                else if (G.qual == LR_SHIFTKEY)
 
805
                                                        setConstraint(&Trans, mati, (CON_AXIS1|CON_AXIS2), "locking global X");
607
806
                                        }
608
807
                                }
609
 
                                else {
610
 
                                        if (G.qual == 0)
611
 
                                                setConstraint(&Trans, mati, (CON_AXIS0), "along global X");
612
 
                                        else if ((G.qual == LR_SHIFTKEY) && ((Trans.flag & T_2D_EDIT)==0))
613
 
                                                setConstraint(&Trans, mati, (CON_AXIS1|CON_AXIS2), "locking global X");
614
 
                                }
615
808
                                Trans.redraw = 1;
616
809
                        }
617
810
                        break;
618
811
                case YKEY:
619
812
                        if ((Trans.flag & T_NO_CONSTRAINT)==0) {
620
813
                                if (cmode == 'Y') {
621
 
                                        if (Trans.con.mode & CON_USER) {
 
814
                                        if (Trans.flag & T_2D_EDIT) {
622
815
                                                stopConstraint(&Trans);
623
816
                                        }
624
817
                                        else {
 
818
                                                if (Trans.con.mode & CON_USER) {
 
819
                                                        stopConstraint(&Trans);
 
820
                                                }
 
821
                                                else {
 
822
                                                        if (G.qual == 0)
 
823
                                                                setUserConstraint(&Trans, (CON_AXIS1), "along %s Y");
 
824
                                                        else if (G.qual == LR_SHIFTKEY)
 
825
                                                                setUserConstraint(&Trans, (CON_AXIS0|CON_AXIS2), "locking %s Y");
 
826
                                                }
 
827
                                        }
 
828
                                }
 
829
                                else {
 
830
                                        if (Trans.flag & T_2D_EDIT) {
 
831
                                                setConstraint(&Trans, mati, (CON_AXIS1), "along Y axis");
 
832
                                        }
 
833
                                        else {
625
834
                                                if (G.qual == 0)
626
 
                                                        setUserConstraint(&Trans, (CON_AXIS1), "along %s Y");
627
 
                                                else if ((G.qual == LR_SHIFTKEY) && ((Trans.flag & T_2D_EDIT)==0))
628
 
                                                        setUserConstraint(&Trans, (CON_AXIS0|CON_AXIS2), "locking %s Y");
 
835
                                                        setConstraint(&Trans, mati, (CON_AXIS1), "along global Y");
 
836
                                                else if (G.qual == LR_SHIFTKEY)
 
837
                                                        setConstraint(&Trans, mati, (CON_AXIS0|CON_AXIS2), "locking global Y");
629
838
                                        }
630
839
                                }
631
 
                                else {
632
 
                                        if (G.qual == 0)
633
 
                                                setConstraint(&Trans, mati, (CON_AXIS1), "along global Y");
634
 
                                        else if ((G.qual == LR_SHIFTKEY) && ((Trans.flag & T_2D_EDIT)==0))
635
 
                                                setConstraint(&Trans, mati, (CON_AXIS0|CON_AXIS2), "locking global Y");
636
 
                                }
637
840
                                Trans.redraw = 1;
638
841
                        }
639
842
                        break;
675
878
                        break;
676
879
                case PAGEUPKEY:
677
880
                case WHEELDOWNMOUSE:
678
 
                        if(Trans.flag & T_PROP_EDIT) {
 
881
                        if (Trans.flag & T_AUTOIK) {
 
882
                                transform_autoik_update(&Trans, 1);
 
883
                        }
 
884
                        else if(Trans.flag & T_PROP_EDIT) {
679
885
                                Trans.propsize*= 1.1f;
680
886
                                calculatePropRatio(&Trans);
681
887
                        }
691
897
                        break;
692
898
                case PAGEDOWNKEY:
693
899
                case WHEELUPMOUSE:
694
 
                        if(Trans.flag & T_PROP_EDIT) {
 
900
                        if (Trans.flag & T_AUTOIK) {
 
901
                                transform_autoik_update(&Trans, -1);
 
902
                        }
 
903
                        else if (Trans.flag & T_PROP_EDIT) {
695
904
                                Trans.propsize*= 0.90909090f;
696
905
                                calculatePropRatio(&Trans);
697
906
                        }
698
907
                        else view_editmove(event);
699
908
                        Trans.redraw= 1;
700
909
                        break;
 
910
//              case NDOFMOTION:
 
911
//            viewmoveNDOF(1);
 
912
  //         break;
701
913
                }
 
914
                
 
915
                // Numerical input events
702
916
                Trans.redraw |= handleNumInput(&(Trans.num), event);
 
917
                
 
918
                // NDof input events
 
919
                switch(handleNDofInput(&(Trans.ndof), event, val))
 
920
                {
 
921
                        case NDOF_CONFIRM:
 
922
                                if ((Trans.context & CTX_NDOF) == 0)
 
923
                                {
 
924
                                        /* Confirm on normal transform only */
 
925
                                        Trans.state = TRANS_CONFIRM;
 
926
                                }
 
927
                                break;
 
928
                        case NDOF_CANCEL:
 
929
                                if (Trans.context & CTX_NDOF)
 
930
                                {
 
931
                                        /* Cancel on pure NDOF transform */
 
932
                                        Trans.state = TRANS_CANCEL; 
 
933
                                }
 
934
                                else
 
935
                                {
 
936
                                        /* Otherwise, just redraw, NDof input was cancelled */
 
937
                                        Trans.redraw = 1;
 
938
                                }
 
939
                                break;
 
940
                        case NDOF_NOMOVE:
 
941
                                if (Trans.context & CTX_NDOF)
 
942
                                {
 
943
                                        /* Confirm on pure NDOF transform */
 
944
                                        Trans.state = TRANS_CONFIRM;
 
945
                                }
 
946
                                break;
 
947
                        case NDOF_REFRESH:
 
948
                                Trans.redraw = 1;
 
949
                                break;
 
950
                        
 
951
                }
 
952
                
 
953
                // Snapping events
 
954
                Trans.redraw |= handleSnapping(&Trans, event);
 
955
                
703
956
                arrows_move_cursor(event);
704
957
        }
705
958
        else {
725
978
                        break;
726
979
                }
727
980
        }
 
981
        
 
982
        // Per transform event, if present
 
983
        if (Trans.handleEvent)
 
984
                Trans.redraw |= Trans.handleEvent(&Trans, event, val);
 
985
}
 
986
 
 
987
int calculateTransformCenter(int centerMode, float *vec)
 
988
{
 
989
        int success = 1;
 
990
        checkFirstTime();
 
991
 
 
992
        Trans.state = TRANS_RUNNING;
 
993
 
 
994
        Trans.context = CTX_NONE;
 
995
        
 
996
        Trans.mode = TFM_DUMMY;
 
997
 
 
998
        initTrans(&Trans);                                      // internal data, mouse, vectors
 
999
 
 
1000
        createTransData(&Trans);                        // make TransData structs from selection
 
1001
 
 
1002
        Trans.around = centerMode;                      // override userdefined mode
 
1003
 
 
1004
        if (Trans.total == 0) {
 
1005
                success = 0;
 
1006
        }
 
1007
        else {
 
1008
                success = 1;
 
1009
                
 
1010
                calculateCenter(&Trans);
 
1011
        
 
1012
                // Copy center from constraint center. Transform center can be local    
 
1013
                VECCOPY(vec, Trans.con.center);
 
1014
        }
 
1015
 
 
1016
        postTrans(&Trans);
 
1017
 
 
1018
        /* aftertrans does insert ipos and action channels, and clears base flags, doesnt read transdata */
 
1019
        special_aftertrans_update(&Trans);
 
1020
        
 
1021
        return success;
728
1022
}
729
1023
 
730
1024
void initTransform(int mode, int context) {
734
1028
        Trans.state = TRANS_RUNNING;
735
1029
 
736
1030
        Trans.context = context;
 
1031
        
 
1032
        Trans.mode = mode;
737
1033
 
738
1034
        initTrans(&Trans);                                      // internal data, mouse, vectors
739
1035
 
740
1036
        if(Trans.spacetype==SPACE_VIEW3D) {
741
1037
                calc_manipulator_stats(curarea);
742
1038
                Mat3CpyMat4(Trans.spacemtx, G.vd->twmat);
 
1039
                Mat3Ortho(Trans.spacemtx);
743
1040
        }
744
1041
        else
745
1042
                Mat3One(Trans.spacemtx);
746
1043
 
747
 
        initTransModeFlags(&Trans, mode);       // modal settings in struct Trans
748
 
 
749
1044
        createTransData(&Trans);                        // make TransData structs from selection
750
1045
 
 
1046
        initSnapping(&Trans); // Initialize snapping data AFTER mode flags
 
1047
 
751
1048
        if (Trans.total == 0) {
752
1049
                postTrans(&Trans);
753
1050
                return;
755
1052
 
756
1053
        /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. will be removed (ton) */
757
1054
        /* EVIL2: we gave as argument also texture space context bit... was cleared */
758
 
        mode= Trans.mode;
 
1055
        /* EVIL3: extend mode for animation editors also switches modes... but is best way to avoid duplicate code */
 
1056
        mode = Trans.mode;
759
1057
        
760
1058
        calculatePropRatio(&Trans);
761
1059
        calculateCenter(&Trans);
785
1083
        case TFM_TILT:
786
1084
                initTilt(&Trans);
787
1085
                break;
 
1086
        case TFM_CURVE_SHRINKFATTEN:
 
1087
                initCurveShrinkFatten(&Trans);
 
1088
                break;
788
1089
        case TFM_TRACKBALL:
789
1090
                initTrackball(&Trans);
790
1091
                break;
806
1107
        case TFM_BONE_ENVELOPE:
807
1108
                initBoneEnvelope(&Trans);
808
1109
                break;
 
1110
        case TFM_BONE_ROLL:
 
1111
                initBoneRoll(&Trans);
 
1112
                break;
 
1113
        case TFM_TIME_TRANSLATE:
 
1114
                initTimeTranslate(&Trans);
 
1115
                break;
 
1116
        case TFM_TIME_SLIDE:
 
1117
                initTimeSlide(&Trans);
 
1118
                break;
 
1119
        case TFM_TIME_SCALE:
 
1120
                initTimeScale(&Trans);
 
1121
                break;
 
1122
        case TFM_TIME_EXTEND: 
 
1123
                /* now that transdata has been made, do like for TFM_TIME_TRANSLATE */
 
1124
                initTimeTranslate(&Trans);
 
1125
                break;
 
1126
        case TFM_BAKE_TIME:
 
1127
                initBakeTime(&Trans);
 
1128
                break;
 
1129
        case TFM_MIRROR:
 
1130
                initMirror(&Trans);
 
1131
                break;
 
1132
        case TFM_BEVEL:
 
1133
                initBevel(&Trans);
 
1134
                break;
 
1135
        case TFM_BWEIGHT:
 
1136
                initBevelWeight(&Trans);
 
1137
                break;
 
1138
        case TFM_ALIGN:
 
1139
                initAlign(&Trans);
 
1140
                break;
809
1141
        }
810
1142
}
811
1143
 
842
1174
                        }
843
1175
                        Trans.redraw = 0;
844
1176
                }
 
1177
 
 
1178
                /* If auto confirm is on, break after one pass */               
 
1179
                if (Trans.context & CTX_AUTOCONFIRM)
 
1180
                {
 
1181
                        Trans.state = TRANS_CONFIRM;
 
1182
                        break;
 
1183
                }
845
1184
                
846
1185
                /* essential for idling subloop */
847
1186
                if( qtest()==0) PIL_sleep_ms(2);
850
1189
                        event= extern_qread(&val);
851
1190
                        transformEvent(event, val);
852
1191
                }
 
1192
 
 
1193
                if(BKE_ptcache_get_continue_physics()) {
 
1194
                        do_screenhandlers(G.curscreen);
 
1195
                        Trans.redraw= 1;
 
1196
                }
853
1197
        }
854
1198
        
855
1199
        
886
1230
 
887
1231
        Trans.context = CTX_NONE;
888
1232
        
 
1233
        Trans.mode = mode;
 
1234
        
889
1235
        /* automatic switch to scaling bone envelopes */
890
1236
        if(mode==TFM_RESIZE && G.obedit && G.obedit->type==OB_ARMATURE) {
891
1237
                bArmature *arm= G.obedit->data;
895
1241
 
896
1242
        initTrans(&Trans);                                      // internal data, mouse, vectors
897
1243
 
898
 
        initTransModeFlags(&Trans, mode);       // modal settings in struct Trans
899
 
 
900
1244
        G.moving |= G_TRANSFORM_MANIP;          // signal to draw manipuls while transform
901
1245
        createTransData(&Trans);                        // make TransData structs from selection
902
1246
 
903
1247
        if (Trans.total == 0)
904
1248
                return;
905
1249
 
 
1250
        initSnapping(&Trans); // Initialize snapping data AFTER mode flags
 
1251
 
906
1252
        /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. will be removed (ton) */
907
1253
        /* EVIL2: we gave as argument also texture space context bit... was cleared */
908
 
        mode= Trans.mode;
 
1254
        mode = Trans.mode;
909
1255
        
910
1256
        calculatePropRatio(&Trans);
911
1257
        calculateCenter(&Trans);
996
1342
                        case RETKEY:
997
1343
                                Trans.state = TRANS_CONFIRM;
998
1344
                                break;
 
1345
   //         case NDOFMOTION:
 
1346
     //           viewmoveNDOF(1);
 
1347
     //           break;
999
1348
                        }
1000
1349
                        if(val) {
1001
1350
                                switch(event) {
 
1351
                                case PADPLUSKEY:
 
1352
                                        if(G.qual & LR_ALTKEY && Trans.flag & T_PROP_EDIT) {
 
1353
                                                Trans.propsize*= 1.1f;
 
1354
                                                calculatePropRatio(&Trans);
 
1355
                                        }
 
1356
                                        Trans.redraw= 1;
 
1357
                                        break;
 
1358
                                case PAGEUPKEY:
1002
1359
                                case WHEELDOWNMOUSE:
1003
 
                                case PADPLUSKEY:
1004
 
                                        if(Trans.flag & T_PROP_EDIT) {
 
1360
                                        if (Trans.flag & T_AUTOIK) {
 
1361
                                                transform_autoik_update(&Trans, 1);
 
1362
                                        }
 
1363
                                        else if(Trans.flag & T_PROP_EDIT) {
1005
1364
                                                Trans.propsize*= 1.1f;
1006
1365
                                                calculatePropRatio(&Trans);
1007
 
                                                Trans.redraw= 1;
1008
 
                                        }
1009
 
                                        break;
 
1366
                                        }
 
1367
                                        else view_editmove(event);
 
1368
                                        Trans.redraw= 1;
 
1369
                                        break;
 
1370
                                case PADMINUS:
 
1371
                                        if(G.qual & LR_ALTKEY && Trans.flag & T_PROP_EDIT) {
 
1372
                                                Trans.propsize*= 0.90909090f;
 
1373
                                                calculatePropRatio(&Trans);
 
1374
                                        }
 
1375
                                        Trans.redraw= 1;
 
1376
                                        break;
 
1377
                                case PAGEDOWNKEY:
1010
1378
                                case WHEELUPMOUSE:
1011
 
                                case PADMINUS:
1012
 
                                        if(Trans.flag & T_PROP_EDIT) {
 
1379
                                        if (Trans.flag & T_AUTOIK) {
 
1380
                                                transform_autoik_update(&Trans, -1);
 
1381
                                        }
 
1382
                                        else if (Trans.flag & T_PROP_EDIT) {
1013
1383
                                                Trans.propsize*= 0.90909090f;
1014
1384
                                                calculatePropRatio(&Trans);
1015
 
                                                Trans.redraw= 1;
1016
1385
                                        }
 
1386
                                        else view_editmove(event);
 
1387
                                        Trans.redraw= 1;
1017
1388
                                        break;
1018
 
                                }                       
 
1389
                                }
 
1390
                                                        
 
1391
                                // Numerical input events
 
1392
                                Trans.redraw |= handleNumInput(&(Trans.num), event);
1019
1393
                        }
1020
1394
                }
1021
1395
        }
1023
1397
        if(Trans.state == TRANS_CANCEL) {
1024
1398
                restoreTransObjects(&Trans);
1025
1399
        }
1026
 
        else {
 
1400
        
 
1401
        /* free data, reset vars */
 
1402
        postTrans(&Trans);
 
1403
        
 
1404
        /* aftertrans does insert ipos and action channels, and clears base flags */
 
1405
        special_aftertrans_update(&Trans);
 
1406
        
 
1407
        /* send events out for redraws */
 
1408
        viewRedrawPost(&Trans);
 
1409
 
 
1410
        if(Trans.state != TRANS_CANCEL) {
1027
1411
                BIF_undo_push(transform_to_undostr(&Trans));
1028
1412
        }
1029
1413
        
1030
 
        /* free data, reset vars */
1031
 
        postTrans(&Trans);
1032
 
        
1033
 
        /* aftertrans does insert ipos and action channels, and clears base flags */
1034
 
        special_aftertrans_update(&Trans);
1035
 
        
1036
 
        /* send events out for redraws */
1037
 
        viewRedrawPost(&Trans);
1038
1414
}
1039
1415
 
1040
 
/* ************************** TRANSFORMATIONS **************************** */
 
1416
/* ************************** TRANSFORM LOCKS **************************** */
1041
1417
 
1042
1418
static void protectedTransBits(short protectflag, float *vec)
1043
1419
{
1096
1472
        }
1097
1473
}
1098
1474
 
 
1475
/* ******************* TRANSFORM LIMITS ********************** */
 
1476
 
 
1477
static void constraintTransLim(TransInfo *t, TransData *td)
 
1478
{
 
1479
        if (td->con) {
 
1480
                bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
 
1481
                bConstraintOb cob;
 
1482
                bConstraint *con;
 
1483
                
 
1484
                /* Make a temporary bConstraintOb for using these limit constraints 
 
1485
                 *      - they only care that cob->matrix is correctly set ;-)
 
1486
                 *      - current space should be local
 
1487
                 */
 
1488
                memset(&cob, 0, sizeof(bConstraintOb));
 
1489
                Mat4One(cob.matrix);
 
1490
                if (td->tdi) {
 
1491
                        TransDataIpokey *tdi= td->tdi;
 
1492
                        cob.matrix[3][0]= tdi->locx[0];
 
1493
                        cob.matrix[3][1]= tdi->locy[0];
 
1494
                        cob.matrix[3][2]= tdi->locz[0];
 
1495
                }
 
1496
                else {
 
1497
                        VECCOPY(cob.matrix[3], td->loc);
 
1498
                }
 
1499
                
 
1500
                /* Evaluate valid constraints */
 
1501
                for (con= td->con; con; con= con->next) {
 
1502
                        float tmat[4][4];
 
1503
                        
 
1504
                        /* only use it if it's tagged for this purpose (and the right type) */
 
1505
                        if (con->type == CONSTRAINT_TYPE_LOCLIMIT) {
 
1506
                                bLocLimitConstraint *data= con->data;
 
1507
                                
 
1508
                                if ((data->flag2 & LIMIT_TRANSFORM)==0) 
 
1509
                                        continue;
 
1510
                                
 
1511
                                /* do space conversions */
 
1512
                                if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
 
1513
                                        /* just multiply by td->mtx (this should be ok) */
 
1514
                                        Mat4CpyMat4(tmat, cob.matrix);
 
1515
                                        Mat4MulMat34(cob.matrix, td->mtx, tmat);
 
1516
                                }
 
1517
                                else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
 
1518
                                        /* skip... incompatable spacetype */
 
1519
                                        continue;
 
1520
                                }
 
1521
                                
 
1522
                                /* do constraint */
 
1523
                                cti->evaluate_constraint(con, &cob, NULL);
 
1524
                                
 
1525
                                /* convert spaces again */
 
1526
                                if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
 
1527
                                        /* just multiply by td->mtx (this should be ok) */
 
1528
                                        Mat4CpyMat4(tmat, cob.matrix);
 
1529
                                        Mat4MulMat34(cob.matrix, td->smtx, tmat);
 
1530
                                }
 
1531
                        }
 
1532
                }
 
1533
                
 
1534
                /* copy results from cob->matrix */
 
1535
                if (td->tdi) {
 
1536
                        TransDataIpokey *tdi= td->tdi;
 
1537
                        tdi->locx[0]= cob.matrix[3][0];
 
1538
                        tdi->locy[0]= cob.matrix[3][1];
 
1539
                        tdi->locz[0]= cob.matrix[3][2];
 
1540
                }
 
1541
                else {
 
1542
                        VECCOPY(td->loc, cob.matrix[3]);
 
1543
                }
 
1544
        }
 
1545
}
 
1546
 
 
1547
static void constraintRotLim(TransInfo *t, TransData *td)
 
1548
{
 
1549
        if (td->con) {
 
1550
                bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT);
 
1551
                bConstraintOb cob;
 
1552
                bConstraint *con;
 
1553
                
 
1554
                /* Make a temporary bConstraintOb for using these limit constraints 
 
1555
                 *      - they only care that cob->matrix is correctly set ;-)
 
1556
                 *      - current space should be local
 
1557
                 */
 
1558
                memset(&cob, 0, sizeof(bConstraintOb));
 
1559
                if (td->flag & TD_USEQUAT) {
 
1560
                        /* quats */
 
1561
                        if (td->ext)
 
1562
                                QuatToMat4(td->ext->quat, cob.matrix);
 
1563
                        else
 
1564
                                return;
 
1565
                }
 
1566
                else if (td->tdi) {
 
1567
                        /* ipo-keys eulers */
 
1568
                        TransDataIpokey *tdi= td->tdi;
 
1569
                        float eul[3];
 
1570
                        
 
1571
                        eul[0]= tdi->rotx[0];
 
1572
                        eul[1]= tdi->roty[0];
 
1573
                        eul[2]= tdi->rotz[0];
 
1574
                        
 
1575
                        EulToMat4(eul, cob.matrix);
 
1576
                }
 
1577
                else {
 
1578
                        /* eulers */
 
1579
                        if (td->ext)
 
1580
                                EulToMat4(td->ext->rot, cob.matrix);
 
1581
                        else
 
1582
                                return;
 
1583
                }
 
1584
                        
 
1585
                /* Evaluate valid constraints */
 
1586
                for (con= td->con; con; con= con->next) {
 
1587
                        /* we're only interested in Limit-Scale constraints */
 
1588
                        if (con->type == CONSTRAINT_TYPE_ROTLIMIT) {
 
1589
                                bRotLimitConstraint *data= con->data;
 
1590
                                float tmat[4][4];
 
1591
                                
 
1592
                                /* only use it if it's tagged for this purpose */
 
1593
                                if ((data->flag2 & LIMIT_TRANSFORM)==0) 
 
1594
                                        continue;
 
1595
                                        
 
1596
                                /* do space conversions */
 
1597
                                if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
 
1598
                                        /* just multiply by td->mtx (this should be ok) */
 
1599
                                        Mat4CpyMat4(tmat, cob.matrix);
 
1600
                                        Mat4MulMat34(cob.matrix, td->mtx, tmat);
 
1601
                                }
 
1602
                                else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
 
1603
                                        /* skip... incompatable spacetype */
 
1604
                                        continue;
 
1605
                                }
 
1606
                                
 
1607
                                /* do constraint */
 
1608
                                cti->evaluate_constraint(con, &cob, NULL);
 
1609
                                
 
1610
                                /* convert spaces again */
 
1611
                                if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
 
1612
                                        /* just multiply by td->mtx (this should be ok) */
 
1613
                                        Mat4CpyMat4(tmat, cob.matrix);
 
1614
                                        Mat4MulMat34(cob.matrix, td->smtx, tmat);
 
1615
                                }
 
1616
                        }
 
1617
                }
 
1618
                
 
1619
                /* copy results from cob->matrix */
 
1620
                if (td->flag & TD_USEQUAT) {
 
1621
                        /* quats */
 
1622
                        Mat4ToQuat(cob.matrix, td->ext->quat);
 
1623
                }
 
1624
                else if (td->tdi) {
 
1625
                        /* ipo-keys eulers */
 
1626
                        TransDataIpokey *tdi= td->tdi;
 
1627
                        float eul[3];
 
1628
                        
 
1629
                        Mat4ToEul(cob.matrix, eul);
 
1630
                        
 
1631
                        tdi->rotx[0]= eul[0];
 
1632
                        tdi->roty[0]= eul[1];
 
1633
                        tdi->rotz[0]= eul[2];
 
1634
                }
 
1635
                else {
 
1636
                        /* eulers */
 
1637
                        Mat4ToEul(cob.matrix, td->ext->rot);
 
1638
                }
 
1639
        }
 
1640
}
 
1641
 
 
1642
static void constraintSizeLim(TransInfo *t, TransData *td)
 
1643
{
 
1644
        if (td->con && td->ext) {
 
1645
                bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT);
 
1646
                bConstraintOb cob;
 
1647
                bConstraint *con;
 
1648
                
 
1649
                /* Make a temporary bConstraintOb for using these limit constraints 
 
1650
                 *      - they only care that cob->matrix is correctly set ;-)
 
1651
                 *      - current space should be local
 
1652
                 */
 
1653
                memset(&cob, 0, sizeof(bConstraintOb));
 
1654
                if (td->tdi) {
 
1655
                        TransDataIpokey *tdi= td->tdi;
 
1656
                        float size[3];
 
1657
                        
 
1658
                        size[0]= tdi->sizex[0];
 
1659
                        size[1]= tdi->sizey[0];
 
1660
                        size[2]= tdi->sizez[0];
 
1661
                        SizeToMat4(size, cob.matrix);
 
1662
                } 
 
1663
                else if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
 
1664
                        /* scale val and reset size */
 
1665
                        return; // TODO: fix this case
 
1666
                }
 
1667
                else {
 
1668
                        /* Reset val if SINGLESIZE but using a constraint */
 
1669
                        if (td->flag & TD_SINGLESIZE)
 
1670
                                return;
 
1671
                        
 
1672
                        SizeToMat4(td->ext->size, cob.matrix);
 
1673
                }
 
1674
                        
 
1675
                /* Evaluate valid constraints */
 
1676
                for (con= td->con; con; con= con->next) {
 
1677
                        /* we're only interested in Limit-Scale constraints */
 
1678
                        if (con->type == CONSTRAINT_TYPE_SIZELIMIT) {
 
1679
                                bSizeLimitConstraint *data= con->data;
 
1680
                                float tmat[4][4];
 
1681
                                
 
1682
                                /* only use it if it's tagged for this purpose */
 
1683
                                if ((data->flag2 & LIMIT_TRANSFORM)==0) 
 
1684
                                        continue;
 
1685
                                        
 
1686
                                /* do space conversions */
 
1687
                                if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
 
1688
                                        /* just multiply by td->mtx (this should be ok) */
 
1689
                                        Mat4CpyMat4(tmat, cob.matrix);
 
1690
                                        Mat4MulMat34(cob.matrix, td->mtx, tmat);
 
1691
                                }
 
1692
                                else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
 
1693
                                        /* skip... incompatable spacetype */
 
1694
                                        continue;
 
1695
                                }
 
1696
                                
 
1697
                                /* do constraint */
 
1698
                                cti->evaluate_constraint(con, &cob, NULL);
 
1699
                                
 
1700
                                /* convert spaces again */
 
1701
                                if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
 
1702
                                        /* just multiply by td->mtx (this should be ok) */
 
1703
                                        Mat4CpyMat4(tmat, cob.matrix);
 
1704
                                        Mat4MulMat34(cob.matrix, td->smtx, tmat);
 
1705
                                }
 
1706
                        }
 
1707
                }
 
1708
                
 
1709
                /* copy results from cob->matrix */
 
1710
                if (td->tdi) {
 
1711
                        TransDataIpokey *tdi= td->tdi;
 
1712
                        float size[3];
 
1713
                        
 
1714
                        Mat4ToSize(cob.matrix, size);
 
1715
                        
 
1716
                        tdi->sizex[0]= size[0];
 
1717
                        tdi->sizey[0]= size[1];
 
1718
                        tdi->sizez[0]= size[2];
 
1719
                } 
 
1720
                else if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
 
1721
                        /* scale val and reset size */
 
1722
                        return; // TODO: fix this case
 
1723
                }
 
1724
                else {
 
1725
                        /* Reset val if SINGLESIZE but using a constraint */
 
1726
                        if (td->flag & TD_SINGLESIZE)
 
1727
                                return;
 
1728
                                
 
1729
                        Mat4ToSize(cob.matrix, td->ext->size);
 
1730
                }
 
1731
        }
 
1732
}
 
1733
 
1099
1734
/* ************************** WARP *************************** */
1100
1735
 
1101
 
/* warp is done fully in view space */
1102
1736
void initWarp(TransInfo *t) 
1103
1737
{
1104
1738
        float max[3], min[3];
1105
1739
        int i;
1106
1740
        
1107
 
        calculateCenterCursor(t);
1108
 
        t->idx_max = 0;
1109
 
        t->num.idx_max = 0;
 
1741
        t->mode = TFM_WARP;
1110
1742
        t->transform = Warp;
 
1743
        t->handleEvent = handleEventWarp;
 
1744
        
 
1745
        t->idx_max = 0;
 
1746
        t->num.idx_max = 0;
1111
1747
        t->snap[0] = 0.0f;
1112
1748
        t->snap[1] = 5.0f;
1113
1749
        t->snap[2] = 1.0f;
1114
1750
        
 
1751
        t->flag |= T_NO_CONSTRAINT;
 
1752
 
 
1753
/* warp is done fully in view space */
 
1754
        calculateCenterCursor(t);
1115
1755
        t->fac = (float)(t->center2d[0] - t->imval[0]);
1116
1756
        
1117
1757
        /* we need min/max in view space */
1128
1768
                        VECCOPY(min, center);
1129
1769
                }
1130
1770
        }
1131
 
 
 
1771
        
1132
1772
        t->center[0]= (min[0]+max[0])/2.0f;
1133
1773
        t->center[1]= (min[1]+max[1])/2.0f;
1134
1774
        t->center[2]= (min[2]+max[2])/2.0f;
1135
1775
        
1136
 
        t->val= (max[0]-min[0])/2.0f;   // t->val is free variable
 
1776
        if (max[0] == min[0]) max[0] += 0.1; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */
 
1777
        t->val= (max[0]-min[0])/2.0f; /* t->val is X dimension projected boundbox */
1137
1778
}
1138
1779
 
 
1780
int handleEventWarp(TransInfo *t, unsigned short event, short val)
 
1781
{
 
1782
        int status = 0;
 
1783
        
 
1784
        if (event == MIDDLEMOUSE && val)
 
1785
        {
 
1786
                // Use customData pointer to signal warp direction
 
1787
                if      (t->customData == 0)
 
1788
                        t->customData = (void*)1;
 
1789
                else
 
1790
                        t->customData = 0;
 
1791
                        
 
1792
                status = 1;
 
1793
        }
 
1794
        
 
1795
        return status;
 
1796
}
1139
1797
 
1140
1798
int Warp(TransInfo *t, short mval[2])
1141
1799
{
1165
1823
        Mat4MulVecfl(t->viewmat, cursor);
1166
1824
        VecSubf(cursor, cursor, t->viewmat[3]);
1167
1825
 
1168
 
        // amount of degrees for warp, 450 = allow to create 360 degree warp
1169
 
        circumfac= 450.0f*(mval[1] - t->imval[1]) / (float)(curarea->winy);
1170
 
        circumfac+= 90.0f;
 
1826
        /* amount of degrees for warp */
 
1827
        circumfac= 360.0f * InputHorizontalRatio(t, mval);
 
1828
        
 
1829
        if (t->customData) /* non-null value indicates reversed input */
 
1830
        {
 
1831
                circumfac *= -1;
 
1832
        }
1171
1833
 
1172
1834
        snapGrid(t, &circumfac);
1173
1835
        applyNumInput(&t->num, &circumfac);
1187
1849
        
1188
1850
        circumfac*= (float)(-M_PI/360.0);
1189
1851
        
1190
 
        for(i = 0 ; i < t->total; i++, td++) {
 
1852
        for(i = 0; i < t->total; i++, td++) {
1191
1853
                float loc[3];
1192
1854
                if (td->flag & TD_NOACTION)
1193
1855
                        break;
1194
1856
 
1195
 
                /* translate point to centre, rotate in such a way that outline==distance */
 
1857
                if (td->flag & TD_SKIP)
 
1858
                        continue;
1196
1859
                
 
1860
                /* translate point to center, rotate in such a way that outline==distance */
1197
1861
                VECCOPY(vec, td->iloc);
1198
1862
                Mat3MulVecfl(td->mtx, vec);
1199
1863
                Mat4MulVecfl(t->viewmat, vec);
1200
1864
                VecSubf(vec, vec, t->viewmat[3]);
1201
1865
                
1202
1866
                dist= vec[0]-cursor[0];
1203
 
 
1204
 
                phi0= (circumfac*dist/t->val);  // t->val is X dimension projected boundbox
 
1867
                
 
1868
                /* t->val is X dimension projected boundbox */
 
1869
                phi0= (circumfac*dist/t->val);  
1205
1870
                
1206
1871
                vec[1]= (vec[1]-cursor[1]);
1207
1872
                
1214
1879
                Mat4MulVecfl(t->viewinv, loc);
1215
1880
                VecSubf(loc, loc, t->viewinv[3]);
1216
1881
                Mat3MulVecfl(td->smtx, loc);
1217
 
 
 
1882
                
1218
1883
                VecSubf(loc, loc, td->iloc);
1219
1884
                VecMulf(loc, td->factor);
1220
1885
                VecAddf(td->loc, td->iloc, loc);
1235
1900
 
1236
1901
void initShear(TransInfo *t) 
1237
1902
{
1238
 
        t->idx_max = 0;
1239
 
        t->num.idx_max = 0;
1240
 
        t->snap[0] = 0.0f;
1241
 
        t->snap[1] = 0.1f;
1242
 
        t->snap[2] = t->snap[1] * 0.1f;
 
1903
        t->mode = TFM_SHEAR;
1243
1904
        t->transform = Shear;
1244
 
}
 
1905
        t->handleEvent = handleEventShear;
 
1906
        
 
1907
        t->idx_max = 0;
 
1908
        t->num.idx_max = 0;
 
1909
        t->snap[0] = 0.0f;
 
1910
        t->snap[1] = 0.1f;
 
1911
        t->snap[2] = t->snap[1] * 0.1f;
 
1912
        
 
1913
        t->flag |= T_NO_CONSTRAINT;
 
1914
}
 
1915
 
 
1916
int handleEventShear(TransInfo *t, unsigned short event, short val)
 
1917
{
 
1918
        int status = 0;
 
1919
        
 
1920
        if (event == MIDDLEMOUSE && val)
 
1921
        {
 
1922
                // Use customData pointer to signal Shear direction
 
1923
                if      (t->customData == 0)
 
1924
                        t->customData = (void*)1;
 
1925
                else
 
1926
                        t->customData = 0;
 
1927
                        
 
1928
                status = 1;
 
1929
        }
 
1930
        
 
1931
        return status;
 
1932
}
 
1933
 
1245
1934
 
1246
1935
int Shear(TransInfo *t, short mval[2]) 
1247
1936
{
1255
1944
        Mat3CpyMat4(persmat, t->viewmat);
1256
1945
        Mat3Inv(persinv, persmat);
1257
1946
 
1258
 
        value = 0.05f * InputHorizontalAbsolute(t, mval);
 
1947
        // Custom data signals shear direction
 
1948
        if (t->customData == 0)
 
1949
                value = 0.05f * InputHorizontalAbsolute(t, mval);
 
1950
        else
 
1951
                value = 0.05f * InputVerticalAbsolute(t, mval);
1259
1952
 
1260
1953
        snapGrid(t, &value);
1261
1954
 
1275
1968
        }
1276
1969
        
1277
1970
        Mat3One(smat);
1278
 
        smat[1][0] = value;
 
1971
        
 
1972
        // Custom data signals shear direction
 
1973
        if (t->customData == 0)
 
1974
                smat[1][0] = value;
 
1975
        else
 
1976
                smat[0][1] = value;
 
1977
        
1279
1978
        Mat3MulMat3(tmat, smat, persmat);
1280
1979
        Mat3MulMat3(totmat, persinv, tmat);
1281
1980
        
1283
1982
                if (td->flag & TD_NOACTION)
1284
1983
                        break;
1285
1984
 
 
1985
                if (td->flag & TD_SKIP)
 
1986
                        continue;
 
1987
 
1286
1988
                if (G.obedit) {
1287
1989
                        float mat3[3][3];
1288
1990
                        Mat3MulMat3(mat3, totmat, td->mtx);
1318
2020
 
1319
2021
void initResize(TransInfo *t) 
1320
2022
{
1321
 
        t->fac = (float)sqrt(
1322
 
                (
1323
 
                        ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
1324
 
                +
1325
 
                        ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
1326
 
                ) );
1327
 
 
1328
 
        if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
1329
 
        
1330
 
        t->idx_max = 2;
1331
 
        t->num.idx_max = 2;
1332
 
        t->snap[0] = 0.0f;
1333
 
        t->snap[1] = 0.1f;
1334
 
        t->snap[2] = t->snap[1] * 0.1f;
 
2023
        t->mode = TFM_RESIZE;
1335
2024
        t->transform = Resize;
 
2025
        
 
2026
        t->flag |= T_NULL_ONE;
 
2027
        t->num.flag |= NUM_NULL_ONE;
 
2028
        t->num.flag |= NUM_AFFECT_ALL;
 
2029
        if (!G.obedit) {
 
2030
                t->flag |= T_NO_ZERO;
 
2031
                t->num.flag |= NUM_NO_ZERO;
 
2032
        }
 
2033
        
 
2034
        t->idx_max = 2;
 
2035
        t->num.idx_max = 2;
 
2036
        t->snap[0] = 0.0f;
 
2037
        t->snap[1] = 0.1f;
 
2038
        t->snap[2] = t->snap[1] * 0.1f;
 
2039
 
 
2040
        t->fac = (float)sqrt(
 
2041
                (
 
2042
                        ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
 
2043
                +
 
2044
                        ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
 
2045
                ) );
 
2046
 
 
2047
        if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
1336
2048
}
1337
2049
 
1338
2050
static void headerResize(TransInfo *t, float vec[3], char *str) {
1375
2087
        float vec[3];
1376
2088
        
1377
2089
        VecCopyf(vec, mat[0]);
1378
 
        size[0]= Normalise(vec);
 
2090
        size[0]= Normalize(vec);
1379
2091
        VecCopyf(vec, mat[1]);
1380
 
        size[1]= Normalise(vec);
 
2092
        size[1]= Normalize(vec);
1381
2093
        VecCopyf(vec, mat[2]);
1382
 
        size[2]= Normalise(vec);
 
2094
        size[2]= Normalize(vec);
1383
2095
        
1384
2096
        /* first tried with dotproduct... but the sign flip is crucial */
1385
2097
        if( VECSIGNFLIP(mat[0], smat[0]) ) size[0]= -size[0]; 
1428
2140
 
1429
2141
        if (td->ext) {
1430
2142
                float fsize[3];
1431
 
 
1432
 
                if (t->flag & (T_OBJECT|T_TEXTURE)) {
 
2143
                
 
2144
                if (t->flag & (T_OBJECT|T_TEXTURE|T_POSE)) {
1433
2145
                        float obsizemat[3][3];
1434
2146
                        // Reorient the size mat to fit the oriented object.
1435
2147
                        Mat3MulMat3(obsizemat, tmat, td->axismtx);
1443
2155
                
1444
2156
                protectedSizeBits(td->protectflag, fsize);
1445
2157
                
1446
 
                if ((t->flag & T_V3D_ALIGN)==0) {       // align mode doesn't rotate objects itself
 
2158
                if ((t->flag & T_V3D_ALIGN)==0) {       // align mode doesn't resize objects itself
1447
2159
                        /* handle ipokeys? */
1448
2160
                        if(td->tdi) {
1449
2161
                                TransDataIpokey *tdi= td->tdi;
1457
2169
                                add_tdi_poin(tdi->sizey, tdi->oldsize+1, vec[1]);
1458
2170
                                add_tdi_poin(tdi->sizez, tdi->oldsize+2, vec[2]);
1459
2171
                                
1460
 
                        }
 
2172
                        } 
1461
2173
                        else if((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)){
1462
2174
                                /* scale val and reset size */
1463
2175
                                *td->val = td->ival * fsize[0] * td->factor;
1464
 
 
 
2176
                                
1465
2177
                                td->ext->size[0] = td->ext->isize[0];
1466
2178
                                td->ext->size[1] = td->ext->isize[1];
1467
2179
                                td->ext->size[2] = td->ext->isize[2];
1470
2182
                                /* Reset val if SINGLESIZE but using a constraint */
1471
2183
                                if (td->flag & TD_SINGLESIZE)
1472
2184
                                        *td->val = td->ival;
1473
 
 
 
2185
                                
1474
2186
                                td->ext->size[0] = td->ext->isize[0] * (fsize[0]) * td->factor;
1475
2187
                                td->ext->size[1] = td->ext->isize[1] * (fsize[1]) * td->factor;
1476
2188
                                td->ext->size[2] = td->ext->isize[2] * (fsize[2]) * td->factor;
1477
2189
                        }
1478
2190
                }
 
2191
                
 
2192
                constraintSizeLim(t, td);
1479
2193
        }
 
2194
        
1480
2195
        /* For individual element center, Editmode need to use iloc */
1481
2196
        if (t->flag & T_POINTS)
1482
2197
                VecSubf(vec, td->iloc, center);
1493
2208
 
1494
2209
        VecMulf(vec, td->factor);
1495
2210
 
1496
 
        if (t->flag & T_OBJECT) {
 
2211
        if (t->flag & (T_OBJECT|T_POSE)) {
1497
2212
                Mat3MulVecfl(td->smtx, vec);
1498
2213
        }
1499
2214
 
1506
2221
                add_tdi_poin(tdi->locz, tdi->oldloc+2, vec[2]);
1507
2222
        }
1508
2223
        else VecAddf(td->loc, td->iloc, vec);
 
2224
        
 
2225
        constraintTransLim(t, td);
1509
2226
}
1510
2227
 
1511
2228
int Resize(TransInfo *t, short mval[2]) 
1538
2255
                constraintNumInput(t, size);
1539
2256
        }
1540
2257
 
 
2258
        applySnapping(t, size);
 
2259
 
1541
2260
        SizeToMat3(size, mat);
1542
2261
 
1543
2262
        if (t->con.applySize) {
1551
2270
        for(i = 0, td=t->data; i < t->total; i++, td++) {
1552
2271
                if (td->flag & TD_NOACTION)
1553
2272
                        break;
 
2273
 
 
2274
                if (td->flag & TD_SKIP)
 
2275
                        continue;
1554
2276
                
1555
2277
                ElementResize(t, td, mat);
1556
2278
        }
1557
2279
 
1558
 
        /* evil hack - redo resize if cliiping needeed */
 
2280
        /* evil hack - redo resize if cliping needed */
1559
2281
        if (t->flag & T_CLIP_UV && clipUVTransform(t, size, 1)) {
1560
2282
                SizeToMat3(size, mat);
1561
2283
 
1584
2306
        TransData *td = t->data;
1585
2307
        int i;
1586
2308
 
 
2309
        t->mode = TFM_TOSPHERE;
 
2310
        t->transform = ToSphere;
 
2311
 
 
2312
        t->idx_max = 0;
 
2313
        t->num.idx_max = 0;
 
2314
        t->snap[0] = 0.0f;
 
2315
        t->snap[1] = 0.1f;
 
2316
        t->snap[2] = t->snap[1] * 0.1f;
 
2317
        
 
2318
        t->num.flag |= NUM_NULL_ONE | NUM_NO_NEGATIVE;
 
2319
        t->flag |= T_NO_CONSTRAINT;
 
2320
 
1587
2321
        // Calculate average radius
1588
2322
        for(i = 0 ; i < t->total; i++, td++) {
1589
2323
                t->val += VecLenf(t->center, td->iloc);
1590
2324
        }
1591
2325
 
1592
2326
        t->val /= (float)t->total;
1593
 
 
1594
 
        t->idx_max = 0;
1595
 
        t->num.idx_max = 0;
1596
 
        t->snap[0] = 0.0f;
1597
 
        t->snap[1] = 0.1f;
1598
 
        t->snap[2] = t->snap[1] * 0.1f;
1599
 
        t->transform = ToSphere;
1600
2327
}
1601
2328
 
1602
 
 
1603
 
 
1604
2329
int ToSphere(TransInfo *t, short mval[2]) 
1605
2330
{
1606
2331
        float vec[3];
1607
2332
        float ratio, radius;
1608
2333
        int i;
1609
 
        char str[50];
 
2334
        char str[64];
1610
2335
        TransData *td = t->data;
1611
2336
 
1612
2337
        ratio = InputHorizontalRatio(t, mval);
1639
2364
                if (td->flag & TD_NOACTION)
1640
2365
                        break;
1641
2366
 
 
2367
                if (td->flag & TD_SKIP)
 
2368
                        continue;
 
2369
 
1642
2370
                VecSubf(vec, td->iloc, t->center);
1643
2371
 
1644
 
                radius = Normalise(vec);
 
2372
                radius = Normalize(vec);
1645
2373
 
1646
2374
                tratio = ratio * td->factor;
1647
2375
 
1649
2377
 
1650
2378
                VecAddf(td->loc, t->center, vec);
1651
2379
        }
 
2380
        
1652
2381
 
1653
2382
        recalcData(t);
1654
2383
 
1664
2393
 
1665
2394
void initRotation(TransInfo *t) 
1666
2395
{
1667
 
        t->idx_max = 0;
1668
 
        t->num.idx_max = 0;
1669
 
        t->snap[0] = 0.0f;
1670
 
        t->snap[1] = (float)((5.0/180)*M_PI);
1671
 
        t->snap[2] = t->snap[1] * 0.2f;
1672
 
        t->fac = 0;
 
2396
        t->mode = TFM_ROTATION;
1673
2397
        t->transform = Rotation;
 
2398
        
 
2399
        t->ndof.axis = 16;
 
2400
        /* Scale down and flip input for rotation */
 
2401
        t->ndof.factor[0] = -0.2f;
 
2402
        
 
2403
        t->idx_max = 0;
 
2404
        t->num.idx_max = 0;
 
2405
        t->snap[0] = 0.0f;
 
2406
        t->snap[1] = (float)((5.0/180)*M_PI);
 
2407
        t->snap[2] = t->snap[1] * 0.2f;
 
2408
        t->fac = 0;
 
2409
        
 
2410
        if (t->flag & T_2D_EDIT)
 
2411
                t->flag |= T_NO_CONSTRAINT;
1674
2412
}
1675
2413
 
1676
2414
static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3]) {
1686
2424
                
1687
2425
                VecAddf(td->loc, vec, t->center);
1688
2426
 
 
2427
                VecSubf(vec,td->loc,td->iloc);
 
2428
                protectedTransBits(td->protectflag, vec);
 
2429
                VecAddf(td->loc, td->iloc, vec);
 
2430
 
1689
2431
                if(td->flag & TD_USEQUAT) {
1690
2432
                        Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
1691
2433
                        Mat3ToQuat(fmat, quat); // Actual transform
 
2434
                        
 
2435
                        if(td->ext->quat){
 
2436
                                QuatMul(td->ext->quat, quat, td->ext->iquat);
 
2437
                                
 
2438
                                /* is there a reason not to have this here? -jahka */
 
2439
                                protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
 
2440
                        }
 
2441
                }
 
2442
        }
 
2443
        /**
 
2444
         * HACK WARNING
 
2445
         * 
 
2446
         * This is some VERY ugly special case to deal with pose mode.
 
2447
         * 
 
2448
         * The problem is that mtx and smtx include each bone orientation.
 
2449
         * 
 
2450
         * That is needed to rotate each bone properly, HOWEVER, to calculate
 
2451
         * the translation component, we only need the actual armature object's
 
2452
         * matrix (and inverse). That is not all though. Once the proper translation
 
2453
         * has been computed, it has to be converted back into the bone's space.
 
2454
         */
 
2455
        else if (t->flag & T_POSE) {
 
2456
                float pmtx[3][3], imtx[3][3];
 
2457
 
 
2458
                // Extract and invert armature object matrix            
 
2459
                Mat3CpyMat4(pmtx, t->poseobj->obmat);
 
2460
                Mat3Inv(imtx, pmtx);
 
2461
                
 
2462
                VecSubf(vec, td->center, t->center);
 
2463
                
 
2464
                Mat3MulVecfl(pmtx, vec);        // To Global space
 
2465
                Mat3MulVecfl(mat, vec);         // Applying rotation
 
2466
                Mat3MulVecfl(imtx, vec);        // To Local space
 
2467
 
 
2468
                VecAddf(vec, vec, t->center);
 
2469
                /* vec now is the location where the object has to be */
 
2470
                
 
2471
                VecSubf(vec, vec, td->center); // Translation needed from the initial location
 
2472
                
 
2473
                Mat3MulVecfl(pmtx, vec);        // To Global space
 
2474
                Mat3MulVecfl(td->smtx, vec);// To Pose space
 
2475
 
 
2476
                protectedTransBits(td->protectflag, vec);
 
2477
 
 
2478
                VecAddf(td->loc, td->iloc, vec);
 
2479
                
 
2480
                constraintTransLim(t, td);
 
2481
                
 
2482
                /* rotation */
 
2483
                if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate objects itself
 
2484
                        Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
 
2485
                        
 
2486
                        Mat3ToQuat(fmat, quat); // Actual transform
 
2487
                        
1692
2488
                        QuatMul(td->ext->quat, quat, td->ext->iquat);
 
2489
                        /* this function works on end result */
 
2490
                        protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
 
2491
                        
 
2492
                        constraintRotLim(t, td);
1693
2493
                }
1694
2494
        }
1695
2495
        else {
1696
2496
                /* translation */
1697
 
                
1698
2497
                VecSubf(vec, td->center, t->center);
1699
2498
                Mat3MulVecfl(mat, vec);
1700
2499
                VecAddf(vec, vec, t->center);
1701
2500
                /* vec now is the location where the object has to be */
1702
2501
                VecSubf(vec, vec, td->center);
1703
2502
                Mat3MulVecfl(td->smtx, vec);
1704
 
 
 
2503
                
1705
2504
                protectedTransBits(td->protectflag, vec);
1706
 
 
 
2505
                
1707
2506
                if(td->tdi) {
1708
2507
                        TransDataIpokey *tdi= td->tdi;
1709
2508
                        add_tdi_poin(tdi->locx, tdi->oldloc, vec[0]);
1711
2510
                        add_tdi_poin(tdi->locz, tdi->oldloc+2, vec[2]);
1712
2511
                }
1713
2512
                else VecAddf(td->loc, td->iloc, vec);
 
2513
                
 
2514
                constraintTransLim(t, td);
1714
2515
 
1715
2516
                /* rotation */
1716
 
                
1717
 
                if(td->flag & TD_USEQUAT) {
1718
 
                        Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
1719
 
                        Mat3ToQuat(fmat, quat); // Actual transform
1720
 
                        
1721
 
                        QuatMul(td->ext->quat, quat, td->ext->iquat);
1722
 
                        /* this function works on end result */
1723
 
                        protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
1724
 
                }
1725
 
                else if ((t->flag & T_V3D_ALIGN)==0) {  // align mode doesn't rotate objects itself
1726
 
                        float obmat[3][3];
1727
 
                        
1728
 
                        /* are there ipo keys? */
1729
 
                        if(td->tdi) {
1730
 
                                TransDataIpokey *tdi= td->tdi;
1731
 
                                float rot[3];
1732
 
                                
1733
 
                                /* calculate the total rotatation in eulers */
1734
 
                                VecAddf(eul, td->ext->irot, td->ext->drot);
1735
 
                                EulToMat3(eul, obmat);
1736
 
                                /* mat = transform, obmat = object rotation */
1737
 
                                Mat3MulMat3(fmat, mat, obmat);
1738
 
                                Mat3ToEul(fmat, eul);
1739
 
                                compatible_eul(eul, td->ext->irot);
1740
 
                                
1741
 
                                /* correct back for delta rot */
1742
 
                                if(tdi->flag & TOB_IPODROT) {
1743
 
                                        VecSubf(rot, eul, td->ext->irot);
 
2517
                if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate objects itself
 
2518
                        if(td->flag & TD_USEQUAT) {
 
2519
                                Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
 
2520
                                Mat3ToQuat(fmat, quat); // Actual transform
 
2521
                                
 
2522
                                QuatMul(td->ext->quat, quat, td->ext->iquat);
 
2523
                                /* this function works on end result */
 
2524
                                protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
 
2525
                        }
 
2526
                        else {
 
2527
                                float obmat[3][3];
 
2528
                                
 
2529
                                /* are there ipo keys? */
 
2530
                                if(td->tdi) {
 
2531
                                        TransDataIpokey *tdi= td->tdi;
 
2532
                                        float rot[3];
 
2533
                                        
 
2534
                                        /* calculate the total rotatation in eulers */
 
2535
                                        VecAddf(eul, td->ext->irot, td->ext->drot);
 
2536
                                        EulToMat3(eul, obmat);
 
2537
                                        /* mat = transform, obmat = object rotation */
 
2538
                                        Mat3MulMat3(fmat, mat, obmat);
 
2539
                                        
 
2540
                                        Mat3ToCompatibleEul(fmat, eul, td->ext->irot);
 
2541
                                        
 
2542
                                        /* correct back for delta rot */
 
2543
                                        if(tdi->flag & TOB_IPODROT) {
 
2544
                                                VecSubf(rot, eul, td->ext->irot);
 
2545
                                        }
 
2546
                                        else {
 
2547
                                                VecSubf(rot, eul, td->ext->drot);
 
2548
                                        }
 
2549
                                        
 
2550
                                        VecMulf(rot, (float)(9.0/M_PI_2));
 
2551
                                        VecSubf(rot, rot, tdi->oldrot);
 
2552
                                        
 
2553
                                        protectedRotateBits(td->protectflag, rot, tdi->oldrot);
 
2554
                                        
 
2555
                                        add_tdi_poin(tdi->rotx, tdi->oldrot, rot[0]);
 
2556
                                        add_tdi_poin(tdi->roty, tdi->oldrot+1, rot[1]);
 
2557
                                        add_tdi_poin(tdi->rotz, tdi->oldrot+2, rot[2]);
1744
2558
                                }
1745
2559
                                else {
1746
 
                                        VecSubf(rot, eul, td->ext->drot);
 
2560
                                        Mat3MulMat3(totmat, mat, td->mtx);
 
2561
                                        Mat3MulMat3(smat, td->smtx, totmat);
 
2562
                                        
 
2563
                                        /* calculate the total rotatation in eulers */
 
2564
                                        VecAddf(eul, td->ext->irot, td->ext->drot); /* we have to correct for delta rot */
 
2565
                                        EulToMat3(eul, obmat);
 
2566
                                        /* mat = transform, obmat = object rotation */
 
2567
                                        Mat3MulMat3(fmat, smat, obmat);
 
2568
                                        
 
2569
                                        Mat3ToCompatibleEul(fmat, eul, td->ext->irot);
 
2570
                                        
 
2571
                                        /* correct back for delta rot */
 
2572
                                        VecSubf(eul, eul, td->ext->drot);
 
2573
                                        
 
2574
                                        /* and apply */
 
2575
                                        protectedRotateBits(td->protectflag, eul, td->ext->irot);
 
2576
                                        VECCOPY(td->ext->rot, eul);
1747
2577
                                }
1748
 
                                
1749
 
                                VecMulf(rot, (float)(9.0/M_PI_2));
1750
 
                                VecSubf(rot, rot, tdi->oldrot);
1751
 
                                
1752
 
                                protectedRotateBits(td->protectflag, rot, tdi->oldrot);
1753
 
                                
1754
 
                                add_tdi_poin(tdi->rotx, tdi->oldrot, rot[0]);
1755
 
                                add_tdi_poin(tdi->roty, tdi->oldrot+1, rot[1]);
1756
 
                                add_tdi_poin(tdi->rotz, tdi->oldrot+2, rot[2]);
1757
 
                        }
1758
 
                        else {
1759
 
                                Mat3MulMat3(totmat, mat, td->mtx);
1760
 
                                Mat3MulMat3(smat, td->smtx, totmat);
1761
 
                                
1762
 
                                /* calculate the total rotatation in eulers */
1763
 
                                VecAddf(eul, td->ext->irot, td->ext->drot); /* we have to correct for delta rot */
1764
 
                                EulToMat3(eul, obmat);
1765
 
                                /* mat = transform, obmat = object rotation */
1766
 
                                Mat3MulMat3(fmat, smat, obmat);
1767
 
                                Mat3ToEul(fmat, eul);
1768
 
                                compatible_eul(eul, td->ext->irot);
1769
 
                                
1770
 
                                /* correct back for delta rot */
1771
 
                                VecSubf(eul, eul, td->ext->drot);
1772
 
                                
1773
 
                                /* and apply */
1774
 
                                protectedRotateBits(td->protectflag, eul, td->ext->irot);
1775
 
                                VECCOPY(td->ext->rot, eul);
1776
 
                        }
 
2578
                        }
 
2579
                        
 
2580
                        constraintRotLim(t, td);
1777
2581
                }
1778
2582
        }
1779
2583
}
1788
2592
        if (t->around == V3D_LOCAL) {
1789
2593
                VECCOPY(center, t->center);
1790
2594
        }
 
2595
        else {
 
2596
                center[0] = center[1] = center[2] = 0.0f;
 
2597
        }
1791
2598
 
1792
2599
        VecRotToMat3(axis, angle, mat);
1793
 
 
 
2600
        
1794
2601
        for(i = 0 ; i < t->total; i++, td++) {
1795
2602
 
1796
2603
                if (td->flag & TD_NOACTION)
1797
2604
                        break;
 
2605
 
 
2606
                if (td->flag & TD_SKIP)
 
2607
                        continue;
1798
2608
                
1799
2609
                /* local constraint shouldn't alter center */
1800
2610
                if (t->around == V3D_LOCAL) {
1827
2637
 
1828
2638
int Rotation(TransInfo *t, short mval[2]) 
1829
2639
{
1830
 
        TransData *td = t->data;
1831
 
        char str[50];
 
2640
        char str[64];
1832
2641
 
1833
2642
        float final;
1834
2643
 
1835
 
        int dx2 = t->center2d[0] - mval[0];
1836
 
        int dy2 = t->center2d[1] - mval[1];
1837
 
        double B = sqrt(dx2*dx2+dy2*dy2);
1838
 
 
1839
 
        int dx1 = t->center2d[0] - t->imval[0];
1840
 
        int dy1 = t->center2d[1] - t->imval[1];
1841
 
        double A = sqrt(dx1*dx1+dy1*dy1);
1842
 
 
1843
 
        int dx3 = mval[0] - t->imval[0];
1844
 
        int dy3 = mval[1] - t->imval[1];
1845
 
                /* use doubles here, to make sure a "1.0" (no rotation) doesnt become 9.999999e-01, which gives 0.02 for acos */
1846
 
        double deler= ((double)((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3) ))
1847
 
                / (2.0 * (A*B?A*B:1.0));
1848
 
        /* (A*B?A*B:1.0f) this takes care of potential divide by zero errors */
1849
 
 
1850
 
        float dphi;
1851
 
 
1852
2644
        float axis[3];
1853
2645
        float mat[3][3];
1854
2646
 
1855
2647
        VECCOPY(axis, t->viewinv[2]);
1856
2648
        VecMulf(axis, -1.0f);
1857
 
        Normalise(axis);
1858
 
 
1859
 
        dphi = saacos((float)deler);
1860
 
        if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
1861
 
 
1862
 
        if(G.qual & LR_SHIFTKEY) t->fac += dphi/30.0f;
1863
 
        else t->fac += dphi;
1864
 
 
1865
 
        /*
1866
 
        clamping angle between -2 PI and 2 PI (not sure if useful so commented out - theeth)
1867
 
        if (t->fac >= 2 * M_PI)
1868
 
                t->fac -= 2 * M_PI;
1869
 
        else if (t->fac <= -2 * M_PI)
1870
 
                t->fac -= -2 * M_PI;
1871
 
        */
 
2649
        Normalize(axis);
 
2650
 
 
2651
        t->fac += InputDeltaAngle(t, mval);
1872
2652
 
1873
2653
        final = t->fac;
1874
2654
 
 
2655
        applyNDofInput(&t->ndof, &final);
 
2656
        
1875
2657
        snapGrid(t, &final);
1876
2658
 
1877
 
        t->imval[0] = mval[0];
1878
 
        t->imval[1] = mval[1];
1879
 
 
1880
2659
        if (t->con.applyRot) {
1881
2660
                t->con.applyRot(t, NULL, axis);
1882
2661
        }
 
2662
        
 
2663
        applySnapping(t, &final);
1883
2664
 
1884
2665
        if (hasNumInput(&t->num)) {
1885
2666
                char c[20];
1888
2669
 
1889
2670
                outputNumInput(&(t->num), c);
1890
2671
 
1891
 
                sprintf(str, "Rot: %s %s", &c[0], t->proptext);
 
2672
                sprintf(str, "Rot: %s %s %s", &c[0], t->con.text, t->proptext);
 
2673
 
 
2674
                /* Clamp between -180 and 180 */
 
2675
                while (final >= 180.0)
 
2676
                        final -= 360.0;
 
2677
                
 
2678
                while (final <= -180.0)
 
2679
                        final += 360.0;
1892
2680
 
1893
2681
                final *= (float)(M_PI / 180.0);
1894
2682
        }
1896
2684
                sprintf(str, "Rot: %.2f%s %s", 180.0*final/M_PI, t->con.text, t->proptext);
1897
2685
        }
1898
2686
 
1899
 
        VecRotToMat3(axis, final * td->factor, mat);
 
2687
        VecRotToMat3(axis, final, mat);
1900
2688
 
1901
2689
        t->val = final;                         // used in manipulator
1902
2690
        Mat3CpyMat3(t->mat, mat);       // used in manipulator
1919
2707
 
1920
2708
void initTrackball(TransInfo *t) 
1921
2709
{
 
2710
        t->mode = TFM_TRACKBALL;
 
2711
        t->transform = Trackball;
 
2712
        
 
2713
        t->ndof.axis = 40;
 
2714
        /* Scale down input for rotation */
 
2715
        t->ndof.factor[0] = 0.2f;
 
2716
        t->ndof.factor[1] = 0.2f;
 
2717
 
1922
2718
        t->idx_max = 1;
1923
2719
        t->num.idx_max = 1;
1924
2720
        t->snap[0] = 0.0f;
1925
2721
        t->snap[1] = (float)((5.0/180)*M_PI);
1926
2722
        t->snap[2] = t->snap[1] * 0.2f;
1927
2723
        t->fac = 0;
1928
 
        t->transform = Trackball;
1929
2724
        
1930
 
        t->flag |= T_NO_CONSTRAINT; /* making sure the flag is always set */
 
2725
        t->flag |= T_NO_CONSTRAINT;
1931
2726
}
1932
2727
 
1933
2728
static void applyTrackball(TransInfo *t, float axis1[3], float axis2[3], float angles[2])
1934
2729
{
1935
2730
        TransData *td = t->data;
1936
2731
        float mat[3][3], smat[3][3], totmat[3][3];
 
2732
        float center[3];
1937
2733
        int i;
1938
2734
 
1939
2735
        VecRotToMat3(axis1, angles[0], smat);
1944
2740
        for(i = 0 ; i < t->total; i++, td++) {
1945
2741
                if (td->flag & TD_NOACTION)
1946
2742
                        break;
 
2743
 
 
2744
                if (td->flag & TD_SKIP)
 
2745
                        continue;
 
2746
                
 
2747
                VECCOPY(center, t->center);
1947
2748
                
1948
2749
                if (t->around == V3D_LOCAL) {
1949
 
                        if (t->flag & T_OBJECT)
1950
 
                                VECCOPY(t->center, td->center); // not supported in editmode yet
 
2750
                        /* local-mode shouldn't change center */
 
2751
                        if (t->flag & (T_OBJECT|T_POSE)) {
 
2752
                                VECCOPY(t->center, td->center);
 
2753
                        }
 
2754
                        else {
 
2755
                                if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE)) {
 
2756
                                        VECCOPY(t->center, td->center);
 
2757
                                }
 
2758
                        }
1951
2759
                }
1952
2760
                
1953
2761
                if (t->flag & T_PROP_EDIT) {
1956
2764
                        
1957
2765
                        Mat3MulMat3(mat, smat, totmat);
1958
2766
                }
1959
 
 
 
2767
                
1960
2768
                ElementRotation(t, td, mat);
 
2769
                
 
2770
                VECCOPY(t->center, center);
1961
2771
        }
1962
2772
}
1963
2773
 
1964
2774
int Trackball(TransInfo *t, short mval[2]) 
1965
2775
{
1966
 
        char str[80];
 
2776
        char str[128];
1967
2777
        float axis1[3], axis2[3];
1968
2778
        float mat[3][3], totmat[3][3], smat[3][3];
1969
2779
        float phi[2];
1970
2780
        
1971
2781
        VECCOPY(axis1, t->persinv[0]);
1972
2782
        VECCOPY(axis2, t->persinv[1]);
1973
 
        Normalise(axis1);
1974
 
        Normalise(axis2);
 
2783
        Normalize(axis1);
 
2784
        Normalize(axis2);
1975
2785
        
1976
2786
        /* factore has to become setting or so */
1977
2787
        phi[0]= 0.01f*(float)( t->imval[1] - mval[1] );
1978
2788
        phi[1]= 0.01f*(float)( mval[0] - t->imval[0] );
1979
 
        
1980
 
        //if(G.qual & LR_SHIFTKEY) t->fac += dphi/30.0f;
1981
 
        //else t->fac += dphi;
 
2789
                
 
2790
        applyNDofInput(&t->ndof, phi);
1982
2791
        
1983
2792
        snapGrid(t, phi);
1984
2793
        
1996
2805
        }
1997
2806
        else {
1998
2807
                sprintf(str, "Trackball: %.2f %.2f %s", 180.0*phi[0]/M_PI, 180.0*phi[1]/M_PI, t->proptext);
 
2808
        
 
2809
                if(t->flag & T_SHIFT_MOD) {
 
2810
                        if(phi[0] != 0.0) phi[0]/= 5.0f;
 
2811
                        if(phi[1] != 0.0) phi[1]/= 5.0f;
 
2812
                }
1999
2813
        }
2000
 
        
 
2814
 
2001
2815
        VecRotToMat3(axis1, phi[0], smat);
2002
2816
        VecRotToMat3(axis2, phi[1], totmat);
2003
2817
        
2022
2836
        
2023
2837
void initTranslation(TransInfo *t) 
2024
2838
{
 
2839
        t->mode = TFM_TRANSLATION;
 
2840
        t->transform = Translation;
 
2841
 
2025
2842
        t->idx_max = (t->flag & T_2D_EDIT)? 1: 2;
 
2843
        t->num.flag = 0;
2026
2844
        t->num.idx_max = t->idx_max;
2027
 
        t->transform = Translation;
2028
2845
        
 
2846
        t->ndof.axis = 7;
 
2847
 
2029
2848
        if(t->spacetype == SPACE_VIEW3D) {
2030
2849
                /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d() */
2031
2850
                if(t->flag & (T_EDIT|T_POSE)) {
2036
2855
                        Mat4MulVecfl(ob->obmat, vec);
2037
2856
                        initgrabz(vec[0], vec[1], vec[2]);
2038
2857
                }
2039
 
                else initgrabz(t->center[0], t->center[1], t->center[2]); 
 
2858
                else {
 
2859
                        initgrabz(t->center[0], t->center[1], t->center[2]);
 
2860
                } 
2040
2861
 
2041
2862
                t->snap[0] = 0.0f;
2042
2863
                t->snap[1] = G.vd->gridview * 1.0f;
2056
2877
static void headerTranslation(TransInfo *t, float vec[3], char *str) {
2057
2878
        char tvec[60];
2058
2879
        char distvec[20];
 
2880
        char autoik[20];
2059
2881
        float dvec[3];
2060
2882
        float dist;
2061
2883
        
2076
2898
                sprintf(distvec, "%.4e", dist);
2077
2899
        else
2078
2900
                sprintf(distvec, "%.4f", dist);
 
2901
                
 
2902
        if(t->flag & T_AUTOIK) {
 
2903
                short chainlen= G.scene->toolsettings->autoik_chainlen;
 
2904
                
 
2905
                if(chainlen)
 
2906
                        sprintf(autoik, "AutoIK-Len: %d", chainlen);
 
2907
                else
 
2908
                        strcpy(autoik, "");
 
2909
        }
 
2910
        else
 
2911
                strcpy(autoik, "");
2079
2912
 
2080
2913
        if (t->con.mode & CON_APPLY) {
2081
2914
                switch(t->num.idx_max) {
2082
2915
                case 0:
2083
 
                        sprintf(str, "D: %s (%s)%s %s", &tvec[0], distvec, t->con.text, t->proptext);
 
2916
                        sprintf(str, "D: %s (%s)%s %s  %s", &tvec[0], distvec, t->con.text, t->proptext, &autoik[0]);
2084
2917
                        break;
2085
2918
                case 1:
2086
 
                        sprintf(str, "D: %s   D: %s (%s)%s %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext);
 
2919
                        sprintf(str, "D: %s   D: %s (%s)%s %s  %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext, &autoik[0]);
2087
2920
                        break;
2088
2921
                case 2:
2089
 
                        sprintf(str, "D: %s   D: %s  D: %s (%s)%s %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext);
 
2922
                        sprintf(str, "D: %s   D: %s  D: %s (%s)%s %s  %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoik[0]);
2090
2923
                }
2091
2924
        }
2092
2925
        else {
2093
2926
                if(t->flag & T_2D_EDIT)
2094
2927
                        sprintf(str, "Dx: %s   Dy: %s (%s)%s %s", &tvec[0], &tvec[20], distvec, t->con.text, t->proptext);
2095
2928
                else
2096
 
                        sprintf(str, "Dx: %s   Dy: %s  Dz: %s (%s)%s %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext);
 
2929
                        sprintf(str, "Dx: %s   Dy: %s  Dz: %s (%s)%s %s  %s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoik[0]);
2097
2930
        }
2098
2931
}
2099
2932
 
2105
2938
        for(i = 0 ; i < t->total; i++, td++) {
2106
2939
                if (td->flag & TD_NOACTION)
2107
2940
                        break;
2108
 
 
 
2941
                
 
2942
                if (td->flag & TD_SKIP)
 
2943
                        continue;
 
2944
                
2109
2945
                if (t->con.applyVec) {
2110
2946
                        float pvec[3];
2111
2947
                        t->con.applyVec(t, td, vec, tvec, pvec);
2113
2949
                else {
2114
2950
                        VECCOPY(tvec, vec);
2115
2951
                }
2116
 
 
 
2952
                
2117
2953
                Mat3MulVecfl(td->smtx, tvec);
2118
2954
                VecMulf(tvec, td->factor);
2119
2955
                
2127
2963
                        add_tdi_poin(tdi->locz, tdi->oldloc+2, tvec[2]);
2128
2964
                }
2129
2965
                else VecAddf(td->loc, td->iloc, tvec);
 
2966
                
 
2967
                constraintTransLim(t, td);
2130
2968
        }
2131
2969
}
2132
2970
 
2134
2972
int Translation(TransInfo *t, short mval[2]) 
2135
2973
{
2136
2974
        float tvec[3];
2137
 
        char str[200];
 
2975
        char str[250];
2138
2976
        
2139
2977
        if(t->flag & T_SHIFT_MOD) {
2140
2978
                float dvec[3];
2148
2986
 
2149
2987
        if (t->con.mode & CON_APPLY) {
2150
2988
                float pvec[3] = {0.0f, 0.0f, 0.0f};
 
2989
                applySnapping(t, t->vec);
2151
2990
                t->con.applyVec(t, NULL, t->vec, tvec, pvec);
2152
2991
                VECCOPY(t->vec, tvec);
2153
2992
                headerTranslation(t, pvec, str);
2154
2993
        }
2155
2994
        else {
 
2995
                applyNDofInput(&t->ndof, t->vec);
2156
2996
                snapGrid(t, t->vec);
2157
2997
                applyNumInput(&t->num, t->vec);
 
2998
                applySnapping(t, t->vec);
2158
2999
                headerTranslation(t, t->vec, str);
2159
3000
        }
2160
 
 
 
3001
        
2161
3002
        applyTranslation(t, t->vec);
2162
3003
 
2163
3004
        /* evil hack - redo translation if cliiping needeed */
2167
3008
        recalcData(t);
2168
3009
 
2169
3010
        headerprint(str);
2170
 
 
 
3011
        
2171
3012
        viewRedrawForce(t);
2172
3013
 
 
3014
        drawSnapping(t);
 
3015
 
2173
3016
        return 1;
2174
3017
}
2175
3018
 
2177
3020
 
2178
3021
void initShrinkFatten(TransInfo *t) 
2179
3022
{
 
3023
        // If not in mesh edit mode, fallback to Resize
2180
3024
        if (G.obedit==NULL || G.obedit->type != OB_MESH) {
2181
 
                initTransModeFlags(t, TFM_RESIZE);
2182
3025
                initResize(t);
2183
 
                return;
2184
 
        }
2185
 
 
2186
 
        t->idx_max = 0;
2187
 
        t->num.idx_max = 0;
2188
 
        t->snap[0] = 0.0f;
2189
 
        t->snap[1] = 1.0f;
2190
 
        t->snap[2] = t->snap[1] * 0.1f;
2191
 
        t->transform = ShrinkFatten;
 
3026
        }
 
3027
        else {
 
3028
                t->mode = TFM_SHRINKFATTEN;
 
3029
                t->transform = ShrinkFatten;
 
3030
        
 
3031
                t->idx_max = 0;
 
3032
                t->num.idx_max = 0;
 
3033
                t->snap[0] = 0.0f;
 
3034
                t->snap[1] = 1.0f;
 
3035
                t->snap[2] = t->snap[1] * 0.1f;
 
3036
                
 
3037
                t->flag |= T_NO_CONSTRAINT;
 
3038
        }
2192
3039
}
2193
3040
 
2194
3041
 
2198
3045
        float vec[3];
2199
3046
        float distance;
2200
3047
        int i;
2201
 
        char str[50];
 
3048
        char str[64];
2202
3049
        TransData *td = t->data;
2203
3050
 
2204
3051
        distance = -InputVerticalAbsolute(t, mval);
2225
3072
                if (td->flag & TD_NOACTION)
2226
3073
                        break;
2227
3074
 
 
3075
                if (td->flag & TD_SKIP)
 
3076
                        continue;
 
3077
 
2228
3078
                VECCOPY(vec, td->axismtx[2]);
2229
3079
                VecMulf(vec, distance);
2230
3080
                VecMulf(vec, td->factor);
2245
3095
 
2246
3096
void initTilt(TransInfo *t) 
2247
3097
{
2248
 
        t->idx_max = 0;
2249
 
        t->num.idx_max = 0;
2250
 
        t->snap[0] = 0.0f;
2251
 
        t->snap[1] = (float)((5.0/180)*M_PI);
2252
 
        t->snap[2] = t->snap[1] * 0.2f;
2253
 
        t->fac = 0;
 
3098
        t->mode = TFM_TILT;
2254
3099
        t->transform = Tilt;
 
3100
 
 
3101
        t->ndof.axis = 16;
 
3102
        /* Scale down and flip input for rotation */
 
3103
        t->ndof.factor[0] = -0.2f;
 
3104
 
 
3105
        t->idx_max = 0;
 
3106
        t->num.idx_max = 0;
 
3107
        t->snap[0] = 0.0f;
 
3108
        t->snap[1] = (float)((5.0/180)*M_PI);
 
3109
        t->snap[2] = t->snap[1] * 0.2f;
 
3110
        t->fac = 0;
 
3111
        
 
3112
        t->flag |= T_NO_CONSTRAINT;
2255
3113
}
2256
3114
 
2257
3115
 
2264
3122
 
2265
3123
        float final;
2266
3124
 
2267
 
        int dx2 = t->center2d[0] - mval[0];
2268
 
        int dy2 = t->center2d[1] - mval[1];
2269
 
        float B = (float)sqrt(dx2*dx2+dy2*dy2);
2270
 
 
2271
 
        int dx1 = t->center2d[0] - t->imval[0];
2272
 
        int dy1 = t->center2d[1] - t->imval[1];
2273
 
        float A = (float)sqrt(dx1*dx1+dy1*dy1);
2274
 
 
2275
 
        int dx3 = mval[0] - t->imval[0];
2276
 
        int dy3 = mval[1] - t->imval[1];
2277
 
 
2278
 
        float deler= ((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3))
2279
 
                / (2 * A * B);
2280
 
 
2281
 
        float dphi;
2282
 
 
2283
 
        dphi = saacos(deler);
2284
 
        if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
2285
 
 
2286
 
        if(G.qual & LR_SHIFTKEY) t->fac += dphi/30.0f;
2287
 
        else t->fac += dphi;
 
3125
        t->fac += InputDeltaAngle(t, mval);
2288
3126
 
2289
3127
        final = t->fac;
 
3128
        
 
3129
        applyNDofInput(&t->ndof, &final);
2290
3130
 
2291
3131
        snapGrid(t, &final);
2292
3132
 
2293
 
        t->imval[0] = mval[0];
2294
 
        t->imval[1] = mval[1];
2295
 
 
2296
3133
        if (hasNumInput(&t->num)) {
2297
3134
                char c[20];
2298
3135
 
2312
3149
                if (td->flag & TD_NOACTION)
2313
3150
                        break;
2314
3151
 
 
3152
                if (td->flag & TD_SKIP)
 
3153
                        continue;
 
3154
 
2315
3155
                if (td->val) {
2316
3156
                        *td->val = td->ival + final * td->factor;
2317
3157
                }
2328
3168
        return 1;
2329
3169
}
2330
3170
 
 
3171
 
 
3172
/* ******************** Curve Shrink/Fatten *************** */
 
3173
 
 
3174
int CurveShrinkFatten(TransInfo *t, short mval[2]) 
 
3175
{
 
3176
        TransData *td = t->data;
 
3177
        float ratio;
 
3178
        int i;
 
3179
        char str[50];
 
3180
        
 
3181
        if(t->flag & T_SHIFT_MOD) {
 
3182
                /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
 
3183
                float dx= (float)(t->center2d[0] - t->shiftmval[0]);
 
3184
                float dy= (float)(t->center2d[1] - t->shiftmval[1]);
 
3185
                ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
 
3186
                
 
3187
                dx= (float)(t->center2d[0] - mval[0]);
 
3188
                dy= (float)(t->center2d[1] - mval[1]);
 
3189
                ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio);
 
3190
                
 
3191
        }
 
3192
        else {
 
3193
                float dx= (float)(t->center2d[0] - mval[0]);
 
3194
                float dy= (float)(t->center2d[1] - mval[1]);
 
3195
                ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
 
3196
        }
 
3197
        
 
3198
        snapGrid(t, &ratio);
 
3199
        
 
3200
        applyNumInput(&t->num, &ratio);
 
3201
        
 
3202
        /* header print for NumInput */
 
3203
        if (hasNumInput(&t->num)) {
 
3204
                char c[20];
 
3205
                
 
3206
                outputNumInput(&(t->num), c);
 
3207
                sprintf(str, "Shrink/Fatten: %s", c);
 
3208
        }
 
3209
        else {
 
3210
                sprintf(str, "Shrink/Fatten: %3f", ratio);
 
3211
        }
 
3212
        
 
3213
        for(i = 0 ; i < t->total; i++, td++) {
 
3214
                if (td->flag & TD_NOACTION)
 
3215
                        break;
 
3216
 
 
3217
                if (td->flag & TD_SKIP)
 
3218
                        continue;
 
3219
                
 
3220
                if(td->val) {
 
3221
                        //*td->val= ratio;
 
3222
                        *td->val= td->ival*ratio;
 
3223
                        if (*td->val <= 0.0f) *td->val = 0.0001f;
 
3224
                }
 
3225
        }
 
3226
        
 
3227
        recalcData(t);
 
3228
        
 
3229
        headerprint(str);
 
3230
        
 
3231
        viewRedrawForce(t);
 
3232
        
 
3233
        if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
 
3234
        
 
3235
        return 1;
 
3236
}
 
3237
 
 
3238
void initCurveShrinkFatten(TransInfo *t)
 
3239
{
 
3240
        t->mode = TFM_CURVE_SHRINKFATTEN;
 
3241
        t->transform = CurveShrinkFatten;
 
3242
        
 
3243
        t->idx_max = 0;
 
3244
        t->num.idx_max = 0;
 
3245
        t->snap[0] = 0.0f;
 
3246
        t->snap[1] = 0.1f;
 
3247
        t->snap[2] = t->snap[1] * 0.1f;
 
3248
        
 
3249
        t->flag |= T_NO_CONSTRAINT;
 
3250
 
 
3251
        t->fac = (float)sqrt( (
 
3252
                   ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
 
3253
                   +
 
3254
                   ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
 
3255
                   ) );
 
3256
}
 
3257
 
2331
3258
/* ************************** PUSH/PULL *************************** */
2332
3259
 
2333
3260
void initPushPull(TransInfo *t) 
2334
3261
{
2335
 
        t->idx_max = 0;
2336
 
        t->num.idx_max = 0;
2337
 
        t->snap[0] = 0.0f;
2338
 
        t->snap[1] = 1.0f;
2339
 
        t->snap[2] = t->snap[1] * 0.1f;
 
3262
        t->mode = TFM_PUSHPULL;
2340
3263
        t->transform = PushPull;
 
3264
        
 
3265
        t->ndof.axis = 4;
 
3266
        /* Flip direction */
 
3267
        t->ndof.factor[0] = -1.0f;
 
3268
 
 
3269
        t->idx_max = 0;
 
3270
        t->num.idx_max = 0;
 
3271
        t->snap[0] = 0.0f;
 
3272
        t->snap[1] = 1.0f;
 
3273
        t->snap[2] = t->snap[1] * 0.1f;
2341
3274
}
2342
3275
 
2343
3276
 
2344
 
 
2345
3277
int PushPull(TransInfo *t, short mval[2]) 
2346
3278
{
2347
3279
        float vec[3], axis[3];
2348
3280
        float distance;
2349
3281
        int i;
2350
 
        char str[50];
 
3282
        char str[128];
2351
3283
        TransData *td = t->data;
2352
3284
 
2353
3285
        distance = InputVerticalAbsolute(t, mval);
 
3286
        
 
3287
        applyNDofInput(&t->ndof, &distance);
2354
3288
 
2355
3289
        snapGrid(t, &distance);
2356
3290
 
2377
3311
                if (td->flag & TD_NOACTION)
2378
3312
                        break;
2379
3313
 
 
3314
                if (td->flag & TD_SKIP)
 
3315
                        continue;
 
3316
 
2380
3317
                VecSubf(vec, t->center, td->center);
2381
3318
                if (t->con.applyRot && t->con.mode & CON_APPLY) {
2382
3319
                        t->con.applyRot(t, td, axis);
2389
3326
                                Projf(vec, vec, axis);
2390
3327
                        }
2391
3328
                }
2392
 
                Normalise(vec);
 
3329
                Normalize(vec);
2393
3330
                VecMulf(vec, distance);
2394
3331
                VecMulf(vec, td->factor);
2395
3332
 
2405
3342
        return 1;
2406
3343
}
2407
3344
 
 
3345
/* ************************** BEVEL **************************** */
 
3346
 
 
3347
void initBevel(TransInfo *t) 
 
3348
{
 
3349
        t->mode = TFM_BEVEL;
 
3350
        t->flag |= T_NO_CONSTRAINT;
 
3351
        t->transform = Bevel;
 
3352
        t->handleEvent = handleEventBevel;
 
3353
        if (G.editBMesh->imval[0] == 0 && G.editBMesh->imval[1] == 0) {
 
3354
                /* save the initial mouse co */
 
3355
                G.editBMesh->imval[0] = t->imval[0];
 
3356
                G.editBMesh->imval[1] = t->imval[1];
 
3357
        }
 
3358
        else {
 
3359
                /* restore the mouse co from a previous call to initTransform() */
 
3360
                t->imval[0] = G.editBMesh->imval[0];
 
3361
                t->imval[1] = G.editBMesh->imval[1];
 
3362
        }
 
3363
}
 
3364
 
 
3365
int handleEventBevel(TransInfo *t, unsigned short event, short val)
 
3366
{
 
3367
        if (val) {
 
3368
                if(!G.editBMesh) return 0;
 
3369
 
 
3370
                switch (event) {
 
3371
                case MIDDLEMOUSE:
 
3372
                        G.editBMesh->options ^= BME_BEVEL_VERT;
 
3373
                        t->state = TRANS_CANCEL;
 
3374
                        return 1;
 
3375
                //case PADPLUSKEY:
 
3376
                //      G.editBMesh->options ^= BME_BEVEL_RES;
 
3377
                //      G.editBMesh->res += 1;
 
3378
                //      if (G.editBMesh->res > 4) {
 
3379
                //              G.editBMesh->res = 4;
 
3380
                //      }
 
3381
                //      t->state = TRANS_CANCEL;
 
3382
                //      return 1;
 
3383
                //case PADMINUS:
 
3384
                //      G.editBMesh->options ^= BME_BEVEL_RES;
 
3385
                //      G.editBMesh->res -= 1;
 
3386
                //      if (G.editBMesh->res < 0) {
 
3387
                //              G.editBMesh->res = 0;
 
3388
                //      }
 
3389
                //      t->state = TRANS_CANCEL;
 
3390
                //      return 1;
 
3391
                default:
 
3392
                        return 0;
 
3393
                }
 
3394
        }
 
3395
        return 0;
 
3396
}
 
3397
 
 
3398
int Bevel(TransInfo *t, short mval[2])
 
3399
{
 
3400
        float distance,d;
 
3401
        int i;
 
3402
        char str[128];
 
3403
        char *mode;
 
3404
        TransData *td = t->data;
 
3405
 
 
3406
        mode = (G.editBMesh->options & BME_BEVEL_VERT) ? "verts only" : "normal";
 
3407
        distance = InputHorizontalAbsolute(t, mval)/4; /* 4 just seemed a nice value to me, nothing special */
 
3408
 
 
3409
        applyNumInput(&t->num, &distance);
 
3410
 
 
3411
        /* header print for NumInput */
 
3412
        if (hasNumInput(&t->num)) {
 
3413
                char c[20];
 
3414
 
 
3415
                outputNumInput(&(t->num), c);
 
3416
 
 
3417
                sprintf(str, "Bevel: %s", c);
 
3418
        }
 
3419
        else {
 
3420
                /* default header print */
 
3421
                sprintf(str, "Bevel - Dist: %.4f, Mode: %s (MMB to toggle))", distance, mode);
 
3422
        }
 
3423
        
 
3424
        if (distance < 0) distance = -distance;
 
3425
        for(i = 0 ; i < t->total; i++, td++) {
 
3426
                if (td->axismtx[1][0] > 0 && distance > td->axismtx[1][0]) {
 
3427
                        d = td->axismtx[1][0];
 
3428
                }
 
3429
                else {
 
3430
                        d = distance;
 
3431
                }
 
3432
                VECADDFAC(td->loc,td->center,td->axismtx[0],(*td->val)*d);
 
3433
        }
 
3434
 
 
3435
        recalcData(t);
 
3436
 
 
3437
        headerprint(str);
 
3438
 
 
3439
        viewRedrawForce(t);
 
3440
 
 
3441
        return 1;
 
3442
}
 
3443
 
 
3444
/* ************************** BEVEL WEIGHT *************************** */
 
3445
 
 
3446
void initBevelWeight(TransInfo *t) 
 
3447
{
 
3448
        t->mode = TFM_BWEIGHT;
 
3449
        t->transform = BevelWeight;
 
3450
        
 
3451
        t->idx_max = 0;
 
3452
        t->num.idx_max = 0;
 
3453
        t->snap[0] = 0.0f;
 
3454
        t->snap[1] = 0.1f;
 
3455
        t->snap[2] = t->snap[1] * 0.1f;
 
3456
        
 
3457
        t->flag |= T_NO_CONSTRAINT;
 
3458
 
 
3459
        t->fac = (float)sqrt(
 
3460
                (
 
3461
                        ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
 
3462
                +
 
3463
                        ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
 
3464
                ) );
 
3465
 
 
3466
        if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
 
3467
}
 
3468
 
 
3469
int BevelWeight(TransInfo *t, short mval[2]) 
 
3470
{
 
3471
        TransData *td = t->data;
 
3472
        float weight;
 
3473
        int i;
 
3474
        char str[50];
 
3475
 
 
3476
                
 
3477
        if(t->flag & T_SHIFT_MOD) {
 
3478
                /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
 
3479
                float dx= (float)(t->center2d[0] - t->shiftmval[0]);
 
3480
                float dy= (float)(t->center2d[1] - t->shiftmval[1]);
 
3481
                weight = (float)sqrt( dx*dx + dy*dy)/t->fac;
 
3482
                
 
3483
                dx= (float)(t->center2d[0] - mval[0]);
 
3484
                dy= (float)(t->center2d[1] - mval[1]);
 
3485
                weight+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -weight);
 
3486
                
 
3487
        }
 
3488
        else {
 
3489
                float dx= (float)(t->center2d[0] - mval[0]);
 
3490
                float dy= (float)(t->center2d[1] - mval[1]);
 
3491
                weight = (float)sqrt( dx*dx + dy*dy)/t->fac;
 
3492
        }
 
3493
 
 
3494
        weight -= 1.0f;
 
3495
        if (weight > 1.0f) weight = 1.0f;
 
3496
 
 
3497
        snapGrid(t, &weight);
 
3498
 
 
3499
        applyNumInput(&t->num, &weight);
 
3500
 
 
3501
        /* header print for NumInput */
 
3502
        if (hasNumInput(&t->num)) {
 
3503
                char c[20];
 
3504
 
 
3505
                outputNumInput(&(t->num), c);
 
3506
 
 
3507
                if (weight >= 0.0f)
 
3508
                        sprintf(str, "Bevel Weight: +%s %s", c, t->proptext);
 
3509
                else
 
3510
                        sprintf(str, "Bevel Weight: %s %s", c, t->proptext);
 
3511
        }
 
3512
        else {
 
3513
                /* default header print */
 
3514
                if (weight >= 0.0f)
 
3515
                        sprintf(str, "Bevel Weight: +%.3f %s", weight, t->proptext);
 
3516
                else
 
3517
                        sprintf(str, "Bevel Weight: %.3f %s", weight, t->proptext);
 
3518
        }
 
3519
        
 
3520
        for(i = 0 ; i < t->total; i++, td++) {
 
3521
                if (td->flag & TD_NOACTION)
 
3522
                        break;
 
3523
 
 
3524
                if (td->val) {
 
3525
                        *td->val = td->ival + weight * td->factor;
 
3526
                        if (*td->val < 0.0f) *td->val = 0.0f;
 
3527
                        if (*td->val > 1.0f) *td->val = 1.0f;
 
3528
                }
 
3529
        }
 
3530
 
 
3531
        recalcData(t);
 
3532
 
 
3533
        headerprint(str);
 
3534
 
 
3535
        viewRedrawForce(t);
 
3536
 
 
3537
        helpline (t, t->center);
 
3538
 
 
3539
        return 1;
 
3540
}
 
3541
 
2408
3542
/* ************************** CREASE *************************** */
2409
3543
 
2410
3544
void initCrease(TransInfo *t) 
2411
3545
{
2412
 
        t->idx_max = 0;
2413
 
        t->num.idx_max = 0;
2414
 
        t->snap[0] = 0.0f;
2415
 
        t->snap[1] = 0.1f;
2416
 
        t->snap[2] = t->snap[1] * 0.1f;
 
3546
        t->mode = TFM_CREASE;
2417
3547
        t->transform = Crease;
 
3548
        
 
3549
        t->idx_max = 0;
 
3550
        t->num.idx_max = 0;
 
3551
        t->snap[0] = 0.0f;
 
3552
        t->snap[1] = 0.1f;
 
3553
        t->snap[2] = t->snap[1] * 0.1f;
 
3554
        
 
3555
        t->flag |= T_NO_CONSTRAINT;
 
3556
 
2418
3557
        t->fac = (float)sqrt(
2419
3558
                (
2420
3559
                        ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
2480
3619
                if (td->flag & TD_NOACTION)
2481
3620
                        break;
2482
3621
 
 
3622
                if (td->flag & TD_SKIP)
 
3623
                        continue;
 
3624
 
2483
3625
                if (td->val) {
2484
3626
                        *td->val = td->ival + crease * td->factor;
2485
3627
                        if (*td->val < 0.0f) *td->val = 0.0f;
2498
3640
        return 1;
2499
3641
}
2500
3642
 
2501
 
/* ************************** MIRROR *************************** */
2502
 
 
2503
 
void Mirror(short mode) 
2504
 
{
2505
 
        TransData *td;
2506
 
        float mati[3][3], matview[3][3], mat[3][3];
2507
 
        float size[3];
2508
 
        int i;
2509
 
 
2510
 
        Trans.context = CTX_NO_PET;
2511
 
 
2512
 
        initTrans(&Trans);              // internal data, mouse, vectors
2513
 
 
2514
 
        Mat3One(mati);
2515
 
        Mat3CpyMat4(matview, Trans.viewinv); // t->viewinv was set in initTrans
2516
 
        Mat3Ortho(matview);
2517
 
 
2518
 
        initTransModeFlags(&Trans, TFM_MIRROR); // modal settings in struct Trans
2519
 
 
2520
 
        createTransData(&Trans);        // make TransData structs from selection
2521
 
 
2522
 
        calculatePropRatio(&Trans);
2523
 
        calculateCenter(&Trans);
2524
 
 
2525
 
        initResize(&Trans);
2526
 
 
2527
 
        if (Trans.total == 0) {
2528
 
                postTrans(&Trans);
2529
 
                return;
2530
 
        }
2531
 
 
2532
 
        size[0] = size[1] = size[2] = 1.0f;
2533
 
        td = Trans.data;
2534
 
 
2535
 
        switch (mode) {
2536
 
        case 1:
2537
 
                size[0] = -1.0f;
2538
 
                setConstraint(&Trans, mati, (CON_AXIS0), "");
2539
 
                break;
2540
 
        case 2:
2541
 
                size[1] = -1.0f;
2542
 
                setConstraint(&Trans, mati, (CON_AXIS1), "");
2543
 
                break;
2544
 
        case 3:
2545
 
                size[2] = -1.0f;
2546
 
                setConstraint(&Trans, mati, (CON_AXIS2), "");
2547
 
                break;
2548
 
        case 4:
2549
 
                size[0] = -1.0f;
2550
 
                setLocalConstraint(&Trans, (CON_AXIS0), "");
2551
 
                break;
2552
 
        case 5:
2553
 
                size[1] = -1.0f;
2554
 
                setLocalConstraint(&Trans, (CON_AXIS1), "");
2555
 
                break;
2556
 
        case 6:
2557
 
                size[2] = -1.0f;
2558
 
                setLocalConstraint(&Trans, (CON_AXIS2), "");
2559
 
                break;
2560
 
        case 7:
2561
 
                size[0] = -1.0f;
2562
 
                setConstraint(&Trans, matview, (CON_AXIS0), "");
2563
 
                break;
2564
 
        case 8:
2565
 
                size[1] = -1.0f;
2566
 
                setConstraint(&Trans, matview, (CON_AXIS1), "");
2567
 
                break;
2568
 
        case 9:
2569
 
                size[2] = -1.0f;
2570
 
                setConstraint(&Trans, matview, (CON_AXIS2), "");
2571
 
                break;
2572
 
        default:
2573
 
                return;
2574
 
        }
2575
 
 
2576
 
        SizeToMat3(size, mat);
2577
 
 
2578
 
        if (Trans.con.applySize) {
2579
 
                Trans.con.applySize(&Trans, NULL, mat);
2580
 
        }
2581
 
 
2582
 
        for(i = 0 ; i < Trans.total; i++, td++) {
2583
 
                if (td->flag & TD_NOACTION)
2584
 
                        break;
2585
 
                
2586
 
                ElementResize(&Trans, td, mat);
2587
 
        }
2588
 
 
2589
 
        recalcData(&Trans);
2590
 
        
2591
 
        BIF_undo_push("Mirror");
2592
 
 
2593
 
        /* free data, reset vars */
2594
 
        postTrans(&Trans);
2595
 
 
2596
 
        /* send events out for redraws */
2597
 
        viewRedrawPost(&Trans);
2598
 
}
2599
 
 
2600
3643
/* ******************** EditBone (B-bone) width scaling *************** */
2601
3644
 
 
3645
void initBoneSize(TransInfo *t)
 
3646
{
 
3647
        t->mode = TFM_BONESIZE;
 
3648
        t->transform = BoneSize;
 
3649
        
 
3650
        t->idx_max = 2;
 
3651
        t->num.idx_max = 2;
 
3652
        t->num.flag |= NUM_NULL_ONE;
 
3653
        t->snap[0] = 0.0f;
 
3654
        t->snap[1] = 0.1f;
 
3655
        t->snap[2] = t->snap[1] * 0.1f;
 
3656
        
 
3657
        t->fac = (float)sqrt( (
 
3658
                                           ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
 
3659
                                           +
 
3660
                                           ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
 
3661
                                           ) );
 
3662
        
 
3663
        if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
 
3664
}
 
3665
 
 
3666
static void headerBoneSize(TransInfo *t, float vec[3], char *str) {
 
3667
        char tvec[60];
 
3668
        if (hasNumInput(&t->num)) {
 
3669
                outputNumInput(&(t->num), tvec);
 
3670
        }
 
3671
        else {
 
3672
                sprintf(&tvec[0], "%.4f", vec[0]);
 
3673
                sprintf(&tvec[20], "%.4f", vec[1]);
 
3674
                sprintf(&tvec[40], "%.4f", vec[2]);
 
3675
        }
 
3676
 
 
3677
        /* hmm... perhaps the y-axis values don't need to be shown? */
 
3678
        if (t->con.mode & CON_APPLY) {
 
3679
                if (t->num.idx_max == 0)
 
3680
                        sprintf(str, "ScaleB: %s%s %s", &tvec[0], t->con.text, t->proptext);
 
3681
                else 
 
3682
                        sprintf(str, "ScaleB: %s : %s : %s%s %s", &tvec[0], &tvec[20], &tvec[40], t->con.text, t->proptext);
 
3683
        }
 
3684
        else {
 
3685
                sprintf(str, "ScaleB X: %s  Y: %s  Z: %s%s %s", &tvec[0], &tvec[20], &tvec[40], t->con.text, t->proptext);
 
3686
        }
 
3687
}
 
3688
 
2602
3689
static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3]) 
2603
3690
{
2604
3691
        float tmat[3][3], smat[3][3], oldy;
2619
3706
        td->loc[1]= oldy;
2620
3707
}
2621
3708
 
2622
 
 
2623
3709
int BoneSize(TransInfo *t, short mval[2]) 
2624
3710
{
2625
3711
        TransData *td = t->data;
2626
3712
        float size[3], mat[3][3];
2627
3713
        float ratio;
2628
3714
        int i;
2629
 
        char str[50];
 
3715
        char str[60];
2630
3716
        
2631
3717
        /* for manipulator, center handle, the scaling can't be done relative to center */
2632
3718
        if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0) {
2674
3760
        
2675
3761
        Mat3CpyMat3(t->mat, mat);       // used in manipulator
2676
3762
        
2677
 
        headerResize(t, size, str);
 
3763
        headerBoneSize(t, size, str);
2678
3764
        
2679
3765
        for(i = 0 ; i < t->total; i++, td++) {
2680
3766
                if (td->flag & TD_NOACTION)
2681
3767
                        break;
 
3768
 
 
3769
                if (td->flag & TD_SKIP)
 
3770
                        continue;
2682
3771
                
2683
3772
                ElementBoneSize(t, td, mat);
2684
3773
        }
2694
3783
        return 1;
2695
3784
}
2696
3785
 
2697
 
void initBoneSize(TransInfo *t)
2698
 
{
2699
 
        t->idx_max = 0;
2700
 
        t->num.idx_max = 0;
2701
 
        t->snap[0] = 0.0f;
2702
 
        t->snap[1] = 0.1f;
2703
 
        t->snap[2] = t->snap[1] * 0.1f;
2704
 
        t->transform = BoneSize;
2705
 
        t->fac = (float)sqrt( (
2706
 
                                           ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
2707
 
                                           +
2708
 
                                           ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
2709
 
                                           ) );
2710
 
        
2711
 
        if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
2712
 
}
2713
3786
 
2714
3787
/* ******************** EditBone envelope *************** */
2715
3788
 
2716
 
int BoneEnvelope(TransInfo *t, short mval[2]) 
2717
 
{
2718
 
        TransData *td = t->data;
2719
 
        float ratio;
2720
 
        int i;
2721
 
        char str[50];
2722
 
        
2723
 
        if(t->flag & T_SHIFT_MOD) {
2724
 
                /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
2725
 
                float dx= (float)(t->center2d[0] - t->shiftmval[0]);
2726
 
                float dy= (float)(t->center2d[1] - t->shiftmval[1]);
2727
 
                ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
2728
 
                
2729
 
                dx= (float)(t->center2d[0] - mval[0]);
2730
 
                dy= (float)(t->center2d[1] - mval[1]);
2731
 
                ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio);
2732
 
                
2733
 
        }
2734
 
        else {
2735
 
                float dx= (float)(t->center2d[0] - mval[0]);
2736
 
                float dy= (float)(t->center2d[1] - mval[1]);
2737
 
                ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
2738
 
        }
2739
 
        
2740
 
        snapGrid(t, &ratio);
2741
 
        
2742
 
        applyNumInput(&t->num, &ratio);
2743
 
        
2744
 
        /* header print for NumInput */
2745
 
        if (hasNumInput(&t->num)) {
2746
 
                char c[20];
2747
 
                
2748
 
                outputNumInput(&(t->num), c);
2749
 
                sprintf(str, "Envelope: %s", c);
2750
 
        }
2751
 
        else {
2752
 
                sprintf(str, "Envelope: %3f", ratio);
2753
 
        }
2754
 
        
2755
 
        for(i = 0 ; i < t->total; i++, td++) {
2756
 
                if (td->flag & TD_NOACTION)
2757
 
                        break;
2758
 
                
2759
 
                if(td->val) *td->val= td->ival*ratio;
2760
 
        }
2761
 
        
2762
 
        recalcData(t);
2763
 
        
2764
 
        headerprint(str);
2765
 
        
2766
 
        force_draw(0);
2767
 
        
2768
 
        if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
2769
 
        
2770
 
        return 1;
2771
 
}
2772
 
 
2773
3789
void initBoneEnvelope(TransInfo *t)
2774
3790
{
2775
 
        t->idx_max = 0;
2776
 
        t->num.idx_max = 0;
2777
 
        t->snap[0] = 0.0f;
2778
 
        t->snap[1] = 0.1f;
2779
 
        t->snap[2] = t->snap[1] * 0.1f;
 
3791
        t->mode = TFM_BONE_ENVELOPE;
2780
3792
        t->transform = BoneEnvelope;
 
3793
        
 
3794
        t->idx_max = 0;
 
3795
        t->num.idx_max = 0;
 
3796
        t->snap[0] = 0.0f;
 
3797
        t->snap[1] = 0.1f;
 
3798
        t->snap[2] = t->snap[1] * 0.1f;
 
3799
 
 
3800
        t->flag |= T_NO_CONSTRAINT;
 
3801
 
2781
3802
        t->fac = (float)sqrt( (
2782
3803
                                                   ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
2783
3804
                                                   +
2787
3808
        if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
2788
3809
}
2789
3810
 
 
3811
int BoneEnvelope(TransInfo *t, short mval[2]) 
 
3812
{
 
3813
        TransData *td = t->data;
 
3814
        float ratio;
 
3815
        int i;
 
3816
        char str[50];
 
3817
        
 
3818
        if(t->flag & T_SHIFT_MOD) {
 
3819
                /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
 
3820
                float dx= (float)(t->center2d[0] - t->shiftmval[0]);
 
3821
                float dy= (float)(t->center2d[1] - t->shiftmval[1]);
 
3822
                ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
 
3823
                
 
3824
                dx= (float)(t->center2d[0] - mval[0]);
 
3825
                dy= (float)(t->center2d[1] - mval[1]);
 
3826
                ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio);
 
3827
                
 
3828
        }
 
3829
        else {
 
3830
                float dx= (float)(t->center2d[0] - mval[0]);
 
3831
                float dy= (float)(t->center2d[1] - mval[1]);
 
3832
                ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
 
3833
        }
 
3834
        
 
3835
        snapGrid(t, &ratio);
 
3836
        
 
3837
        applyNumInput(&t->num, &ratio);
 
3838
        
 
3839
        /* header print for NumInput */
 
3840
        if (hasNumInput(&t->num)) {
 
3841
                char c[20];
 
3842
                
 
3843
                outputNumInput(&(t->num), c);
 
3844
                sprintf(str, "Envelope: %s", c);
 
3845
        }
 
3846
        else {
 
3847
                sprintf(str, "Envelope: %3f", ratio);
 
3848
        }
 
3849
        
 
3850
        for(i = 0 ; i < t->total; i++, td++) {
 
3851
                if (td->flag & TD_NOACTION)
 
3852
                        break;
 
3853
 
 
3854
                if (td->flag & TD_SKIP)
 
3855
                        continue;
 
3856
                
 
3857
                if (td->val) {
 
3858
                        /* if the old/original value was 0.0f, then just use ratio */
 
3859
                        if (td->ival)
 
3860
                                *td->val= td->ival*ratio;
 
3861
                        else
 
3862
                                *td->val= ratio;
 
3863
                }
 
3864
        }
 
3865
        
 
3866
        recalcData(t);
 
3867
        
 
3868
        headerprint(str);
 
3869
        
 
3870
        force_draw(0);
 
3871
        
 
3872
        if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
 
3873
        
 
3874
        return 1;
 
3875
}
 
3876
 
 
3877
 
 
3878
/* ******************** EditBone roll *************** */
 
3879
 
 
3880
void initBoneRoll(TransInfo *t)
 
3881
{
 
3882
        t->mode = TFM_BONE_ROLL;
 
3883
        t->transform = BoneRoll;
 
3884
 
 
3885
        t->idx_max = 0;
 
3886
        t->num.idx_max = 0;
 
3887
        t->snap[0] = 0.0f;
 
3888
        t->snap[1] = (float)((5.0/180)*M_PI);
 
3889
        t->snap[2] = t->snap[1] * 0.2f;
 
3890
        
 
3891
        t->fac = 0.0f;
 
3892
        
 
3893
        t->flag |= T_NO_CONSTRAINT;
 
3894
}
 
3895
 
 
3896
int BoneRoll(TransInfo *t, short mval[2]) 
 
3897
{
 
3898
        TransData *td = t->data;
 
3899
        int i;
 
3900
        char str[50];
 
3901
 
 
3902
        float final;
 
3903
 
 
3904
        t->fac += InputDeltaAngle(t, mval);
 
3905
 
 
3906
        final = t->fac;
 
3907
 
 
3908
        snapGrid(t, &final);
 
3909
 
 
3910
        if (hasNumInput(&t->num)) {
 
3911
                char c[20];
 
3912
 
 
3913
                applyNumInput(&t->num, &final);
 
3914
 
 
3915
                outputNumInput(&(t->num), c);
 
3916
 
 
3917
                sprintf(str, "Roll: %s", &c[0]);
 
3918
 
 
3919
                final *= (float)(M_PI / 180.0);
 
3920
        }
 
3921
        else {
 
3922
                sprintf(str, "Roll: %.2f", 180.0*final/M_PI);
 
3923
        }
 
3924
        
 
3925
        /* set roll values */
 
3926
        for (i = 0; i < t->total; i++, td++) {  
 
3927
                if (td->flag & TD_NOACTION)
 
3928
                        break;
 
3929
 
 
3930
                if (td->flag & TD_SKIP)
 
3931
                        continue;
 
3932
                
 
3933
                *(td->val) = td->ival - final;
 
3934
        }
 
3935
                
 
3936
        recalcData(t);
 
3937
 
 
3938
        headerprint(str);
 
3939
 
 
3940
        viewRedrawForce(t);
 
3941
 
 
3942
        if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
 
3943
 
 
3944
        return 1;
 
3945
}
 
3946
 
 
3947
/* ************************** BAKE TIME ******************* */
 
3948
 
 
3949
void initBakeTime(TransInfo *t) 
 
3950
{
 
3951
        t->idx_max = 0;
 
3952
        t->num.idx_max = 0;
 
3953
        t->snap[0] = 0.0f;
 
3954
        t->snap[1] = 1.0f;
 
3955
        t->snap[2] = t->snap[1] * 0.1f;
 
3956
        t->transform = BakeTime;
 
3957
        t->fac = 0.1f;
 
3958
}
 
3959
 
 
3960
int BakeTime(TransInfo *t, short mval[2]) 
 
3961
{
 
3962
        TransData *td = t->data;
 
3963
        float time;
 
3964
        int i;
 
3965
        char str[50];
 
3966
 
 
3967
                
 
3968
        if(t->flag & T_SHIFT_MOD) {
 
3969
                /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
 
3970
                time= (float)(t->center2d[0] - t->shiftmval[0])*t->fac;
 
3971
                time+= 0.1f*((float)(t->center2d[0]*t->fac - mval[0]) -time);
 
3972
        }
 
3973
        else {
 
3974
                time = (float)(t->center2d[0] - mval[0])*t->fac;
 
3975
        }
 
3976
 
 
3977
        snapGrid(t, &time);
 
3978
 
 
3979
        applyNumInput(&t->num, &time);
 
3980
 
 
3981
        /* header print for NumInput */
 
3982
        if (hasNumInput(&t->num)) {
 
3983
                char c[20];
 
3984
 
 
3985
                outputNumInput(&(t->num), c);
 
3986
 
 
3987
                if (time >= 0.0f)
 
3988
                        sprintf(str, "Time: +%s %s", c, t->proptext);
 
3989
                else
 
3990
                        sprintf(str, "Time: %s %s", c, t->proptext);
 
3991
        }
 
3992
        else {
 
3993
                /* default header print */
 
3994
                if (time >= 0.0f)
 
3995
                        sprintf(str, "Time: +%.3f %s", time, t->proptext);
 
3996
                else
 
3997
                        sprintf(str, "Time: %.3f %s", time, t->proptext);
 
3998
        }
 
3999
        
 
4000
        for(i = 0 ; i < t->total; i++, td++) {
 
4001
                if (td->flag & TD_NOACTION)
 
4002
                        break;
 
4003
 
 
4004
                if (td->flag & TD_SKIP)
 
4005
                        continue;
 
4006
 
 
4007
                if (td->val) {
 
4008
                        *td->val = td->ival + time * td->factor;
 
4009
                        if (td->ext->size && *td->val < *td->ext->size) *td->val = *td->ext->size;
 
4010
                        if (td->ext->quat && *td->val > *td->ext->quat) *td->val = *td->ext->quat;
 
4011
                }
 
4012
        }
 
4013
 
 
4014
        recalcData(t);
 
4015
 
 
4016
        headerprint(str);
 
4017
 
 
4018
        viewRedrawForce(t);
 
4019
 
 
4020
        helpline (t, t->center);
 
4021
 
 
4022
        return 1;
 
4023
}
 
4024
 
 
4025
/* ************************** MIRROR *************************** */
 
4026
 
 
4027
void initMirror(TransInfo *t) 
 
4028
{
 
4029
        t->flag |= T_NULL_ONE;
 
4030
        if (!G.obedit) {
 
4031
                t->flag |= T_NO_ZERO;
 
4032
        }
 
4033
        
 
4034
        t->transform = Mirror;
 
4035
}
 
4036
 
 
4037
int Mirror(TransInfo *t, short mval[2]) 
 
4038
{
 
4039
        TransData *td;
 
4040
        float size[3], mat[3][3];
 
4041
        int i;
 
4042
        char str[200];
 
4043
 
 
4044
        /*
 
4045
         * OPTIMISATION:
 
4046
         * This still recalcs transformation on mouse move
 
4047
         * while it should only recalc on constraint change
 
4048
         * */
 
4049
 
 
4050
        /* if an axis has been selected */
 
4051
        if (t->con.mode & CON_APPLY) {
 
4052
                size[0] = size[1] = size[2] = -1;
 
4053
        
 
4054
                SizeToMat3(size, mat);
 
4055
                
 
4056
                if (t->con.applySize) {
 
4057
                        t->con.applySize(t, NULL, mat);
 
4058
                }
 
4059
                
 
4060
                sprintf(str, "Mirror%s", t->con.text);
 
4061
        
 
4062
                for(i = 0, td=t->data; i < t->total; i++, td++) {
 
4063
                        if (td->flag & TD_NOACTION)
 
4064
                                break;
 
4065
        
 
4066
                        if (td->flag & TD_SKIP)
 
4067
                                continue;
 
4068
                        
 
4069
                        ElementResize(t, td, mat);
 
4070
                }
 
4071
        
 
4072
                recalcData(t);
 
4073
        
 
4074
                headerprint(str);
 
4075
        
 
4076
                viewRedrawForce(t);
 
4077
        }
 
4078
        else
 
4079
        {
 
4080
                size[0] = size[1] = size[2] = 1;
 
4081
        
 
4082
                SizeToMat3(size, mat);
 
4083
                
 
4084
                for(i = 0, td=t->data; i < t->total; i++, td++) {
 
4085
                        if (td->flag & TD_NOACTION)
 
4086
                                break;
 
4087
        
 
4088
                        if (td->flag & TD_SKIP)
 
4089
                                continue;
 
4090
                        
 
4091
                        ElementResize(t, td, mat);
 
4092
                }
 
4093
        
 
4094
                recalcData(t);
 
4095
        
 
4096
                headerprint("Select a mirror axis (X, Y, Z)");
 
4097
        
 
4098
                viewRedrawForce(t);
 
4099
        }
 
4100
 
 
4101
        return 1;
 
4102
}
 
4103
 
 
4104
/* ************************** ALIGN *************************** */
 
4105
 
 
4106
void initAlign(TransInfo *t) 
 
4107
{
 
4108
        t->flag |= T_NO_CONSTRAINT;
 
4109
        
 
4110
        t->transform = Align;
 
4111
}
 
4112
 
 
4113
int Align(TransInfo *t, short mval[2])
 
4114
{
 
4115
        TransData *td = t->data;
 
4116
        float center[3];
 
4117
        int i;
 
4118
 
 
4119
        /* saving original center */
 
4120
        VECCOPY(center, t->center);
 
4121
 
 
4122
        for(i = 0 ; i < t->total; i++, td++)
 
4123
        {
 
4124
                float mat[3][3], invmat[3][3];
 
4125
                
 
4126
                if (td->flag & TD_NOACTION)
 
4127
                        break;
 
4128
 
 
4129
                if (td->flag & TD_SKIP)
 
4130
                        continue;
 
4131
                
 
4132
                /* around local centers */
 
4133
                if (t->flag & (T_OBJECT|T_POSE)) {
 
4134
                        VECCOPY(t->center, td->center);
 
4135
                }
 
4136
                else {
 
4137
                        if(G.scene->selectmode & SCE_SELECT_FACE) {
 
4138
                                VECCOPY(t->center, td->center);
 
4139
                        }
 
4140
                }
 
4141
 
 
4142
                Mat3Inv(invmat, td->axismtx);
 
4143
                
 
4144
                Mat3MulMat3(mat, t->spacemtx, invmat);  
 
4145
 
 
4146
                ElementRotation(t, td, mat);
 
4147
        }
 
4148
 
 
4149
        /* restoring original center */
 
4150
        VECCOPY(t->center, center);
 
4151
                
 
4152
        recalcData(t);
 
4153
 
 
4154
        headerprint("Align");
 
4155
        
 
4156
        return 1;
 
4157
}
 
4158
 
 
4159
/* ************************** ANIM EDITORS - TRANSFORM TOOLS *************************** */
 
4160
 
 
4161
/* ---------------- Special Helpers for Various Settings ------------- */
 
4162
 
 
4163
/* This function returns the snapping 'mode' for Animation Editors only 
 
4164
 * We cannot use the standard snapping due to NLA-strip scaling complexities.
 
4165
 */
 
4166
static short getAnimEdit_SnapMode(TransInfo *t)
 
4167
{
 
4168
        short autosnap= SACTSNAP_OFF;
 
4169
        
 
4170
        /* currently, some of these are only for the action editor */
 
4171
        if (t->spacetype == SPACE_ACTION && G.saction) {
 
4172
                switch (G.saction->autosnap) {
 
4173
                case SACTSNAP_OFF:
 
4174
                        if (G.qual == LR_CTRLKEY) 
 
4175
                                autosnap= SACTSNAP_STEP;
 
4176
                        else if (G.qual == LR_SHIFTKEY)
 
4177
                                autosnap= SACTSNAP_FRAME;
 
4178
                        else if (G.qual == LR_ALTKEY)
 
4179
                                autosnap= SACTSNAP_MARKER;
 
4180
                        else
 
4181
                                autosnap= SACTSNAP_OFF;
 
4182
                        break;
 
4183
                case SACTSNAP_STEP:
 
4184
                        autosnap= (G.qual==LR_CTRLKEY)? SACTSNAP_OFF: SACTSNAP_STEP;
 
4185
                        break;
 
4186
                case SACTSNAP_FRAME:
 
4187
                        autosnap= (G.qual==LR_SHIFTKEY)? SACTSNAP_OFF: SACTSNAP_FRAME;
 
4188
                        break;
 
4189
                case SACTSNAP_MARKER:
 
4190
                        autosnap= (G.qual==LR_ALTKEY)? SACTSNAP_OFF: SACTSNAP_MARKER;
 
4191
                        break;
 
4192
                }
 
4193
        }
 
4194
        else if (t->spacetype == SPACE_NLA && G.snla) {
 
4195
                switch (G.snla->autosnap) {
 
4196
                case SACTSNAP_OFF:
 
4197
                        if (G.qual == LR_CTRLKEY) 
 
4198
                                autosnap= SACTSNAP_STEP;
 
4199
                        else if (G.qual == LR_SHIFTKEY)
 
4200
                                autosnap= SACTSNAP_FRAME;
 
4201
                        else if (G.qual == LR_ALTKEY)
 
4202
                                autosnap= SACTSNAP_MARKER;
 
4203
                        else
 
4204
                                autosnap= SACTSNAP_OFF;
 
4205
                        break;
 
4206
                case SACTSNAP_STEP:
 
4207
                        autosnap= (G.qual==LR_CTRLKEY)? SACTSNAP_OFF: SACTSNAP_STEP;
 
4208
                        break;
 
4209
                case SACTSNAP_FRAME:
 
4210
                        autosnap= (G.qual==LR_SHIFTKEY)? SACTSNAP_OFF: SACTSNAP_FRAME;
 
4211
                        break;
 
4212
                case SACTSNAP_MARKER:
 
4213
                        autosnap= (G.qual==LR_ALTKEY)? SACTSNAP_OFF: SACTSNAP_MARKER;
 
4214
                        break;
 
4215
                }
 
4216
        }
 
4217
        else {
 
4218
                if (G.qual == LR_CTRLKEY) 
 
4219
                        autosnap= SACTSNAP_STEP;
 
4220
                else if (G.qual == LR_SHIFTKEY)
 
4221
                        autosnap= SACTSNAP_FRAME;
 
4222
                else if (G.qual == LR_ALTKEY)
 
4223
                        autosnap= SACTSNAP_MARKER;
 
4224
                else
 
4225
                        autosnap= SACTSNAP_OFF;
 
4226
        }
 
4227
        
 
4228
        return autosnap;
 
4229
}
 
4230
 
 
4231
/* This function is used for testing if an Animation Editor is displaying
 
4232
 * its data in frames or seconds (and the data needing to be edited as such).
 
4233
 * Returns 1 if in seconds, 0 if in frames 
 
4234
 */
 
4235
static short getAnimEdit_DrawTime(TransInfo *t)
 
4236
{
 
4237
        short drawtime;
 
4238
        
 
4239
        /* currently, some of these are only for the action editor */
 
4240
        if (t->spacetype == SPACE_ACTION && G.saction) {
 
4241
                drawtime = (G.saction->flag & SACTION_DRAWTIME)? 1 : 0;
 
4242
        }
 
4243
        else if (t->spacetype == SPACE_NLA && G.snla) {
 
4244
                drawtime = (G.snla->flag & SNLA_DRAWTIME)? 1 : 0;
 
4245
        }
 
4246
        else {
 
4247
                drawtime = 0;
 
4248
        }
 
4249
        
 
4250
        return drawtime;
 
4251
}       
 
4252
 
 
4253
 
 
4254
/* This function is used by Animation Editor specific transform functions to do 
 
4255
 * the Snap Keyframe to Nearest Frame/Marker
 
4256
 */
 
4257
static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, Object *ob, short autosnap)
 
4258
{
 
4259
        /* snap key to nearest frame? */
 
4260
        if (autosnap == SACTSNAP_FRAME) {
 
4261
                short doTime= getAnimEdit_DrawTime(t);
 
4262
                double secf= FPS;
 
4263
                double val;
 
4264
                
 
4265
                /* convert frame to nla-action time (if needed) */
 
4266
                if (ob) 
 
4267
                        val= get_action_frame_inv(ob, *(td->val));
 
4268
                else
 
4269
                        val= *(td->val);
 
4270
                
 
4271
                /* do the snapping to nearest frame/second */
 
4272
                if (doTime)
 
4273
                        val= (float)( floor((val/secf) + 0.5f) * secf );
 
4274
                else
 
4275
                        val= (float)( floor(val+0.5f) );
 
4276
                        
 
4277
                /* convert frame out of nla-action time */
 
4278
                if (ob)
 
4279
                        *(td->val)= get_action_frame(ob, val);
 
4280
                else
 
4281
                        *(td->val)= val;
 
4282
        }
 
4283
        /* snap key to nearest marker? */
 
4284
        else if (autosnap == SACTSNAP_MARKER) {
 
4285
                float val;
 
4286
                
 
4287
                /* convert frame to nla-action time (if needed) */
 
4288
                if (ob) 
 
4289
                        val= get_action_frame_inv(ob, *(td->val));
 
4290
                else
 
4291
                        val= *(td->val);
 
4292
                
 
4293
                /* snap to nearest marker */
 
4294
                val= (float)find_nearest_marker_time(val);
 
4295
                        
 
4296
                /* convert frame out of nla-action time */
 
4297
                if (ob)
 
4298
                        *(td->val)= get_action_frame(ob, val);
 
4299
                else
 
4300
                        *(td->val)= val;
 
4301
        }
 
4302
}
 
4303
 
 
4304
/* ----------------- Translation ----------------------- */
 
4305
 
 
4306
void initTimeTranslate(TransInfo *t) 
 
4307
{
 
4308
        t->mode = TFM_TIME_TRANSLATE;
 
4309
        t->transform = TimeTranslate;
 
4310
 
 
4311
        /* num-input has max of (n-1) */
 
4312
        t->idx_max = 0;
 
4313
        t->num.flag = 0;
 
4314
        t->num.idx_max = t->idx_max;
 
4315
        
 
4316
        /* initialise snap like for everything else */
 
4317
        t->snap[0] = 0.0f; 
 
4318
        t->snap[1] = t->snap[2] = 1.0f;
 
4319
}
 
4320
 
 
4321
static void headerTimeTranslate(TransInfo *t, char *str) 
 
4322
{
 
4323
        char tvec[60];
 
4324
        
 
4325
        /* if numeric input is active, use results from that, otherwise apply snapping to result */
 
4326
        if (hasNumInput(&t->num)) {
 
4327
                outputNumInput(&(t->num), tvec);
 
4328
        }
 
4329
        else {
 
4330
                short autosnap= getAnimEdit_SnapMode(t);
 
4331
                short doTime = getAnimEdit_DrawTime(t);
 
4332
                double secf= FPS;
 
4333
                float val= t->fac;
 
4334
                
 
4335
                /* apply snapping + frame->seconds conversions */
 
4336
                if (autosnap == SACTSNAP_STEP) {
 
4337
                        if (doTime)
 
4338
                                val= floor(val/secf + 0.5f);
 
4339
                        else
 
4340
                                val= floor(val + 0.5f);
 
4341
                }
 
4342
                else {
 
4343
                        if (doTime)
 
4344
                                val= val / secf;
 
4345
                }
 
4346
                
 
4347
                sprintf(&tvec[0], "%.4f", val);
 
4348
        }
 
4349
                
 
4350
        sprintf(str, "DeltaX: %s", &tvec[0]);
 
4351
}
 
4352
 
 
4353
static void applyTimeTranslate(TransInfo *t, float sval) 
 
4354
{
 
4355
        TransData *td = t->data;
 
4356
        int i;
 
4357
        
 
4358
        short doTime= getAnimEdit_DrawTime(t);
 
4359
        double secf= FPS;
 
4360
        
 
4361
        short autosnap= getAnimEdit_SnapMode(t);
 
4362
        
 
4363
        float deltax, val;
 
4364
        
 
4365
        /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
 
4366
        for (i = 0 ; i < t->total; i++, td++) {
 
4367
                /* it is assumed that td->ob is a pointer to the object,
 
4368
                 * whose active action is where this keyframe comes from 
 
4369
                 */
 
4370
                Object *ob= td->ob;
 
4371
                
 
4372
                /* check if any need to apply nla-scaling */
 
4373
                if (ob) {
 
4374
                        deltax = t->fac;
 
4375
                        
 
4376
                        if (autosnap == SACTSNAP_STEP) {
 
4377
                                if (doTime) 
 
4378
                                        deltax= (float)( floor((deltax/secf) + 0.5f) * secf );
 
4379
                                else
 
4380
                                        deltax= (float)( floor(deltax + 0.5f) );
 
4381
                        }
 
4382
                        
 
4383
                        val = get_action_frame_inv(ob, td->ival);
 
4384
                        val += deltax;
 
4385
                        *(td->val) = get_action_frame(ob, val);
 
4386
                }
 
4387
                else {
 
4388
                        deltax = val = t->fac;
 
4389
                        
 
4390
                        if (autosnap == SACTSNAP_STEP) {
 
4391
                                if (doTime)
 
4392
                                        val= (float)( floor((deltax/secf) + 0.5f) * secf );
 
4393
                                else
 
4394
                                        val= (float)( floor(val + 0.5f) );
 
4395
                        }
 
4396
                        
 
4397
                        *(td->val) = td->ival + val;
 
4398
                }
 
4399
                
 
4400
                /* apply nearest snapping */
 
4401
                doAnimEdit_SnapFrame(t, td, ob, autosnap);
 
4402
        }
 
4403
}
 
4404
 
 
4405
int TimeTranslate(TransInfo *t, short mval[2]) 
 
4406
{
 
4407
        float cval[2], sval[2];
 
4408
        char str[200];
 
4409
        
 
4410
        /* calculate translation amount from mouse movement - in 'time-grid space' */
 
4411
        areamouseco_to_ipoco(G.v2d, mval, &cval[0], &cval[1]);
 
4412
        areamouseco_to_ipoco(G.v2d, t->imval, &sval[0], &sval[1]);
 
4413
        
 
4414
        /* we only need to calculate effect for time (applyTimeTranslate only needs that) */
 
4415
        t->fac= cval[0] - sval[0];
 
4416
        
 
4417
        /* handle numeric-input stuff */
 
4418
        t->vec[0] = t->fac;
 
4419
        applyNumInput(&t->num, &t->vec[0]);
 
4420
        t->fac = t->vec[0];
 
4421
        headerTimeTranslate(t, str);
 
4422
        
 
4423
        applyTimeTranslate(t, sval[0]);
 
4424
 
 
4425
        recalcData(t);
 
4426
 
 
4427
        headerprint(str);
 
4428
        
 
4429
        viewRedrawForce(t);
 
4430
 
 
4431
        return 1;
 
4432
}
 
4433
 
 
4434
/* ----------------- Time Slide ----------------------- */
 
4435
 
 
4436
void initTimeSlide(TransInfo *t) 
 
4437
{
 
4438
        /* this tool is only really available in the Action Editor... */
 
4439
        if (t->spacetype == SPACE_ACTION) {
 
4440
                /* set flag for drawing stuff*/
 
4441
                G.saction->flag |= SACTION_MOVING;
 
4442
        }
 
4443
        
 
4444
        t->mode = TFM_TIME_SLIDE;
 
4445
        t->transform = TimeSlide;
 
4446
        t->flag |= T_FREE_CUSTOMDATA;
 
4447
 
 
4448
        /* num-input has max of (n-1) */
 
4449
        t->idx_max = 0;
 
4450
        t->num.flag = 0;
 
4451
        t->num.idx_max = t->idx_max;
 
4452
        
 
4453
        /* initialise snap like for everything else */
 
4454
        t->snap[0] = 0.0f; 
 
4455
        t->snap[1] = t->snap[2] = 1.0f;
 
4456
}
 
4457
 
 
4458
static void headerTimeSlide(TransInfo *t, float sval, char *str) 
 
4459
{
 
4460
        char tvec[60];
 
4461
        
 
4462
        if (hasNumInput(&t->num)) {
 
4463
                outputNumInput(&(t->num), tvec);
 
4464
        }
 
4465
        else {
 
4466
                float minx= *((float *)(t->customData));
 
4467
                float maxx= *((float *)(t->customData) + 1);
 
4468
                float cval= t->fac;
 
4469
                float val;
 
4470
                        
 
4471
                val= 2.0*(cval-sval) / (maxx-minx);
 
4472
                CLAMP(val, -1.0f, 1.0f);
 
4473
                
 
4474
                sprintf(&tvec[0], "%.4f", val);
 
4475
        }
 
4476
                
 
4477
        sprintf(str, "TimeSlide: %s", &tvec[0]);
 
4478
}
 
4479
 
 
4480
static void applyTimeSlide(TransInfo *t, float sval) 
 
4481
{
 
4482
        TransData *td = t->data;
 
4483
        int i;
 
4484
        
 
4485
        float minx= *((float *)(t->customData));
 
4486
        float maxx= *((float *)(t->customData) + 1);
 
4487
        
 
4488
        
 
4489
        /* set value for drawing black line */
 
4490
        if (t->spacetype == SPACE_ACTION) {
 
4491
                float cvalf = t->fac;
 
4492
                
 
4493
                if (NLA_ACTION_SCALED)
 
4494
                        cvalf= get_action_frame(OBACT, cvalf);
 
4495
                        
 
4496
                G.saction->timeslide= cvalf;
 
4497
        }
 
4498
        
 
4499
        /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
 
4500
        for (i = 0 ; i < t->total; i++, td++) {
 
4501
                /* it is assumed that td->ob is a pointer to the object,
 
4502
                 * whose active action is where this keyframe comes from 
 
4503
                 */
 
4504
                Object *ob= td->ob;
 
4505
                float cval = t->fac;
 
4506
                
 
4507
                /* apply scaling to necessary values */
 
4508
                if (ob)
 
4509
                        cval= get_action_frame(ob, cval);
 
4510
                
 
4511
                /* only apply to data if in range */
 
4512
                if ((sval > minx) && (sval < maxx)) {
 
4513
                        float cvalc= CLAMPIS(cval, minx, maxx);
 
4514
                        float timefac;
 
4515
                        
 
4516
                        /* left half? */
 
4517
                        if (td->ival < sval) {
 
4518
                                timefac= (sval - td->ival) / (sval - minx);
 
4519
                                *(td->val)= cvalc - timefac * (cvalc - minx);
 
4520
                        }
 
4521
                        else {
 
4522
                                timefac= (td->ival - sval) / (maxx - sval);
 
4523
                                *(td->val)= cvalc + timefac * (maxx - cvalc);
 
4524
                        }
 
4525
                }
 
4526
        }
 
4527
}
 
4528
 
 
4529
int TimeSlide(TransInfo *t, short mval[2]) 
 
4530
{
 
4531
        float cval[2], sval[2];
 
4532
        float minx= *((float *)(t->customData));
 
4533
        float maxx= *((float *)(t->customData) + 1);
 
4534
        char str[200];
 
4535
        
 
4536
        /* calculate mouse co-ordinates */
 
4537
        areamouseco_to_ipoco(G.v2d, mval, &cval[0], &cval[1]);
 
4538
        areamouseco_to_ipoco(G.v2d, t->imval, &sval[0], &sval[1]);
 
4539
        
 
4540
        /* t->fac stores cval[0], which is the current mouse-pointer location (in frames) */
 
4541
        t->fac= cval[0];
 
4542
        
 
4543
        /* handle numeric-input stuff */
 
4544
        t->vec[0] = 2.0*(cval[0]-sval[0]) / (maxx-minx);
 
4545
        applyNumInput(&t->num, &t->vec[0]);
 
4546
        t->fac = (maxx-minx) * t->vec[0] / 2.0 + sval[0];
 
4547
        
 
4548
        headerTimeSlide(t, sval[0], str);
 
4549
        applyTimeSlide(t, sval[0]);
 
4550
 
 
4551
        recalcData(t);
 
4552
 
 
4553
        headerprint(str);
 
4554
        
 
4555
        viewRedrawForce(t);
 
4556
 
 
4557
        return 1;
 
4558
}
 
4559
 
 
4560
/* ----------------- Scaling ----------------------- */
 
4561
 
 
4562
void initTimeScale(TransInfo *t) 
 
4563
{
 
4564
        t->mode = TFM_TIME_SCALE;
 
4565
        t->transform = TimeScale;
 
4566
 
 
4567
        t->flag |= T_NULL_ONE;
 
4568
        t->num.flag |= NUM_NULL_ONE;
 
4569
        
 
4570
        /* num-input has max of (n-1) */
 
4571
        t->idx_max = 0;
 
4572
        t->num.flag = 0;
 
4573
        t->num.idx_max = t->idx_max;
 
4574
        
 
4575
        /* initialise snap like for everything else */
 
4576
        t->snap[0] = 0.0f; 
 
4577
        t->snap[1] = t->snap[2] = 1.0f;
 
4578
}
 
4579
 
 
4580
static void headerTimeScale(TransInfo *t, char *str) {
 
4581
        char tvec[60];
 
4582
        
 
4583
        if (hasNumInput(&t->num))
 
4584
                outputNumInput(&(t->num), tvec);
 
4585
        else
 
4586
                sprintf(&tvec[0], "%.4f", t->fac);
 
4587
                
 
4588
        sprintf(str, "ScaleX: %s", &tvec[0]);
 
4589
}
 
4590
 
 
4591
static void applyTimeScale(TransInfo *t) {
 
4592
        TransData *td = t->data;
 
4593
        int i;
 
4594
        
 
4595
        short autosnap= getAnimEdit_SnapMode(t);
 
4596
        short doTime= getAnimEdit_DrawTime(t);
 
4597
        double secf= FPS;
 
4598
        
 
4599
        
 
4600
        for (i = 0 ; i < t->total; i++, td++) {
 
4601
                /* it is assumed that td->ob is a pointer to the object,
 
4602
                 * whose active action is where this keyframe comes from 
 
4603
                 */
 
4604
                Object *ob= td->ob;
 
4605
                float startx= CFRA;
 
4606
                float fac= t->fac;
 
4607
                
 
4608
                if (autosnap == SACTSNAP_STEP) {
 
4609
                        if (doTime)
 
4610
                                fac= (float)( floor(fac/secf + 0.5f) * secf );
 
4611
                        else
 
4612
                                fac= (float)( floor(fac + 0.5f) );
 
4613
                }
 
4614
                
 
4615
                /* check if any need to apply nla-scaling */
 
4616
                if (ob)
 
4617
                        startx= get_action_frame(ob, startx);
 
4618
                        
 
4619
                /* now, calculate the new value */
 
4620
                *(td->val) = td->ival - startx;
 
4621
                *(td->val) *= fac;
 
4622
                *(td->val) += startx;
 
4623
                
 
4624
                /* apply nearest snapping */
 
4625
                doAnimEdit_SnapFrame(t, td, ob, autosnap);
 
4626
        }
 
4627
}
 
4628
 
 
4629
int TimeScale(TransInfo *t, short mval[2]) 
 
4630
{
 
4631
        float cval, sval;
 
4632
        float deltax, startx;
 
4633
        float width= 0.0f;
 
4634
        char str[200];
 
4635
        
 
4636
        sval= t->imval[0];
 
4637
        cval= mval[0];
 
4638
        
 
4639
        switch (t->spacetype) {
 
4640
                case SPACE_ACTION:
 
4641
                        width= ACTWIDTH;
 
4642
                        break;
 
4643
                case SPACE_NLA:
 
4644
                        width= NLAWIDTH;
 
4645
                        break;
 
4646
        }
 
4647
        
 
4648
        /* calculate scaling factor */
 
4649
        startx= sval-(width/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
 
4650
        deltax= cval-(width/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2);
 
4651
        t->fac = deltax / startx;
 
4652
        
 
4653
        /* handle numeric-input stuff */
 
4654
        t->vec[0] = t->fac;
 
4655
        applyNumInput(&t->num, &t->vec[0]);
 
4656
        t->fac = t->vec[0];
 
4657
        headerTimeScale(t, str);
 
4658
        
 
4659
        applyTimeScale(t);
 
4660
 
 
4661
        recalcData(t);
 
4662
 
 
4663
        headerprint(str);
 
4664
        
 
4665
        viewRedrawForce(t);
 
4666
 
 
4667
        return 1;
 
4668
}
 
4669
 
2790
4670
/* ************************************ */
2791
4671
 
2792
4672
void BIF_TransformSetUndo(char *str)
2795
4675
}
2796
4676
 
2797
4677
 
 
4678
void NDofTransform()
 
4679
{
 
4680
    float fval[7];
 
4681
    float maxval = 50.0f; // also serves as threshold
 
4682
    int axis = -1;
 
4683
    int mode = 0;
 
4684
    int i;
 
4685
 
 
4686
        getndof(fval);
 
4687
 
 
4688
        for(i = 0; i < 6; i++)
 
4689
        {
 
4690
                float val = fabs(fval[i]);
 
4691
                if (val > maxval)
 
4692
                {
 
4693
                        axis = i;
 
4694
                        maxval = val;
 
4695
                }
 
4696
        }
 
4697
        
 
4698
        switch(axis)
 
4699
        {
 
4700
                case -1:
 
4701
                        /* No proper axis found */
 
4702
                        break;
 
4703
                case 0:
 
4704
                case 1:
 
4705
                case 2:
 
4706
                        mode = TFM_TRANSLATION;
 
4707
                        break;
 
4708
                case 4:
 
4709
                        mode = TFM_ROTATION;
 
4710
                        break;
 
4711
                case 3:
 
4712
                case 5:
 
4713
                        mode = TFM_TRACKBALL;
 
4714
                        break;
 
4715
                default:
 
4716
                        printf("ndof: what we are doing here ?");
 
4717
        }
 
4718
        
 
4719
        if (mode != 0)
 
4720
        {
 
4721
                initTransform(mode, CTX_NDOF);
 
4722
                Transform();
 
4723
        }
 
4724
}