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