c557b8df2599f0c2abfd3f62f31719fc2b71054a
[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 #include <string.h>
35
36 #ifndef WIN32
37 #include <unistd.h>
38 #else
39 #include <io.h>
40 #endif   
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_arithb.h"
46
47 #include "DNA_action_types.h"
48 #include "DNA_curve_types.h"
49 #include "DNA_ipo_types.h"
50 #include "DNA_key_types.h"
51 #include "DNA_lattice_types.h"
52 #include "DNA_mesh_types.h"
53 #include "DNA_meshdata_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_scene_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
61 #include "BKE_action.h"
62 #include "BKE_anim.h"
63 #include "BKE_curve.h"
64 #include "BKE_depsgraph.h"
65 #include "BKE_global.h"
66 #include "BKE_ipo.h"
67 #include "BKE_key.h"
68 #include "BKE_library.h"
69 #include "BKE_main.h"
70 #include "BKE_mesh.h"
71 #include "BKE_object.h"
72 #include "BKE_utildefines.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
90 extern ListBase editNurb; /* in editcurve.c */
91
92 /* temporary storage for slider values */
93 /* pretty bad static stuff... is secured in drawaction.c though */
94 float meshslidervals[256] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
95                             0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 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, 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, 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, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
99                             0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
100                             0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
101                             0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
102                                                         0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
103                                                         0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
104                                                         0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
105                                                         0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
106                                                         0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
107                                                         0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
108                                                         0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
109                                                         0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
110
111 static IpoCurve *get_key_icu(Ipo *ipo, int keynum) 
112 {
113         /* return the Ipocurve that has the specified
114          * keynum as ardcode -- return NULL if no such 
115          * curve exists.
116          */
117     IpoCurve *icu;
118         
119         if (!ipo) 
120                 return NULL;
121
122     for (icu = ipo->curve.first; icu ; icu = icu->next) {
123         if (!icu->adrcode) continue;
124         if (icu->adrcode == keynum) return icu;
125     }
126
127     return NULL;
128 }
129
130 BezTriple *get_bezt_icu_time(IpoCurve *icu, float *frame, float *val) 
131 {
132         /* this function tries to find a bezier that is within
133          * 0.25 time units from the specified frame. If there
134          * are more than one such beziers, it returns the
135          * closest one.
136          */
137         int   i;
138         float d, dmin = 0.25, newframe;
139         BezTriple *bezt = NULL;
140         
141         newframe = *frame;
142
143         for (i=0; i<icu->totvert; i++){
144                 d = fabs(icu->bezt[i].vec[1][0] - *frame);
145                 if (d < dmin) {
146                         dmin     = d;
147                         newframe = icu->bezt[i].vec[1][0];
148                         *val     = icu->bezt[i].vec[1][1];
149                         bezt     = icu->bezt + i;
150                 }
151         }
152
153         *frame = newframe;
154         return bezt;
155 }
156
157 static void rvk_slider_func(void *voidob, void *voidkeynum) 
158 {
159         /* the callback for the rvk sliders ... copies the
160          * value from the temporary array into a bezier at the
161          * right frame on the right ipo curve (creating both the
162          * ipo curve and the bezier if needed).
163          */
164         Object *ob= voidob;
165         IpoCurve  *icu=NULL;
166         BezTriple *bezt=NULL;
167         float cfra, rvkval;
168         int keynum = (long) voidkeynum;
169
170         cfra = frame_to_float(CFRA);
171
172         /* ipo on action or ob? */
173         if(ob->ipoflag & OB_ACTION_KEY)
174                 icu = verify_ipocurve(&ob->id, ID_KE, "Shape", NULL, keynum);
175         else 
176                 icu = verify_ipocurve(&ob->id, ID_KE, NULL, NULL, keynum);
177
178         if (icu) {
179                 /* if the ipocurve exists, try to get a bezier
180                  * for this frame
181                  */
182                 bezt = get_bezt_icu_time(icu, &cfra, &rvkval);
183         
184                 /* create the bezier triple if one doesn't exist,
185                  * otherwise modify it's value
186                  */
187                 if (!bezt) {
188                         insert_vert_ipo(icu, cfra, meshslidervals[keynum]);
189                 }
190                 else {
191                         bezt->vec[1][1] = meshslidervals[keynum];
192                 }
193
194                 /* make sure the Ipo's are properly process and
195                  * redraw as necessary
196                  */
197                 sort_time_ipocurve(icu);
198                 testhandles_ipocurve(icu);
199                 
200                 ob->shapeflag &= ~OB_SHAPE_TEMPLOCK;
201                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
202         }
203         else error("Cannot edit this Shape Key");
204         
205         allqueue (REDRAWVIEW3D, 0);
206         allqueue (REDRAWACTION, 0);
207         allqueue (REDRAWNLA, 0);
208         allqueue (REDRAWIPO, 0);
209         allspace(REMAKEIPO, 0);
210 }
211
212 static float getrvkval(Ipo *ipo, int keynum) 
213 {
214         /* get the value of the rvk from the
215          * ipo curve at the current time -- return 0
216          * if no ipo curve exists
217          */
218         IpoCurve  *icu=NULL;
219         BezTriple *bezt=NULL;
220         float     rvkval = 0.0;
221         float     cfra;
222
223         cfra = frame_to_float(CFRA);
224         icu    = get_key_icu(ipo, keynum);
225         if (icu) {
226                 bezt = get_bezt_icu_time(icu, &cfra, &rvkval);
227                 if (!bezt) {
228                         rvkval = eval_icu(icu, cfra);
229                 }
230         }
231
232         return rvkval;
233
234 }
235
236 void make_rvk_slider(uiBlock *block, Object *ob, int keynum,
237                                          int x, int y, int w, int h, char *tip)
238 {
239         /* create a slider for the rvk */
240         uiBut *but;
241         Ipo *ipo= NULL;
242         Key *key= ob_get_key(ob);
243         KeyBlock   *kb;
244         float min, max;
245         int i;
246         
247         if(key==NULL) return;
248         
249         /* ipo on action or ob? */
250         if(ob->ipoflag & OB_ACTION_KEY) {
251                 if(ob->action) {
252                         bActionChannel *achan;
253                         
254                         achan= get_action_channel(ob->action, "Shape");
255                         if(achan) ipo= achan->ipo;
256                 }
257         }
258         else ipo= key->ipo;
259         
260         /* global array */
261         meshslidervals[keynum] = getrvkval(ipo, 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, tip);
280         
281         uiButSetFunc(but, rvk_slider_func, ob, (void *)(long)keynum);
282         // no hilite, the winmatrix is not correct later on...
283         uiButSetFlag(but, UI_NO_HILITE);
284
285 }
286
287 static void default_key_ipo(Key *key)
288 {
289         IpoCurve *icu;
290         BezTriple *bezt;
291         
292         key->ipo= add_ipo("KeyIpo", ID_KE);
293         
294         icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
295                         
296         icu->blocktype= ID_KE;
297         icu->adrcode= KEY_SPEED;
298         icu->flag= IPO_VISIBLE|IPO_SELECT|IPO_AUTO_HORIZ;
299         set_icu_vars(icu);
300         
301         BLI_addtail( &(key->ipo->curve), icu);
302         
303         icu->bezt= bezt= MEM_callocN(2*sizeof(BezTriple), "defaultipo");
304         icu->totvert= 2;
305         
306         bezt->hide= IPO_BEZ;
307         bezt->f1=bezt->f2= bezt->f3= SELECT;
308         bezt->h1= bezt->h2= HD_AUTO;
309         bezt++;
310         bezt->vec[1][0]= 100.0;
311         bezt->vec[1][1]= 1.0;
312         bezt->hide= IPO_BEZ;
313         bezt->f1=bezt->f2= bezt->f3= SELECT;
314         bezt->h1= bezt->h2= HD_AUTO;
315         
316         calchandles_ipocurve(icu);
317 }
318
319         
320
321 /* **************************************** */
322
323 void mesh_to_key(Mesh *me, KeyBlock *kb)
324 {
325         MVert *mvert;
326         float *fp;
327         int a;
328         
329         if(me->totvert==0) return;
330         
331         if(kb->data) MEM_freeN(kb->data);
332         
333         kb->data= MEM_callocN(me->key->elemsize*me->totvert, "kb->data");
334         kb->totelem= me->totvert;
335         
336         mvert= me->mvert;
337         fp= kb->data;
338         for(a=0; a<kb->totelem; a++, fp+=3, mvert++) {
339                 VECCOPY(fp, mvert->co);
340                 
341         }
342 }
343
344 void key_to_mesh(KeyBlock *kb, Mesh *me)
345 {
346         MVert *mvert;
347         float *fp;
348         int a, tot;
349         
350         mvert= me->mvert;
351         fp= kb->data;
352         
353         tot= MIN2(kb->totelem, me->totvert);
354         
355         for(a=0; a<tot; a++, fp+=3, mvert++) {
356                 VECCOPY(mvert->co, fp);
357         }
358 }
359
360 static KeyBlock *add_keyblock(Key *key)
361 {
362         KeyBlock *kb;
363         float curpos= -0.1;
364         int tot;
365         
366         kb= key->block.last;
367         if(kb) curpos= kb->pos;
368         
369         kb= MEM_callocN(sizeof(KeyBlock), "Keyblock");
370         BLI_addtail(&key->block, kb);
371         kb->type= KEY_CARDINAL;
372         tot= BLI_countlist(&key->block);
373         if(tot==1) strcpy(kb->name, "Basis");
374         else sprintf(kb->name, "Key %d", tot-1);
375         kb->adrcode= tot-1;
376         
377         key->totkey++;
378         if(key->totkey==1) key->refkey= kb;
379         
380         
381         if(key->type == KEY_RELATIVE) 
382                 kb->pos= curpos+0.1;
383         else {
384                 curpos= bsystem_time(0, (float)CFRA, 0.0);
385                 if(calc_ipo_spec(key->ipo, KEY_SPEED, &curpos)==0) {
386                         curpos /= 100.0;
387                 }
388                 kb->pos= curpos;
389                 
390                 sort_keys(key);
391         }
392         return kb;
393 }
394
395 void insert_meshkey(Mesh *me, short rel)
396 {
397         Key *key;
398         KeyBlock *kb;
399
400         if(me->key==NULL) {
401                 me->key= add_key( (ID *)me);
402
403                 if(rel)
404                         me->key->type = KEY_RELATIVE;
405                 else
406                         default_key_ipo(me->key);
407         }
408         key= me->key;
409         
410         kb= add_keyblock(key);
411         
412         mesh_to_key(me, kb);
413 }
414
415 /* ******************** */
416
417 void latt_to_key(Lattice *lt, KeyBlock *kb)
418 {
419         BPoint *bp;
420         float *fp;
421         int a, tot;
422         
423         tot= lt->pntsu*lt->pntsv*lt->pntsw;
424         if(tot==0) return;
425         
426         if(kb->data) MEM_freeN(kb->data);
427         
428         kb->data= MEM_callocN(lt->key->elemsize*tot, "kb->data");
429         kb->totelem= tot;
430         
431         bp= lt->def;
432         fp= kb->data;
433         for(a=0; a<kb->totelem; a++, fp+=3, bp++) {
434                 VECCOPY(fp, bp->vec);
435         }
436 }
437
438 void key_to_latt(KeyBlock *kb, Lattice *lt)
439 {
440         BPoint *bp;
441         float *fp;
442         int a, tot;
443         
444         bp= lt->def;
445         fp= kb->data;
446         
447         tot= lt->pntsu*lt->pntsv*lt->pntsw;
448         tot= MIN2(kb->totelem, tot);
449         
450         for(a=0; a<tot; a++, fp+=3, bp++) {
451                 VECCOPY(bp->vec, fp);
452         }
453         
454 }
455
456 /* exported to python... hrms, should not, use object levels! (ton) */
457 void insert_lattkey(Lattice *lt, short rel)
458 {
459         Key *key;
460         KeyBlock *kb;
461         
462         if(lt->key==NULL) {
463                 lt->key= add_key( (ID *)lt);
464                 default_key_ipo(lt->key);
465         }
466         key= lt->key;
467         
468         kb= add_keyblock(key);
469         
470         latt_to_key(lt, kb);
471 }
472
473 /* ******************************** */
474
475 void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb)
476 {
477         Nurb *nu;
478         BezTriple *bezt;
479         BPoint *bp;
480         float *fp;
481         int a, tot;
482         
483         /* count */
484         tot= count_curveverts(nurb);
485         if(tot==0) return;
486         
487         if(kb->data) MEM_freeN(kb->data);
488         
489         kb->data= MEM_callocN(cu->key->elemsize*tot, "kb->data");
490         kb->totelem= tot;
491         
492         nu= nurb->first;
493         fp= kb->data;
494         while(nu) {
495                 
496                 if(nu->bezt) {
497                         bezt= nu->bezt;
498                         a= nu->pntsu;
499                         while(a--) {
500                                 VECCOPY(fp, bezt->vec[0]);
501                                 fp+= 3;
502                                 VECCOPY(fp, bezt->vec[1]);
503                                 fp+= 3;
504                                 VECCOPY(fp, bezt->vec[2]);
505                                 fp+= 3;
506                                 fp[0]= bezt->alfa;
507                                 fp+= 3; /* alphas */
508                                 bezt++;
509                         }
510                 }
511                 else {
512                         bp= nu->bp;
513                         a= nu->pntsu*nu->pntsv;
514                         while(a--) {
515                                 VECCOPY(fp, bp->vec);
516                                 fp[3]= bp->alfa;
517                                 
518                                 fp+= 4;
519                                 bp++;
520                         }
521                 }
522                 nu= nu->next;
523         }
524 }
525
526 void key_to_curve(KeyBlock *kb, Curve  *cu, ListBase *nurb)
527 {
528         Nurb *nu;
529         BezTriple *bezt;
530         BPoint *bp;
531         float *fp;
532         int a, tot;
533         
534         nu= nurb->first;
535         fp= kb->data;
536         
537         tot= count_curveverts(nurb);
538
539         tot= MIN2(kb->totelem, tot);
540         
541         while(nu && tot>0) {
542                 
543                 if(nu->bezt) {
544                         bezt= nu->bezt;
545                         a= nu->pntsu;
546                         while(a-- && tot>0) {
547                                 VECCOPY(bezt->vec[0], fp);
548                                 fp+= 3;
549                                 VECCOPY(bezt->vec[1], fp);
550                                 fp+= 3;
551                                 VECCOPY(bezt->vec[2], fp);
552                                 fp+= 3;
553                                 bezt->alfa= fp[0];
554                                 fp+= 3; /* alphas */
555                         
556                                 tot-= 3;
557                                 bezt++;
558                         }
559                 }
560                 else {
561                         bp= nu->bp;
562                         a= nu->pntsu*nu->pntsv;
563                         while(a-- && tot>0) {
564                                 VECCOPY(bp->vec, fp);
565                                 bp->alfa= fp[3];
566                                 
567                                 fp+= 4;
568                                 tot--;
569                                 bp++;
570                         }
571                 }
572                 nu= nu->next;
573         }
574 }
575
576
577 void insert_curvekey(Curve *cu, short rel) 
578 {
579         Key *key;
580         KeyBlock *kb;
581         
582         if(cu->key==NULL) {
583                 cu->key= add_key( (ID *)cu);
584
585                 if (rel)
586                         cu->key->type = KEY_RELATIVE;
587                 else
588                         default_key_ipo(cu->key);
589         }
590         key= cu->key;
591         
592         kb= add_keyblock(key);
593         
594         if(editNurb.first) curve_to_key(cu, kb, &editNurb);
595         else curve_to_key(cu, kb, &cu->nurb);
596 }
597
598
599 /* ******************** */
600
601 void insert_shapekey(Object *ob)
602 {
603         if(get_mesh(ob) && get_mesh(ob)->mr) {
604                 error("Cannot create shape keys on a multires mesh.");
605         }
606         else {
607                 Key *key;
608         
609                 if(ob->type==OB_MESH) insert_meshkey(ob->data, 1);
610                 else if ELEM(ob->type, OB_CURVE, OB_SURF) insert_curvekey(ob->data, 1);
611                 else if(ob->type==OB_LATTICE) insert_lattkey(ob->data, 1);
612         
613                 key= ob_get_key(ob);
614                 ob->shapenr= BLI_countlist(&key->block);
615         
616                 BIF_undo_push("Add Shapekey");
617                 allspace(REMAKEIPO, 0);
618                 allqueue(REDRAWIPO, 0);
619                 allqueue(REDRAWACTION, 0);
620                 allqueue(REDRAWNLA, 0);
621                 allqueue(REDRAWBUTSOBJECT, 0);
622                 allqueue(REDRAWBUTSEDIT, 0);
623         }
624 }
625
626 void delete_key(Object *ob)
627 {
628         KeyBlock *kb;
629         Key *key;
630         IpoCurve *icu;
631         
632         key= ob_get_key(ob);
633         if(key==NULL) return;
634         
635         kb= BLI_findlink(&key->block, ob->shapenr-1);
636
637         if(kb) {
638                 BLI_remlink(&key->block, kb);
639                 key->totkey--;
640                 if(key->refkey== kb) key->refkey= key->block.first;
641                         
642                 if(kb->data) MEM_freeN(kb->data);
643                 MEM_freeN(kb);
644                 
645                 for(kb= key->block.first; kb; kb= kb->next) {
646                         if(kb->adrcode>=ob->shapenr)
647                                 kb->adrcode--;
648                 }
649                 
650                 if(key->ipo) {
651                         
652                         for(icu= key->ipo->curve.first; icu; icu= icu->next) {
653                                 if(icu->adrcode==ob->shapenr-1) {
654                                         BLI_remlink(&key->ipo->curve, icu);
655                                         free_ipo_curve(icu);
656                                         break;
657                                 }
658                         }
659                         for(icu= key->ipo->curve.first; icu; icu= icu->next) 
660                                 if(icu->adrcode>=ob->shapenr)
661                                         icu->adrcode--;
662                 }               
663                 
664                 if(ob->shapenr>1) ob->shapenr--;
665         }
666         
667         if(key->totkey==0) {
668                 if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= NULL;
669                 else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= NULL;
670                 else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= NULL;
671
672                 free_libblock_us(&(G.main->key), key);
673                 scrarea_queue_headredraw(curarea);      /* ipo remove too */
674         }
675         
676         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
677         
678         BIF_undo_push("Delete Shapekey");
679         allqueue(REDRAWVIEW3D, 0);
680         allqueue(REDRAWBUTSEDIT, 0);
681         allspace(REMAKEIPO, 0);
682         allqueue(REDRAWIPO, 0);
683 }
684
685 void move_keys(Object *ob)
686 {
687         Key *key;
688         KeyBlock *kb;
689         float div, dy, oldpos, vec[3], dvec[3];
690         int afbreek=0, firsttime= 1;
691         unsigned short event = 0;
692         short mval[2], val, xo, yo;
693         char str[32];
694         
695         if(G.sipo->blocktype!=ID_KE) return;
696         
697         if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
698         if(G.sipo->editipo==NULL) return;
699
700         key= ob_get_key(ob);
701         if(key==NULL) return;
702         
703         /* which kb is involved */
704         kb= BLI_findlink(&key->block, ob->shapenr-1);
705         if(kb==NULL) return;    
706         
707         oldpos= kb->pos;
708         
709         getmouseco_areawin(mval);
710         xo= mval[0];
711         yo= mval[1];
712         dvec[0]=dvec[1]=dvec[2]= 0.0; 
713
714         while(afbreek==0) {
715                 getmouseco_areawin(mval);
716                 if(mval[0]!=xo || mval[1]!=yo || firsttime) {
717                         firsttime= 0;
718                         
719                         dy= (float)(mval[1]- yo);
720
721                         div= (float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
722                         dvec[1]+= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
723                         
724                         VECCOPY(vec, dvec);
725
726                         apply_keyb_grid(vec, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID);
727                         apply_keyb_grid(vec+1, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID);
728
729                         kb->pos= oldpos+vec[1];
730                         
731                         sprintf(str, "Y: %.3f  ", vec[1]);
732                         headerprint(str);
733                         
734                         xo= mval[0];
735                         yo= mval[1];
736                                 
737                         force_draw(0);
738                 }
739                 else BIF_wait_for_statechange();
740                 
741                 while(qtest()) {
742                         event= extern_qread(&val);
743                         if(val) {
744                                 switch(event) {
745                                 case ESCKEY:
746                                 case LEFTMOUSE:
747                                 case SPACEKEY:
748                                         afbreek= 1;
749                                         break;
750                                 default:
751                                         arrows_move_cursor(event);
752                                 }
753                         }
754                 }
755         }
756         
757         if(event==ESCKEY) {
758                 kb->pos= oldpos;
759         }
760         
761         sort_keys(key);
762         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
763         
764         /* for boundbox */
765         editipo_changed(G.sipo, 0);
766
767         BIF_undo_push("Move Shapekey(s)");
768         allspace(REMAKEIPO, 0);
769         allqueue(REDRAWIPO, 0);
770         allqueue(REDRAWVIEW3D, 0);
771         allqueue(REDRAWBUTSEDIT, 0);
772         scrarea_queue_redraw(curarea);
773 }