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