Support for using the action window as a tool for modifying
[blender.git] / source / blender / src / editkey.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <math.h>
34
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #ifndef WIN32
40 #include <unistd.h>
41 #else
42 #include <io.h>
43 #include "BLI_winstuff.h"
44 #endif   
45 #include "MEM_guardedalloc.h"
46
47 #include "BLI_blenlib.h"
48 #include "BLI_arithb.h"
49 #include "BLI_editVert.h"
50
51 #include "DNA_curve_types.h"
52 #include "DNA_ipo_types.h"
53 #include "DNA_key_types.h"
54 #include "DNA_mesh_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_screen_types.h"
57 #include "DNA_space_types.h"
58 #include "DNA_userdef_types.h"
59 #include "DNA_view2d_types.h"
60 #include "DNA_lattice_types.h"
61 #include "DNA_scene_types.h"
62
63 #include "BKE_utildefines.h"
64 #include "BKE_anim.h"
65 #include "BKE_curve.h"
66 #include "BKE_global.h"
67 #include "BKE_ipo.h"
68 #include "BKE_key.h"
69 #include "BKE_library.h"
70 #include "BKE_main.h"
71 #include "BKE_object.h"
72 #include "BKE_displist.h"
73
74 #include "BIF_editkey.h"
75 #include "BIF_editview.h"
76 #include "BIF_mywindow.h"
77 #include "BIF_screen.h"
78 #include "BIF_space.h"
79 #include "BIF_toolbox.h"
80 #include "BIF_interface.h"
81
82 #include "BSE_editipo.h"
83 #include "BSE_trans_types.h"
84
85 #include "BDR_editobject.h"
86
87 #include "blendef.h"
88 #include "mydevice.h"
89 #include "ipo.h"
90 #include "interface.h"
91
92 extern ListBase editNurb; /* in editcurve.c */
93
94 /* temporary storage for slider values */
95 float meshslidervals[32] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
96                             0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
97                             0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
98                             0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
99
100 static IpoCurve *get_key_icu(Key *key, int keynum) {
101         /* return the Ipocurve that has the specified
102          * keynum as ardcode -- return NULL if no such 
103          * curve exists.
104          */
105     IpoCurve *icu;
106         if (!(key->ipo)) {
107                 key->ipo = get_ipo(key, ID_KE, 1);
108                 return NULL;
109         }
110
111
112     for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
113         if (!icu->adrcode) continue;
114         if (icu->adrcode == keynum) return icu;
115     }
116
117     return NULL;
118 }
119
120 static BezTriple *get_bezt_icu_time(IpoCurve *icu, float *frame, float *val) {
121         /* this function tries to find a bezier that is within
122          * 0.25 time units from the specified frame. If there
123          * are more than one such beziers, it returns the
124          * closest one.
125          */
126         int   i;
127         float d, dmin = 0.25, newframe;
128         BezTriple *bezt = NULL;
129         
130         newframe = *frame;
131
132         for (i=0; i<icu->totvert; i++){
133                 d = fabs(icu->bezt[i].vec[1][0] - *frame);
134                 if (d < dmin) {
135                         dmin     = d;
136                         newframe = icu->bezt[i].vec[1][0];
137                         *val     = icu->bezt[i].vec[1][1];
138                         bezt     = icu->bezt + i;
139                 }
140         }
141
142         *frame = newframe;
143         return bezt;
144 }
145
146 static void rvk_slider_func(void *voidkey, void *voidkeynum) {
147         /* the callback for the rvk sliders ... copies the
148          * value from the temporary array into a bezier at the
149          * right frame on the right ipo curve (creating both the
150          * ipo curve and the bezier if needed).
151          */
152         int       *keynum = (int *) voidkeynum;
153         Key       *key = (Key *) voidkey;
154         float     cfra, rvkval;
155         IpoCurve  *icu=NULL;
156         BezTriple *bezt=NULL;
157
158         cfra = frame_to_float(CFRA);
159
160         icu    = get_key_icu(key, *keynum);
161
162         if (icu) {
163                 /* if the ipocurve exists, try to get a bezier
164                  * for this frame
165                  */
166                 bezt = get_bezt_icu_time(icu, &cfra, &rvkval);
167         }
168         else {
169                 /* create an IpoCurve if one doesn't already
170                  * exist.
171                  */
172                 icu = get_ipocurve(key->from, GS(key->from->name), 
173                                                    *keynum, key->ipo);
174         }
175         
176         /* create the bezier triple if one doesn't exist,
177          * otherwise modify it's value
178          */
179         if (!bezt) {
180                 insert_vert_ipo(icu, cfra, meshslidervals[*keynum]);
181         }
182         else {
183                 bezt->vec[1][1] = meshslidervals[*keynum];
184         }
185
186         /* make sure the Ipo's are properly process and
187          * redraw as necessary
188          */
189         sort_time_ipocurve(icu);
190         testhandles_ipocurve(icu);
191
192         do_all_ipos();
193         do_spec_key(key);
194         /* if I'm deformed by a lattice, update my
195          * displists
196          */
197         makeDispList(OBACT);
198
199         /* if I'm a lattice, update the displists of
200          * my children
201          */
202         if (OBACT->type==OB_LATTICE ) {
203                 Base *base;
204
205                 base= FIRSTBASE;
206                 while(base) {
207                         if (base->object->parent == OBACT) {
208                                 makeDispList(base->object);
209                         }
210                         base= base->next;
211                 }
212         }
213         allqueue (REDRAWVIEW3D, 0);
214         allqueue (REDRAWACTION, 0);
215         allqueue (REDRAWNLA, 0);
216         allqueue (REDRAWIPO, 0);
217
218 }
219
220 static float getrvkval(Key *key, int keynum) {
221         /* get the value of the rvk from the
222          * ipo curve at the current time -- return 0
223          * if no ipo curve exists
224          */
225         IpoCurve  *icu=NULL;
226         BezTriple *bezt=NULL;
227         float     rvkval = 0.0;
228         float     cfra;
229
230         cfra = frame_to_float(CFRA);
231         icu    = get_key_icu(key, keynum);
232         if (icu) {
233                 bezt = get_bezt_icu_time(icu, &cfra, &rvkval);
234                 if (!bezt) {
235                         rvkval = eval_icu(icu, cfra);
236                 }
237         }
238
239         return rvkval;
240
241 }
242
243 void make_rvk_slider(uiBlock *block, Key *key, int keynum,
244                                          int x, int y, int w, int h)
245 {
246         /* create a slider for the rvk */
247         uiBut         *but;
248         KeyBlock   *kb;
249         float min, max;
250         int i;
251
252         /* dang, need to pass a pointer to int to uiButSetFunc
253          * that is on the heap, not the stack ... hence this
254          * kludgy static array
255          */
256         static int keynums[] = {0,1,2,3,4,5,6,7,
257                                                         8,9,10,11,12,13,14,15,
258                                                         16,17,18,19,20,21,22,23,
259                                                         24,25,26,27,28,29,30,31};
260
261         meshslidervals[keynum] = getrvkval(key, keynum);
262
263         kb= key->block.first;
264         for (i=0; i<keynum; ++i) kb = kb->next; 
265
266         if ( (kb->slidermin >= kb->slidermax) ) {
267                 kb->slidermin = 0.0;
268                 kb->slidermax = 1.0;
269         }
270
271         min = (kb->slidermin < meshslidervals[keynum]) ? 
272                 kb->slidermin: meshslidervals[keynum];
273
274         max = (kb->slidermax > meshslidervals[keynum]) ? 
275                 kb->slidermax: meshslidervals[keynum];
276
277         but=uiDefButF(block, NUMSLI, REDRAWVIEW3D, "",
278                                   x, y , w, h,
279                                   meshslidervals+keynum, min, max, 10, 2,
280                                   "Slider to control rvk");
281         uiButSetFunc(but, rvk_slider_func, key, keynums+keynum);
282 }
283
284 static void default_key_ipo(Key *key)
285 {
286         IpoCurve *icu;
287         BezTriple *bezt;
288         
289         key->ipo= add_ipo("KeyIpo", ID_KE);
290         
291         icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
292                         
293         icu->blocktype= ID_KE;
294         icu->adrcode= KEY_SPEED;
295         icu->flag= IPO_VISIBLE+IPO_SELECT;
296         set_icu_vars(icu);
297         
298         BLI_addtail( &(key->ipo->curve), icu);
299         
300         icu->bezt= bezt= MEM_callocN(2*sizeof(BezTriple), "defaultipo");
301         icu->totvert= 2;
302         
303         bezt->hide= IPO_BEZ;
304         bezt->f1=bezt->f2= bezt->f3= SELECT;
305         bezt->h1= bezt->h2= HD_AUTO;
306         bezt++;
307         bezt->vec[1][0]= 100.0;
308         bezt->vec[1][1]= 1.0;
309         bezt->hide= IPO_BEZ;
310         bezt->f1=bezt->f2= bezt->f3= SELECT;
311         bezt->h1= bezt->h2= HD_AUTO;
312         
313         calchandles_ipocurve(icu);
314 }
315
316         
317
318 /* **************************************** */
319
320 void mesh_to_key(Mesh *me, KeyBlock *kb)
321 {
322         MVert *mvert;
323         float *fp;
324         int a;
325         
326         if(me->totvert==0) return;
327         
328         if(kb->data) MEM_freeN(kb->data);
329         
330         kb->data= MEM_callocN(me->key->elemsize*me->totvert, "kb->data");
331         kb->totelem= me->totvert;
332         
333         mvert= me->mvert;
334         fp= kb->data;
335         for(a=0; a<kb->totelem; a++, fp+=3, mvert++) {
336                 VECCOPY(fp, mvert->co);
337                 
338         }
339 }
340
341 void key_to_mesh(KeyBlock *kb, Mesh *me)
342 {
343         MVert *mvert;
344         float *fp;
345         int a, tot;
346         
347         mvert= me->mvert;
348         fp= kb->data;
349         
350         tot= MIN2(kb->totelem, me->totvert);
351         
352         for(a=0; a<tot; a++, fp+=3, mvert++) {
353                 VECCOPY(mvert->co, fp);
354         }
355 }
356
357
358
359 void insert_meshkey(Mesh *me)
360 {
361         Key *key;
362         KeyBlock *kb, *kkb;
363         float curpos;
364         short rel;
365
366         if(me->key==0) {
367                 me->key= add_key( (ID *)me);
368                 rel = pupmenu("Relative Vertex Keys? %t|Yes Please! %x1"
369                                           "|Naw, the other kind %x2");
370                 switch (rel) {
371                 case 1:
372                         me->key->type = KEY_RELATIVE;
373                         break;
374                 default:
375                         default_key_ipo(me->key);
376                         break;
377                 }
378         }
379         key= me->key;
380         
381         kb= MEM_callocN(sizeof(KeyBlock), "Keyblock");
382         BLI_addtail(&key->block, kb);
383         kb->type= KEY_CARDINAL;
384         
385         curpos= bsystem_time(0, 0, (float)CFRA, 0.0);
386         if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &curpos)==0) {
387                 curpos /= 100.0;
388         }
389         kb->pos= curpos;
390         
391         key->totkey++;
392         if(key->totkey==1) key->refkey= kb;
393         
394         mesh_to_key(me, kb);
395         
396         sort_keys(me->key);
397
398         /* curent active: */
399         kkb= key->block.first;
400         while(kkb) {
401                 kkb->flag &= ~SELECT;
402                 if(kkb==kb) kkb->flag |= SELECT;
403                 
404                 kkb= kkb->next;
405         }
406 }
407
408 /* ******************** */
409
410 void latt_to_key(Lattice *lt, KeyBlock *kb)
411 {
412         BPoint *bp;
413         float *fp;
414         int a, tot;
415         
416         tot= lt->pntsu*lt->pntsv*lt->pntsw;
417         if(tot==0) return;
418         
419         if(kb->data) MEM_freeN(kb->data);
420         
421         kb->data= MEM_callocN(lt->key->elemsize*tot, "kb->data");
422         kb->totelem= tot;
423         
424         bp= lt->def;
425         fp= kb->data;
426         for(a=0; a<kb->totelem; a++, fp+=3, bp++) {
427                 VECCOPY(fp, bp->vec);
428         }
429 }
430
431 void key_to_latt(KeyBlock *kb, Lattice *lt)
432 {
433         BPoint *bp;
434         float *fp;
435         int a, tot;
436         
437         bp= lt->def;
438         fp= kb->data;
439         
440         tot= lt->pntsu*lt->pntsv*lt->pntsw;
441         tot= MIN2(kb->totelem, tot);
442         
443         for(a=0; a<tot; a++, fp+=3, bp++) {
444                 VECCOPY(bp->vec, fp);
445         }
446         
447 }
448
449 void insert_lattkey(Lattice *lt)
450 {
451         Key *key;
452         KeyBlock *kb, *kkb;
453         float curpos;
454         
455         if(lt->key==0) {
456                 lt->key= add_key( (ID *)lt);
457                 default_key_ipo(lt->key);
458         }
459         key= lt->key;
460         
461         kb= MEM_callocN(sizeof(KeyBlock), "Keyblock");
462         BLI_addtail(&key->block, kb);
463         kb->type= KEY_CARDINAL;
464         
465         curpos= bsystem_time(0, 0, (float)CFRA, 0.0);
466         if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &curpos)==0) {
467                 curpos /= 100.0;
468         }
469         kb->pos= curpos;
470         
471         key->totkey++;
472         if(key->totkey==1) key->refkey= kb;
473         
474         latt_to_key(lt, kb);
475         
476         sort_keys(lt->key);
477
478         /* curent active: */
479         kkb= key->block.first;
480         while(kkb) {
481                 kkb->flag &= ~SELECT;
482                 if(kkb==kb) kkb->flag |= SELECT;
483                 
484                 kkb= kkb->next;
485         }
486 }
487
488 /* ******************************** */
489
490 void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb)
491 {
492         Nurb *nu;
493         BezTriple *bezt;
494         BPoint *bp;
495         float *fp;
496         int a, tot;
497         
498         /* count */
499         tot= count_curveverts(nurb);
500         if(tot==0) return;
501         
502         if(kb->data) MEM_freeN(kb->data);
503         
504         kb->data= MEM_callocN(cu->key->elemsize*tot, "kb->data");
505         kb->totelem= tot;
506         
507         nu= nurb->first;
508         fp= kb->data;
509         while(nu) {
510                 
511                 if(nu->bezt) {
512                         bezt= nu->bezt;
513                         a= nu->pntsu;
514                         while(a--) {
515                                 VECCOPY(fp, bezt->vec[0]);
516                                 fp+= 3;
517                                 VECCOPY(fp, bezt->vec[1]);
518                                 fp+= 3;
519                                 VECCOPY(fp, bezt->vec[2]);
520                                 fp+= 3;
521                                 fp+= 3; /* alphas */
522                                 bezt++;
523                         }
524                 }
525                 else {
526                         bp= nu->bp;
527                         a= nu->pntsu*nu->pntsv;
528                         while(a--) {
529                                 VECCOPY(fp, bp->vec);
530                                 fp[3]= bp->alfa;
531                                 
532                                 fp+= 4;
533                                 bp++;
534                         }
535                 }
536                 nu= nu->next;
537         }
538 }
539
540 void key_to_curve(KeyBlock *kb, Curve  *cu, ListBase *nurb)
541 {
542         Nurb *nu;
543         BezTriple *bezt;
544         BPoint *bp;
545         float *fp;
546         int a, tot;
547         
548         nu= nurb->first;
549         fp= kb->data;
550         
551         tot= count_curveverts(nurb);
552
553         tot= MIN2(kb->totelem, tot);
554         
555         while(nu && tot>0) {
556                 
557                 if(nu->bezt) {
558                         bezt= nu->bezt;
559                         a= nu->pntsu;
560                         while(a-- && tot>0) {
561                                 VECCOPY(bezt->vec[0], fp);
562                                 fp+= 3;
563                                 VECCOPY(bezt->vec[1], fp);
564                                 fp+= 3;
565                                 VECCOPY(bezt->vec[2], fp);
566                                 fp+= 3;
567                                 fp+= 3; /* alphas */
568                                 
569                                 tot-= 3;
570                                 bezt++;
571                         }
572                 }
573                 else {
574                         bp= nu->bp;
575                         a= nu->pntsu*nu->pntsv;
576                         while(a-- && tot>0) {
577                                 VECCOPY(bp->vec, fp);
578                                 bp->alfa= fp[3];
579                                 
580                                 fp+= 4;
581                                 tot--;
582                                 bp++;
583                         }
584                 }
585                 nu= nu->next;
586         }
587 }
588
589
590
591 void insert_curvekey(Curve *cu)
592 {
593         Key *key;
594         KeyBlock *kb, *kkb;
595         float curpos;
596         
597         if(cu->key==0) {
598                 cu->key= add_key( (ID *)cu);
599                 default_key_ipo(cu->key);
600         }
601         key= cu->key;
602         
603         kb= MEM_callocN(sizeof(KeyBlock), "Keyblock");
604         BLI_addtail(&key->block, kb);
605         kb->type= KEY_CARDINAL;
606         
607         curpos= bsystem_time(0, 0, (float)CFRA, 0.0);
608         if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &curpos)==0) {
609                 curpos /= 100.0;
610         }
611         kb->pos= curpos;
612         
613         key->totkey++;
614         if(key->totkey==1) key->refkey= kb;
615         
616         if(editNurb.first) curve_to_key(cu, kb, &editNurb);
617         else curve_to_key(cu, kb, &cu->nurb);
618         
619         sort_keys(cu->key);
620
621         /* curent active: */
622         kkb= key->block.first;
623         while(kkb) {
624                 kkb->flag &= ~SELECT;
625                 if(kkb==kb) kkb->flag |= SELECT;
626                 
627                 kkb= kkb->next;
628         }
629 }
630
631
632 /* ******************** */
633
634 Key *give_current_key(Object *ob)
635 {
636         Mesh *me;
637         Curve *cu;
638         Lattice *lt;
639         
640         if(ob->type==OB_MESH) {
641                 me= ob->data;
642                 return me->key;
643         }
644         else if ELEM(ob->type, OB_CURVE, OB_SURF) {
645                 cu= ob->data;
646                 return cu->key;
647         }
648         else if(ob->type==OB_LATTICE) {
649                 lt= ob->data;
650                 return lt->key;
651         }
652         return 0;
653 }
654
655 void showkeypos(Key *key, KeyBlock *kb)
656 {
657         Object *ob;
658         Mesh *me;
659         Lattice *lt;
660         Curve *cu;
661         int tot;
662         
663         /* from ipo */
664         ob= OBACT;
665         if(ob==0) return;
666         
667         if(key == give_current_key(ob)) {
668                 
669                 if(ob->type==OB_MESH) {
670                         me= ob->data;
671
672                         cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, kb, 0);
673
674                         make_displists_by_obdata(me);
675                 }
676                 else if(ob->type==OB_LATTICE) {
677                         lt= ob->data;
678                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
679                         
680                         cp_key(0, tot, tot, (char *)lt->def->vec, lt->key, kb, 0);
681
682                         make_displists_by_parent(ob);
683                 }
684                 else if ELEM(ob->type, OB_CURVE, OB_SURF) {
685                         cu= ob->data;
686                         tot= count_curveverts(&cu->nurb);
687                         cp_cu_key(cu, kb, 0, tot);
688
689                         make_displists_by_obdata(cu);
690                 }
691                 
692                 allqueue(REDRAWVIEW3D, 0);
693         }
694 }
695
696 void deselectall_key(void)
697 {
698         KeyBlock *kb;
699         Key *key;
700         
701         if(G.sipo->blocktype!=ID_KE) return;
702         key= (Key *)G.sipo->from;
703         if(key==0) return;
704         
705         kb= key->block.first;
706         while(kb) {
707                 kb->flag &= ~SELECT;
708                 kb= kb->next;
709         }
710 }
711
712
713 void delete_key(void)
714 {
715         KeyBlock *kb, *kbn;
716         Key *key;
717         
718         if(G.sipo->blocktype!=ID_KE) return;
719
720         if(okee("Erase selected keys")==0) return;
721         
722         key= (Key *)G.sipo->from;
723         if(key==0) return;
724         
725         kb= key->block.first;
726         while(kb) {
727                 kbn= kb->next;
728                 if(kb->flag & SELECT) {
729                         BLI_remlink(&key->block, kb);
730                         key->totkey--;
731                         if(key->refkey== kb) key->refkey= key->block.first;
732                         
733                         if(kb->data) MEM_freeN(kb->data);
734                         MEM_freeN(kb);
735                         
736                 }
737                 kb= kbn;
738         }
739         
740         if(key->totkey==0) {
741                 if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= 0;
742                 else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= 0;
743                 else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= 0;
744
745                 free_libblock_us(&(G.main->key), key);
746                 scrarea_queue_headredraw(curarea);      /* ipo remove too */
747         }
748         else do_spec_key(key);
749         
750         allqueue(REDRAWVIEW3D, 0);
751         scrarea_queue_winredraw(curarea);
752 }
753
754 void move_keys(void)
755 {
756         Key *key;
757         KeyBlock *kb;
758         TransVert *transmain, *tv;
759         float div, dy, vec[3], dvec[3];
760         int a, tot=0, afbreek=0, firsttime= 1;
761         unsigned short event = 0;
762         short mval[2], val, xo, yo;
763         char str[32];
764         
765         if(G.sipo->blocktype!=ID_KE) return;
766         
767         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
768         if(G.sipo->editipo==0) return;
769
770         key= (Key *)G.sipo->from;
771         if(key==0) return;
772         
773         /* which keys are involved */
774         kb= key->block.first;
775         while(kb) {
776                 if(kb->flag & SELECT) tot++;
777                 kb= kb->next;
778         }
779         
780         if(tot==0) return;      
781         
782         tv=transmain= MEM_callocN(tot*sizeof(TransVert), "transmain");
783         kb= key->block.first;
784         while(kb) {
785                 if(kb->flag & SELECT) {
786                         tv->loc= &kb->pos;
787                         tv->oldloc[0]= kb->pos;
788                         tv++;
789                 }
790                 kb= kb->next;
791         }
792         
793         getmouseco_areawin(mval);
794         xo= mval[0];
795         yo= mval[1];
796         dvec[0]=dvec[1]=dvec[2]= 0.0; 
797         
798
799         while(afbreek==0) {
800                 getmouseco_areawin(mval);
801                 if(mval[0]!=xo || mval[1]!=yo || firsttime) {
802                         firsttime= 0;
803                         
804                         dy= (float)(mval[1]- yo);
805
806                         div= (float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
807                         dvec[1]+= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
808                         
809                         VECCOPY(vec, dvec);
810
811                         apply_keyb_grid(vec, 0.0, 1.0, 0.1, U.flag & AUTOGRABGRID);
812                         apply_keyb_grid(vec+1, 0.0, 1.0, 0.1, U.flag & AUTOGRABGRID);
813
814                         tv= transmain;
815                         for(a=0; a<tot; a++, tv++) {
816                                 tv->loc[0]= tv->oldloc[0]+vec[1];
817                         }
818                         
819                         sprintf(str, "Y: %.3f  ", vec[1]);
820                         headerprint(str);
821                         
822                         xo= mval[0];
823                         yo= mval[1];
824                                 
825                         force_draw();
826                 }
827                 else BIF_wait_for_statechange();
828                 
829                 while(qtest()) {
830                         event= extern_qread(&val);
831                         if(val) {
832                                 switch(event) {
833                                 case ESCKEY:
834                                 case LEFTMOUSE:
835                                 case SPACEKEY:
836                                         afbreek= 1;
837                                         break;
838                                 default:
839                                         arrows_move_cursor(event);
840                                 }
841                         }
842                 }
843         }
844         
845         if(event==ESCKEY) {
846                 tv= transmain;
847                 for(a=0; a<tot; a++, tv++) {
848                         tv->loc[0]= tv->oldloc[0];
849                 }
850         }
851         
852         sort_keys(key);
853         do_spec_key(key);
854         
855         /* for boundbox */
856         editipo_changed(G.sipo, 0);
857
858         MEM_freeN(transmain);   
859         allqueue(REDRAWVIEW3D, 0);
860         scrarea_queue_redraw(curarea);
861 }