smooth view transformations, set the smoothview value to about 250 and the view anima...
[blender.git] / source / blender / src / toets.c
1 /**
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30
31  *
32  *
33  * General blender hot keys (toets = dutch), special hotkeys are in space.c
34  *
35  */
36
37 #include <string.h>
38 #include <math.h>
39
40 #ifdef WIN32
41 #include "BLI_winstuff.h"
42 #endif
43
44 #include "MEM_guardedalloc.h"
45
46 #include "PIL_time.h"
47
48 #include "nla.h"        /* Only for the #ifdef flag - To be removed later */
49
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
52
53 #include "DNA_object_types.h"
54 #include "DNA_screen_types.h"
55 #include "DNA_scene_types.h"
56 #include "DNA_space_types.h"
57 #include "DNA_view3d_types.h"
58 #include "DNA_userdef_types.h"
59
60 #include "BKE_action.h"
61 #include "BKE_anim.h"
62 #include "BKE_blender.h"
63 #include "BKE_depsgraph.h"
64 #include "BKE_displist.h"
65 #include "BKE_global.h"
66 #include "BKE_image.h"
67 #include "BKE_ipo.h"
68 #include "BKE_key.h"
69 #include "BKE_scene.h"
70 #include "BKE_utildefines.h"
71
72 #include "BIF_butspace.h"
73 #include "BIF_editseq.h"
74 #include "BIF_editsound.h"
75 #include "BIF_editmesh.h"
76 #include "BIF_interface.h"
77 #include "BKE_object.h"
78 #include "BIF_poseobject.h"
79 #include "BIF_previewrender.h"
80 #include "BIF_renderwin.h"
81 #include "BIF_retopo.h"
82 #include "BIF_screen.h"
83 #include "BIF_space.h"
84 #include "BIF_toets.h"
85 #include "BIF_toolbox.h"
86 #include "BIF_usiblender.h"
87 #include "BIF_writeimage.h"
88
89 #include "BDR_sculptmode.h"
90 #include "BDR_vpaint.h"
91 #include "BDR_editobject.h"
92 #include "BDR_editface.h"
93
94 #include "BSE_filesel.h"        /* For activate_fileselect */
95 #include "BSE_drawview.h"       /* For play_anim */
96 #include "BSE_view.h"
97 #include "BSE_edit.h"
98 #include "BSE_editipo.h"
99 #include "BSE_headerbuttons.h"
100 #include "BSE_seqaudio.h"
101
102 #include "blendef.h"
103
104 #include "IMB_imbuf.h"
105 #include "IMB_imbuf_types.h"
106
107 #include "mydevice.h"
108
109 #include "BIF_poseobject.h"
110
111 /* ------------------------------------------------------------------------- */
112
113 static int is_an_active_object(void *ob) {
114         Base *base;
115         
116         for (base= FIRSTBASE; base; base= base->next)
117                 if (base->object == ob)
118                         return 1;
119         
120         return 0;
121 }
122
123 void persptoetsen(unsigned short event)
124 {
125         static Object *oldcamera=0;
126         float phi, si, q1[4], vec[3];
127         static int perspo=1;
128         int preview3d_event= 1;
129         
130         float new_quat[4], new_dist;
131         
132         if(event==PADENTER) {
133                 if (G.qual == LR_SHIFTKEY) {
134                         view3d_set_1_to_1_viewborder(G.vd);
135                 } else {
136                         if (G.vd->persp==2) {
137                                 G.vd->camzoom= 0;
138                         } else {
139                                 new_dist = 10.0;
140                                 smooth_view(G.vd, NULL, NULL, &new_dist);
141                         }
142                 }
143         }
144         else if((G.qual & (LR_SHIFTKEY | LR_CTRLKEY)) && (event != PAD0)) {
145                 
146                 /* Indicate that this view is inverted,
147                  * but only if it actually _was_ inverted (jobbe) */
148                 if (event==PAD7 || event == PAD1 || event == PAD3)
149                         G.vd->flag2 |= V3D_OPP_DIRECTION_NAME;
150                 
151                 if(event==PAD0) {
152                         /* G.vd->persp= 3; */
153                 }
154                 else if(event==PAD7) {
155                         new_quat[0]=0.0;
156                         new_quat[1]=-1.0;
157                         new_quat[2]=0.0;
158                         new_quat[3]=0.0;
159                         G.vd->view= 0;
160                         smooth_view(G.vd, NULL, new_quat, NULL);
161                         G.vd->view= 7;
162                         
163                         if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; 
164                         else if(G.vd->persp>=2) G.vd->persp= perspo;
165                 }
166                 else if(event==PAD1) {
167                         new_quat[0]=0.0;
168                         new_quat[1]=0.0;
169                         new_quat[2]=(float)-cos(M_PI/4.0);
170                         new_quat[3]=(float)-cos(M_PI/4.0);
171                         G.vd->view=0;
172                         smooth_view(G.vd, NULL, new_quat, NULL);
173                         G.vd->view=1;
174                         if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
175                         else if(G.vd->persp>=2) G.vd->persp= perspo;
176                 }
177                 else if(event==PAD3) {
178                         new_quat[0]= 0.5;
179                         new_quat[1]=-0.5;
180                         new_quat[2]= 0.5;
181                         new_quat[3]= 0.5;
182                         G.vd->view=0;
183                         smooth_view(G.vd, NULL, new_quat, NULL);
184                         G.vd->view=3;
185                         if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
186                         else if(G.vd->persp>=2) G.vd->persp= perspo;
187                 }
188                 else if(event==PADMINUS) {
189                         /* this min and max is also in viewmove() */
190                         if(G.vd->persp==2) {
191                                 G.vd->camzoom-= 10;
192                                 if(G.vd->camzoom<-30) G.vd->camzoom= -30;
193                         }
194                         else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2f;
195                 }
196                 else if(event==PADPLUSKEY) {
197                         if(G.vd->persp==2) {
198                                 G.vd->camzoom+= 10;
199                                 if(G.vd->camzoom>300) G.vd->camzoom= 300;
200                         }
201                         else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333f;
202                 }
203                 else {
204
205                         initgrabz(0.0, 0.0, 0.0);
206                         
207                         if(event==PAD6) window_to_3d(vec, -32, 0);
208                         else if(event==PAD4) window_to_3d(vec, 32, 0);
209                         else if(event==PAD8) window_to_3d(vec, 0, -25);
210                         else if(event==PAD2) window_to_3d(vec, 0, 25);
211                         G.vd->ofs[0]+= vec[0];
212                         G.vd->ofs[1]+= vec[1];
213                         G.vd->ofs[2]+= vec[2];
214                 }
215         }
216         else {
217                 /* Indicate that this view is not inverted.
218                  * Don't do this for PADMINUS/PADPLUSKEY, though. (jobbe)*/
219                 if (event != PADMINUS && event != PADPLUSKEY)
220                         G.vd->flag2 &= ~V3D_OPP_DIRECTION_NAME;
221                 
222
223                 if(event==PAD7) {
224                         new_quat[0]=1.0;
225                         new_quat[1]=0.0;
226                         new_quat[2]=0.0;
227                         new_quat[3]=0.0;
228                         G.vd->view=0;
229                         smooth_view(G.vd, NULL, new_quat, NULL);
230                         G.vd->view=7;
231                         if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
232                         else if(G.vd->persp>=2) G.vd->persp= perspo;
233                 }
234                 else if(event==PAD1) {
235                         new_quat[0]= (float)cos(M_PI/4.0);
236                         new_quat[1]= (float)-sin(M_PI/4.0);
237                         new_quat[2]= 0.0;
238                         new_quat[3]= 0.0;
239                         G.vd->view=0;
240                         smooth_view(G.vd, NULL, new_quat, NULL);
241                         G.vd->view=1;
242                         if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
243                         else if(G.vd->persp>=2) G.vd->persp= perspo;
244                 }
245                 else if(event==PAD3) {
246                         new_quat[0]= 0.5;
247                         new_quat[1]= -0.5;
248                         new_quat[2]= -0.5;
249                         new_quat[3]= -0.5;
250                         G.vd->view=0;
251                         smooth_view(G.vd, NULL, new_quat, NULL);
252                         G.vd->view=3;
253                         if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
254                         else if(G.vd->persp>=2) G.vd->persp= perspo;
255                 }
256                 else if(event==PADMINUS) {
257                         /* this min and max is also in viewmove() */
258                         if(G.vd->persp==2) {
259                                 G.vd->camzoom= MAX2(-30, G.vd->camzoom-5);
260                         }
261                         else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2f;
262                         if(G.vd->persp!=1) preview3d_event= 0;
263                 }
264                 else if(event==PADPLUSKEY) {
265                         if(G.vd->persp==2) {
266                                 G.vd->camzoom= MIN2(300, G.vd->camzoom+5);
267                         }
268                         else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333f;
269                         if(G.vd->persp!=1) preview3d_event= 0;
270                 }
271                 else if(event==PAD5) {
272                         if(G.vd->persp==1) G.vd->persp=0;
273                         else G.vd->persp=1;
274                 }
275                 else if(event==PAD0) {
276                         if(G.qual==LR_ALTKEY) {
277                                 if(oldcamera && is_an_active_object(oldcamera)) {
278                                         G.vd->camera= oldcamera;
279                                 }
280                                 
281                                 handle_view3d_lock();
282                         }
283                         else if(BASACT) {
284                                 /* check both G.vd as G.scene cameras */
285                                 if(G.qual==LR_CTRLKEY) {
286                                         if(G.vd->camera != OBACT || G.scene->camera != OBACT) {
287                                                 if(G.vd->camera && G.vd->camera->type==OB_CAMERA)
288                                                         oldcamera= G.vd->camera;
289                                                 
290                                                 G.vd->camera= OBACT;
291                                                 handle_view3d_lock();
292                                         }
293                                 }
294                                 else if((G.vd->camera==NULL || G.scene->camera==NULL) && OBACT->type==OB_CAMERA) {
295                                         G.vd->camera= OBACT;
296                                         handle_view3d_lock();
297                                 }
298                         }
299                         if(G.vd->camera==0) {
300                                 G.vd->camera= scene_find_camera(G.scene);
301                                 handle_view3d_lock();
302                         }
303                         
304                         if(G.vd->camera) {
305                                 G.vd->persp= 2;
306                                 G.vd->view= 0;
307                                 if(((G.qual & LR_CTRLKEY) && (G.qual & LR_ALTKEY)) || (G.qual & LR_SHIFTKEY)) {
308                                         void setcameratoview3d(void);   // view.c
309                                         setcameratoview3d();
310                                         DAG_object_flush_update(G.scene, G.scene->camera, OB_RECALC_OB);
311                                         BIF_undo_push("View to Camera position");
312                                         allqueue(REDRAWVIEW3D, 0);
313                                 }                               
314                         }
315                 }
316                 else if(event==PAD9) {
317                         countall();
318                         update_for_newframe();
319                         
320                         reset_slowparents();    /* editobject.c */
321                 }
322                 else if(G.vd->persp<2) {
323                         if(event==PAD4 || event==PAD6) {
324                                 /* z-axis */
325                                 phi= (float)(M_PI/360.0)*U.pad_rot_angle;
326                                 if(event==PAD6) phi= -phi;
327                                 si= (float)sin(phi);
328                                 q1[0]= (float)cos(phi);
329                                 q1[1]= q1[2]= 0.0;
330                                 q1[3]= si;
331                                 QuatMul(G.vd->viewquat, G.vd->viewquat, q1);
332                                 G.vd->view= 0;
333                         }
334                         if(event==PAD2 || event==PAD8) {
335                                 
336                                 /* horizontal axis */
337                                 VECCOPY(q1+1, G.vd->viewinv[0]);
338                                 
339                                 Normalize(q1+1);
340                                 phi= (float)(M_PI/360.0)*U.pad_rot_angle;
341                                 if(event==PAD2) phi= -phi;
342                                 si= (float)sin(phi);
343                                 q1[0]= (float)cos(phi);
344                                 q1[1]*= si;
345                                 q1[2]*= si;
346                                 q1[3]*= si;
347                                 QuatMul(G.vd->viewquat, G.vd->viewquat, q1);
348                                 G.vd->view= 0;
349                         }
350                 }
351
352                 if(G.vd->persp<2) perspo= G.vd->persp;
353         }
354
355         if(G.vd->depths) G.vd->depths->damaged= 1;
356         retopo_queue_updates(G.vd);
357         retopo_force_update();
358         
359         if(preview3d_event) 
360                 BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
361         else
362                 BIF_view3d_previewrender_signal(curarea, PR_PROJECTED);
363
364         scrarea_queue_redraw(curarea);
365 }
366
367 int untitled(char * name)
368 {
369         if (G.save_over == 0 ) {
370                 char * c= BLI_last_slash(name);
371                 
372                 if (c)
373                         strcpy(&c[1], "untitled.blend");
374                 else
375                         strcpy(name, "untitled.blend");
376                         
377                 return(TRUE);
378         }
379         
380         return(FALSE);
381 }
382
383 char *recent_filelist(void)
384 {
385         struct RecentFile *recent;
386         int event, i, ofs;
387         char pup[2048], *p;
388
389         p= pup + sprintf(pup, "Open Recent%%t");
390         
391         if (G.sce[0]) {
392                 p+= sprintf(p, "|%s %%x%d", G.sce, 1);
393                 ofs = 1;
394         } else ofs = 0;
395
396         for (recent = G.recent_files.first, i=0; (i<U.recent_files) && (recent); recent = recent->next, i++) {
397                 if (strcmp(recent->filename, G.sce)) {
398                         p+= sprintf(p, "|%s %%x%d", recent->filename, i+ofs+1);
399                 }
400         }
401         event= pupmenu(pup);
402         if(event>0) {
403                 if (ofs && (event==1))
404                         return(G.sce);
405                 else
406                         recent = BLI_findlink(&(G.recent_files), event-1-ofs);
407                         if(recent) return(recent->filename);
408         }
409         
410         return(NULL);
411 }
412
413 int blenderqread(unsigned short event, short val)
414 {
415         /* here do the general keys handling (not screen/window/space) */
416         /* return 0: do not pass on to the other queues */
417         extern int textediting;
418         extern void playback_anim();
419         ScrArea *sa;
420         Object *ob;
421         int textspace=0;
422         /* Changed str and dir size to 160, to make sure there is enough
423          * space for filenames. */
424         char dir[FILE_MAXDIR * 2], str[FILE_MAXFILE * 2];
425         char *recentfile;
426         
427         if(val==0) return 1;
428         if(event==MOUSEY || event==MOUSEX) return 1;
429         if (G.flags & G_FILE_AUTOPLAY) return 1;
430
431         if (curarea && curarea->spacetype==SPACE_TEXT) textspace= 1;
432         else if (curarea && curarea->spacetype==SPACE_SCRIPT) textspace= 1;
433
434         switch(event) {
435
436         case F1KEY:
437                 if(G.qual==0) {
438                         /* this exception because of the '?' button */
439                         if(curarea->spacetype==SPACE_INFO) {
440                                 sa= closest_bigger_area();
441                                 areawinset(sa->win);
442                         }
443                         
444                         activate_fileselect(FILE_BLENDER, "Open File", G.sce, BIF_read_file);
445                         return 0;
446                 }
447                 else if(G.qual==LR_SHIFTKEY) {
448                         activate_fileselect(FILE_LOADLIB, "Load Library", G.lib, 0);
449                         return 0;
450                 }
451                 break;
452         case F2KEY:
453                 if(G.qual==0) {
454                         strcpy(dir, G.sce);
455                         untitled(dir);
456                         activate_fileselect(FILE_BLENDER, "Save File", dir, BIF_write_file);
457                         return 0;
458                 }
459                 else if(G.qual==LR_CTRLKEY) {
460                         write_vrml_fs();
461                         return 0;
462                 }
463                 else if(G.qual==LR_SHIFTKEY) {
464                         write_dxf_fs();
465                         return 0;
466                 }
467                 break;
468         case F3KEY:
469                 if(G.qual==0) {
470                         BIF_save_rendered_image_fs();
471                         return 0;
472                 }
473                 else if(G.qual==LR_SHIFTKEY) {
474                         newspace(curarea, SPACE_NODE);
475                         return 0;
476                 }
477                 else if(G.qual & LR_CTRLKEY) {
478                         BIF_screendump(0);
479                 }
480                 break;
481         case F4KEY:
482                 if(G.qual==LR_SHIFTKEY) {
483
484                         memset(str, 0, 16);
485                         ob= OBACT;
486                         if(ob) strcpy(str, ob->id.name);
487
488                         activate_fileselect(FILE_MAIN, "Data Select", str, NULL);
489                         return 0;
490                 }
491                 else if(G.qual==0) {
492                         extern_set_butspace(event, 1);
493                 }
494                 break;
495         case F5KEY:
496                 if(G.qual==LR_SHIFTKEY) {
497                         newspace(curarea, SPACE_VIEW3D);
498                         return 0;
499                 }
500                 else if(G.qual==0) {
501                         extern_set_butspace(event, 1);
502                 }
503                 break;
504         case F6KEY:
505                 if(G.qual==LR_SHIFTKEY) {
506                         newspace(curarea, SPACE_IPO);
507                         return 0;
508                 }
509                 else if(G.qual==0) {
510                         extern_set_butspace(event, 1);
511                 }
512                 break;
513         case F7KEY:
514                 if(G.qual==LR_SHIFTKEY) {
515                         newspace(curarea, SPACE_BUTS);
516                         return 0;
517                 }
518                 else if(G.qual==0) {
519                         extern_set_butspace(event, 1);
520                 }
521                 break;
522         case F8KEY:
523                 if(G.qual==LR_SHIFTKEY) {
524                         newspace(curarea, SPACE_SEQ);
525                         return 0;
526                 }
527                 else if(G.qual==0) {
528                         extern_set_butspace(event, 1);
529                 }
530                 break;
531         case F9KEY:
532                 if(G.qual==LR_SHIFTKEY) {
533                         newspace(curarea, SPACE_OOPS);
534                         return 0;
535                 }
536                 else if(G.qual==(LR_SHIFTKEY|LR_ALTKEY)) {
537                         newspace(curarea, SPACE_OOPS+256);
538                         return 0;
539                 }
540                 else if(G.qual==0) {
541                         extern_set_butspace(event, 1);
542                 }
543                 break;
544         case F10KEY:
545                 if(G.qual==LR_SHIFTKEY) {
546                         newspace(curarea, SPACE_IMAGE);
547                         return 0;
548                 }
549                 else if(G.qual==0) {
550                         extern_set_butspace(event, 1);
551                 }
552                 break;
553         case F11KEY:
554                 if(G.qual==LR_SHIFTKEY) {
555                         newspace(curarea, SPACE_TEXT);
556                         return 0;
557                 }
558                 else if (G.qual==LR_CTRLKEY) {
559                         playback_anim();
560                 }
561                 else if(G.qual==0) {
562                         BIF_toggle_render_display();
563                         return 0;
564                 }
565                 break;
566         case F12KEY:
567                 if(G.qual==LR_SHIFTKEY) {
568                         newspace(curarea, SPACE_ACTION);
569                         return 0;
570                 }
571                 else if (G.qual==(LR_SHIFTKEY|LR_CTRLKEY)) {
572                         newspace(curarea, SPACE_NLA);
573                         return 0;
574                 }
575                 else if (G.qual==LR_CTRLKEY) {
576                         BIF_do_render(1);
577                 }
578                 else {
579                         /* ctrl/alt + f12 should render too, for some macs have f12 assigned to cd eject */
580                         BIF_do_render(0);
581                 }
582                 return 0;
583                 break;
584         
585         case WHEELUPMOUSE:
586                 if(G.qual==LR_ALTKEY || G.qual==LR_COMMANDKEY) {
587                         if(CFRA>1) {
588                                 CFRA--;
589                                 update_for_newframe();
590                         }
591                         return 0;
592                 }
593                 break;
594         case WHEELDOWNMOUSE:
595                 if(G.qual==LR_ALTKEY || G.qual==LR_COMMANDKEY) {
596                         CFRA++;
597                         update_for_newframe();
598                         return 0;
599                 }
600                 break;
601                 
602         case LEFTARROWKEY:
603         case DOWNARROWKEY:
604                 if(textediting==0 && textspace==0) {
605
606 #if 0
607 //#ifdef _WIN32 // FULLSCREEN
608                         if(event==DOWNARROWKEY){
609                                 if (G.qual==LR_ALTKEY)
610                                         mainwindow_toggle_fullscreen(0);
611                                 else if(G.qual==0)
612                                         CFRA-= G.scene->jumpframe;
613                         }
614 #else
615                         if((event==DOWNARROWKEY)&&(G.qual==0))
616                                 CFRA-= G.scene->jumpframe;
617 #endif
618                         else if((event==LEFTARROWKEY)&&(G.qual==0))
619                                 CFRA--;
620                         
621                         if(G.qual==LR_SHIFTKEY)
622                                 CFRA= PSFRA;
623                         if(CFRA<1) CFRA=1;
624         
625                         update_for_newframe();
626                         return 0;
627                 }
628                 break;
629
630         case RIGHTARROWKEY:
631         case UPARROWKEY:
632                 if(textediting==0 && textspace==0) {
633
634 #if 0
635 //#ifdef _WIN32 // FULLSCREEN
636                         if(event==UPARROWKEY){ 
637                                 if(G.qual==LR_ALTKEY)
638                                         mainwindow_toggle_fullscreen(1);
639                                 else if(G.qual==0)
640                                         CFRA+= G.scene->jumpframe;
641                         }
642 #else
643                         if((event==UPARROWKEY)&&(G.qual==0))
644                                 CFRA+= G.scene->jumpframe;
645 #endif
646                         else if((event==RIGHTARROWKEY)&&(G.qual==0))
647                                 CFRA++;
648
649                         if(G.qual==LR_SHIFTKEY)
650                                 CFRA= PEFRA;
651                         
652                         update_for_newframe();
653                 }
654                 break;
655
656         case ESCKEY:
657                 sound_stop_all_sounds();        // whats this?
658                 
659                 /* stop playback on ESC always */
660                 rem_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM);
661                 audiostream_stop();
662                 allqueue(REDRAWALL, 0);
663                 
664                 break;
665         case TABKEY:
666                 if(G.qual==0) {
667                         if(textspace==0) {
668                                 if(curarea->spacetype==SPACE_IPO)
669                                         set_editflag_editipo();
670                                 else if(curarea->spacetype==SPACE_SEQ)
671                                         enter_meta();
672                                 else if(curarea->spacetype==SPACE_NODE)
673                                         return 1;
674                                 else if(G.vd) {
675                                         /* also when Alt-E */
676                                         if(G.obedit==NULL) {
677                                                 enter_editmode(EM_WAITCURSOR);
678                                                 if(G.obedit) BIF_undo_push("Original"); // here, because all over code enter_editmode is abused
679                                         }
680                                         else
681                                                 exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); // freedata, and undo
682                                 }
683                                 return 0;
684                         }
685                 }
686                 else if(G.qual==LR_CTRLKEY){
687                         Object *ob= OBACT;
688                         if(ob) {
689                                 if(ob->type==OB_ARMATURE) {
690                                         if(ob->flag & OB_POSEMODE) exit_posemode();
691                                         else enter_posemode();
692                                 }
693                                 else if(ob->type==OB_MESH) {
694                                         if(ob==G.obedit) EM_selectmode_menu();
695                                         else if(G.f & G_SCULPTMODE)
696                                                 sculptmode_selectbrush_menu();
697                                         else set_wpaint();
698                                 }
699                         }
700                 }
701                 break;
702
703         case BACKSPACEKEY:
704                 break;
705
706         case AKEY:
707                 if(textediting==0 && textspace==0) {
708                         if(G.qual==(LR_SHIFTKEY|LR_ALTKEY)){
709                                 play_anim(1);
710                                 return 0;
711                         }
712                         else if(G.qual==LR_ALTKEY) {
713                                 play_anim(0);
714                                 return 0;
715                         }
716                 }
717                 break;
718         case EKEY:
719                 if(G.qual==LR_ALTKEY) {
720                         if(G.vd && textspace==0) {
721                                 if(G.obedit==0) {
722                                         enter_editmode(EM_WAITCURSOR);
723                                         BIF_undo_push("Original");
724                                 }
725                                 else
726                                         exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); // freedata, and undo
727                                 return 0;
728                         }                       
729                 }
730                 break;
731         case IKEY:
732                 if(textediting==0 && textspace==0 && !ELEM3(curarea->spacetype, SPACE_FILE, SPACE_IMASEL, SPACE_NODE)) {
733                         if(G.f & G_SCULPTMODE) return 1;
734                         else if(G.qual==0) {
735                                 common_insertkey();
736                                 return 0;
737                         }
738                 }
739                 break;
740         case JKEY:
741                 if(textediting==0 && textspace==0) {
742                         if (G.qual==0) {
743                                 BIF_swap_render_rects();
744                                 return 0;
745                         }
746                 }
747                 break;
748
749         case NKEY:
750                 if(textediting==0 && textspace==0) {
751                         if(G.qual & LR_CTRLKEY);
752                         else if(G.qual==0 || (G.qual & LR_SHIFTKEY)) {
753                                 if(curarea->spacetype==SPACE_VIEW3D);           // is new panel, in view3d queue
754                                 else if(curarea->spacetype==SPACE_IPO);                 // is new panel, in ipo queue
755                                 else if(curarea->spacetype==SPACE_IMAGE);                       // is new panel, in ipo queue
756                                 else if(curarea->spacetype==SPACE_ACTION);                      // is own queue
757                                 else if(curarea->spacetype==SPACE_NLA);                 // is new panel
758                                 else if(curarea->spacetype==SPACE_SEQ);                 // is new panel
759                                 else {
760                                         clever_numbuts();
761                                         return 0;
762                                 }
763                         }
764                 }
765                 break;
766                 
767         case OKEY:
768                 if(textediting==0) {
769                         if(G.qual==LR_CTRLKEY) {
770                                 recentfile = recent_filelist();
771                                 if(recentfile) {
772                                         BIF_read_file(recentfile);
773                                 }
774                                 return 0;
775                         }
776                 }
777                 break;
778                 
779         case SKEY:
780                 if(G.obedit==NULL) {
781                         if(G.qual==LR_CTRLKEY) {
782                                 strcpy(dir, G.sce);
783                                 if (untitled(dir)) {
784                                         activate_fileselect(FILE_BLENDER, "Save File", dir, BIF_write_file);
785                                 } else {
786                                         BIF_write_file(dir);
787                                         free_filesel_spec(dir);
788                                 }
789                                 return 0;
790                         }
791                 }
792                 break;
793         
794         case TKEY:
795                 if (G.qual==(LR_SHIFTKEY|LR_ALTKEY|LR_CTRLKEY)) {
796                         Object *ob = OBACT;
797                         int event = pupmenu(ob?"Time%t|draw|recalc ob|recalc data":"Time%t|draw");
798                         int a;
799                         double delta, stime;
800
801                         if (event < 0) return 0; /* cancelled by user */
802
803                         waitcursor(1);
804                         
805                         stime= PIL_check_seconds_timer();
806                         for(a=0; a<100000; a++) {
807                                 if (event==1) {
808                                         scrarea_do_windraw(curarea);
809                                 } else if (event==2) {
810                                         ob->recalc |= OB_RECALC_OB;
811                                         object_handle_update(ob);
812                                 } else if (event==3) {
813                                         ob->recalc |= OB_RECALC_DATA;
814                                         object_handle_update(ob);
815                                 }
816
817                                 delta= PIL_check_seconds_timer()-stime;
818                                 if (delta>5.0) break;
819                         }
820                         
821                         waitcursor(0);
822                         notice("%8.6f s/op - %6.2f ops/s - %d iterations", delta/a, a/delta, a);
823                         return 0;
824                 }
825                 else if(G.qual==(LR_ALTKEY|LR_CTRLKEY)) {
826                         int a;
827                         int event= pupmenu("10 Timer%t|draw|draw+swap|undo");
828                         if(event>0) {
829                                 double stime= PIL_check_seconds_timer();
830                                 char tmpstr[128];
831                                 int time;
832
833                                 waitcursor(1);
834                                 
835                                 for(a=0; a<10; a++) {
836                                         if (event==1) {
837                                                 scrarea_do_windraw(curarea);
838                                         } else if (event==2) {
839                                                 scrarea_do_windraw(curarea);
840                                                 screen_swapbuffers();
841                                         }
842                                         else if(event==3) {
843                                                 BIF_undo();
844                                                 BIF_redo();
845                                         }
846                                 }
847                         
848                                 time= (int) ((PIL_check_seconds_timer()-stime)*1000);
849                                 
850                                 if(event==1) sprintf(tmpstr, "draw %%t|%d ms", time);
851                                 if(event==2) sprintf(tmpstr, "d+sw %%t|%d ms", time);
852                                 if(event==3) sprintf(tmpstr, "undo %%t|%d ms", time);
853                         
854                                 waitcursor(0);
855                                 pupmenu(tmpstr);
856
857                         }
858                         return 0;
859                 }
860                 break;
861                                 
862         case UKEY:
863                 if(textediting==0) {
864                         if(G.qual==LR_CTRLKEY) {
865                                 if(okee("Save user defaults")) {
866                                         BIF_write_homefile();
867                                 }
868                                 return 0;
869                         }
870                         else if(G.qual==LR_ALTKEY) {
871                                 if(curarea->spacetype!=SPACE_TEXT) {
872                                         BIF_undo_menu();
873                                         return 0;
874                                 }
875                         }
876                 }
877                 break;
878                 
879         case WKEY:
880                 if(textediting==0) {
881                         if(G.qual==LR_CTRLKEY) {
882                                 strcpy(dir, G.sce);
883                                 if (untitled(dir)) {
884                                         activate_fileselect(FILE_BLENDER, "Save File", dir, BIF_write_file);
885                                 } else {
886                                         BIF_write_file(dir);
887                                         free_filesel_spec(dir);
888                                 }
889                                 return 0;
890                         }
891                         /* Python specials? ;)
892                         else if(G.qual==LR_ALTKEY) {
893                                 write_videoscape_fs();
894                                 return 0;
895                         }*/ 
896                 }
897                 break;
898                 
899         case XKEY:
900                 if(textspace==0 && textediting==0) {
901                         if(G.qual==LR_CTRLKEY) {
902                                 if(okee("Erase all")) {
903                                         if( BIF_read_homefile(0)==0) error("No file ~/.B.blend");
904                                 }
905                                 return 0;
906                         }
907                 }
908                 break;
909         case YKEY:      // redo alternative
910                 if(textspace==0) {
911                         if(G.qual==LR_CTRLKEY) {
912                                 BIF_redo(); 
913                                 return 0;
914                         }
915                 }
916                 break;
917         case ZKEY:      // undo
918                 if(textspace==0) {
919                         if(G.qual & (LR_CTRLKEY|LR_COMMANDKEY)) { // all combos with ctrl/commandkey are accepted
920                                 if ELEM(G.qual, LR_CTRLKEY, LR_COMMANDKEY) BIF_undo();
921                                 else BIF_redo(); // all combos with ctrl is redo
922                                 return 0;
923                         }
924                 }
925                 break; 
926         }
927         
928         return 1;
929 }
930
931 /* eof */