3 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
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
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.
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.
22 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23 * All rights reserved.
25 * The Original Code is: all of this file.
27 * Contributor(s): none yet.
29 * ***** END GPL/BL DUAL LICENSE BLOCK *****
33 * General blender hot keys (toets = dutch), special hotkeys are in space.c
41 #include "BLI_winstuff.h"
44 #include "MEM_guardedalloc.h"
48 #include "nla.h" /* Only for the #ifdef flag - To be removed later */
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
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"
60 #include "BKE_action.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"
69 #include "BKE_scene.h"
70 #include "BKE_utildefines.h"
72 #include "BIF_butspace.h"
73 #include "BIF_editseq.h"
74 #include "BIF_editsound.h"
75 #include "BIF_editmesh.h"
76 #include "BIF_imasel.h"
77 #include "BIF_editparticle.h"
78 #include "BIF_interface.h"
79 #include "BKE_object.h"
80 #include "BIF_poseobject.h"
81 #include "BIF_previewrender.h"
82 #include "BIF_renderwin.h"
83 #include "BIF_retopo.h"
84 #include "BIF_screen.h"
85 #include "BIF_space.h"
86 #include "BIF_toets.h"
87 #include "BIF_toolbox.h"
88 #include "BIF_usiblender.h"
89 #include "BIF_writeimage.h"
91 #include "BDR_sculptmode.h"
92 #include "BDR_vpaint.h"
93 #include "BDR_editobject.h"
94 #include "BDR_editface.h"
96 #include "BSE_filesel.h" /* For activate_fileselect */
97 #include "BSE_drawview.h" /* For play_anim */
100 #include "BSE_editipo.h"
101 #include "BSE_headerbuttons.h"
102 #include "BSE_seqaudio.h"
106 #include "IMB_imbuf.h"
107 #include "IMB_imbuf_types.h"
109 #include "mydevice.h"
111 #include "BIF_poseobject.h"
113 #define VIEW_ZOOM_OUT_FACTOR (1.15f)
114 #define VIEW_ZOOM_IN_FACTOR (1.0f/VIEW_ZOOM_OUT_FACTOR)
116 /* ------------------------------------------------------------------------- */
118 static int is_an_active_object(void *ob) {
121 for (base= FIRSTBASE; base; base= base->next)
122 if (base->object == ob)
128 /* run when pressing 1,3 or 7 */
129 static void axis_set_view(float q1, float q2, float q3, float q4, short view, int perspo)
132 new_quat[0]= q1; new_quat[1]= q2;
133 new_quat[2]= q3; new_quat[3]= q4;
136 if (G.vd->persp==2 && G.vd->camera) {
137 /* Is this switching from a camera view ? */
139 float orig_lens= G.vd->lens;
140 VECCOPY(orig_ofs, G.vd->ofs);
141 view_settings_from_ob(G.vd->camera, G.vd->ofs, G.vd->viewquat, &G.vd->dist, &G.vd->lens);
143 if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
144 else if(G.vd->persp>=2) G.vd->persp= perspo;
146 smooth_view(G.vd, orig_ofs, new_quat, NULL, &orig_lens);
149 if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
150 else if(G.vd->persp>=2) G.vd->persp= perspo;
152 smooth_view(G.vd, NULL, new_quat, NULL, NULL);
157 void persptoetsen(unsigned short event)
159 static Object *oldcamera=0;
160 float phi, si, q1[4], vec[3];
162 int preview3d_event= 1;
165 float new_dist, orig_ofs[3];
167 /* Use this to test if we started out with a camera */
168 Object *act_cam_orig=NULL;
169 if (G.vd->persp == 2)
170 act_cam_orig = G.vd->camera;
172 if(event==PADENTER) {
173 if (G.qual == LR_SHIFTKEY) {
174 view3d_set_1_to_1_viewborder(G.vd);
176 if (G.vd->persp==2) {
180 smooth_view(G.vd, NULL, NULL, &new_dist, NULL);
184 else if((G.qual & (LR_SHIFTKEY | LR_CTRLKEY)) && (event != PAD0)) {
186 /* Indicate that this view is inverted,
187 * but only if it actually _was_ inverted (jobbe) */
188 if (event==PAD7 || event == PAD1 || event == PAD3)
189 G.vd->flag2 |= V3D_OPP_DIRECTION_NAME;
192 /* G.vd->persp= 3; */
194 else if(event==PAD7) {
195 axis_set_view(0.0, -1.0, 0.0, 0.0, 7, perspo);
197 else if(event==PAD1) {
198 axis_set_view(0.0, 0.0, (float)-cos(M_PI/4.0), (float)-cos(M_PI/4.0), 1, perspo);
200 else if(event==PAD3) {
201 axis_set_view(0.5, -0.5, 0.5, 0.5, 3, perspo);
203 else if(event==PADMINUS) {
204 /* this min and max is also in viewmove() */
207 if(G.vd->camzoom<-30) G.vd->camzoom= -30;
209 else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2f;
211 else if(event==PADPLUSKEY) {
214 if(G.vd->camzoom>300) G.vd->camzoom= 300;
216 else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333f;
220 initgrabz(0.0, 0.0, 0.0);
222 if(event==PAD6) window_to_3d(vec, -32, 0);
223 else if(event==PAD4) window_to_3d(vec, 32, 0);
224 else if(event==PAD8) window_to_3d(vec, 0, -25);
225 else if(event==PAD2) window_to_3d(vec, 0, 25);
226 G.vd->ofs[0]+= vec[0];
227 G.vd->ofs[1]+= vec[1];
228 G.vd->ofs[2]+= vec[2];
232 /* Indicate that this view is not inverted.
233 * Don't do this for PADMINUS/PADPLUSKEY, though. (jobbe)*/
234 if (event != PADMINUS && event != PADPLUSKEY)
235 G.vd->flag2 &= ~V3D_OPP_DIRECTION_NAME;
239 axis_set_view(1.0, 0.0, 0.0, 0.0, 7, perspo);
241 else if(event==PAD1) {
242 axis_set_view((float)cos(M_PI/4.0), (float)-sin(M_PI/4.0), 0.0, 0.0, 1, perspo);
244 else if(event==PAD3) {
245 axis_set_view(0.5, -0.5, -0.5, -0.5, 3, perspo);
247 else if(event==PADMINUS) {
248 /* this min and max is also in viewmove() */
250 G.vd->camzoom= MAX2(-30, G.vd->camzoom-5);
252 else if(G.vd->dist<10.0*G.vd->far) {
253 getmouseco_areawin(mouseloc);
254 view_zoom_mouseloc(VIEW_ZOOM_OUT_FACTOR, mouseloc);
256 if(G.vd->persp!=1) preview3d_event= 0;
258 else if(event==PADPLUSKEY) {
260 G.vd->camzoom= MIN2(300, G.vd->camzoom+5);
262 else if(G.vd->dist> 0.001*G.vd->grid) {
263 getmouseco_areawin(mouseloc);
264 view_zoom_mouseloc(VIEW_ZOOM_IN_FACTOR, mouseloc);
266 if(G.vd->persp!=1) preview3d_event= 0;
268 else if(event==PAD5) {
269 if (U.smooth_viewtx) {
270 if(G.vd->persp==1) { G.vd->persp=0;
271 } else if (act_cam_orig) {
272 /* were from a camera view */
273 float orig_dist= G.vd->dist;
274 float orig_lens= G.vd->lens;
275 VECCOPY(orig_ofs, G.vd->ofs);
280 view_settings_from_ob(act_cam_orig, G.vd->ofs, NULL, NULL, &G.vd->lens);
282 smooth_view(G.vd, orig_ofs, NULL, &orig_dist, &orig_lens);
288 if(G.vd->persp==1) G.vd->persp=0;
292 else if(event==PAD0) {
293 if(G.qual==LR_ALTKEY) {
294 if(oldcamera && is_an_active_object(oldcamera)) {
295 G.vd->camera= oldcamera;
297 handle_view3d_lock();
300 /* check both G.vd as G.scene cameras */
301 if(G.qual==LR_CTRLKEY) {
302 if(G.vd->camera != OBACT || G.scene->camera != OBACT) {
303 if(G.vd->camera && G.vd->camera->type==OB_CAMERA)
304 oldcamera= G.vd->camera;
307 handle_view3d_lock();
310 else if((G.vd->camera==NULL || G.scene->camera==NULL) && OBACT->type==OB_CAMERA) {
312 handle_view3d_lock();
315 if(G.vd->camera==0) {
316 G.vd->camera= scene_find_camera(G.scene);
317 handle_view3d_lock();
320 if(G.vd->camera && (G.vd->camera != act_cam_orig)) {
324 if(((G.qual & LR_CTRLKEY) && (G.qual & LR_ALTKEY)) || (G.qual & LR_SHIFTKEY)) {
325 void setcameratoview3d(void); // view.c
327 DAG_object_flush_update(G.scene, G.scene->camera, OB_RECALC_OB);
328 BIF_undo_push("View to Camera position");
329 allqueue(REDRAWVIEW3D, 0);
331 } else if (U.smooth_viewtx) {
332 /* move 3d view to camera view */
333 float orig_lens = G.vd->lens;
334 VECCOPY(orig_ofs, G.vd->ofs);
337 view_settings_from_ob(act_cam_orig, G.vd->ofs, G.vd->viewquat, &G.vd->dist, &G.vd->lens);
339 smooth_view_to_camera(G.vd);
340 VECCOPY(G.vd->ofs, orig_ofs);
341 G.vd->lens = orig_lens;
347 else if(event==PAD9) {
349 update_for_newframe();
351 reset_slowparents(); /* editobject.c */
353 else if(G.vd->persp<2) {
354 if(event==PAD4 || event==PAD6) {
356 phi= (float)(M_PI/360.0)*U.pad_rot_angle;
357 if(event==PAD6) phi= -phi;
359 q1[0]= (float)cos(phi);
362 QuatMul(G.vd->viewquat, G.vd->viewquat, q1);
365 if(event==PAD2 || event==PAD8) {
366 /* horizontal axis */
367 VECCOPY(q1+1, G.vd->viewinv[0]);
370 phi= (float)(M_PI/360.0)*U.pad_rot_angle;
371 if(event==PAD2) phi= -phi;
373 q1[0]= (float)cos(phi);
377 QuatMul(G.vd->viewquat, G.vd->viewquat, q1);
382 if(G.vd->persp<2) perspo= G.vd->persp;
385 if(G.vd->depths) G.vd->depths->damaged= 1;
386 retopo_queue_updates(G.vd);
389 BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
391 BIF_view3d_previewrender_signal(curarea, PR_PROJECTED);
393 scrarea_queue_redraw(curarea);
396 int untitled(char * name)
398 if (G.save_over == 0 ) {
399 char * c= BLI_last_slash(name);
402 strcpy(&c[1], "untitled.blend");
404 strcpy(name, "untitled.blend");
412 char *recent_filelist(void)
414 struct RecentFile *recent;
418 p= pup + sprintf(pup, "Open Recent%%t");
421 p+= sprintf(p, "|%s %%x%d", G.sce, 1);
425 for (recent = G.recent_files.first, i=0; (i<U.recent_files) && (recent); recent = recent->next, i++) {
426 if (strcmp(recent->filename, G.sce)) {
427 p+= sprintf(p, "|%s %%x%d", recent->filename, i+ofs+1);
432 if (ofs && (event==1))
435 recent = BLI_findlink(&(G.recent_files), event-1-ofs);
436 if(recent) return(recent->filename);
442 int blenderqread(unsigned short event, short val)
444 /* here do the general keys handling (not screen/window/space) */
445 /* return 0: do not pass on to the other queues */
446 extern int textediting;
447 extern void playback_anim();
451 /* Changed str and dir size to 160, to make sure there is enough
452 * space for filenames. */
453 char dir[FILE_MAXDIR * 2], str[FILE_MAXFILE * 2];
457 if(event==MOUSEY || event==MOUSEX) return 1;
458 if (G.flags & G_FILE_AUTOPLAY) return 1;
460 if (curarea && curarea->spacetype==SPACE_TEXT) textspace= 1;
461 else if (curarea && curarea->spacetype==SPACE_SCRIPT) textspace= 1;
467 /* this exception because of the '?' button */
468 if(curarea->spacetype==SPACE_INFO) {
469 sa= closest_bigger_area();
473 activate_fileselect(FILE_BLENDER, "Open File", G.sce, BIF_read_file);
476 else if(G.qual==LR_SHIFTKEY) {
477 activate_fileselect(FILE_LOADLIB, "Load Library", G.lib, 0);
480 else if(G.qual==LR_CTRLKEY) {
481 activate_imageselect(FILE_LOADLIB, "Load Library", G.lib, 0);
489 activate_fileselect(FILE_BLENDER, "Save File", dir, BIF_write_file);
492 else if(G.qual==LR_CTRLKEY) {
496 else if(G.qual==LR_SHIFTKEY) {
503 BIF_save_rendered_image_fs();
506 else if(G.qual==LR_SHIFTKEY) {
507 newspace(curarea, SPACE_NODE);
510 else if(G.qual & LR_CTRLKEY) {
515 if(G.qual==LR_SHIFTKEY) {
519 if(ob) strcpy(str, ob->id.name);
521 activate_fileselect(FILE_MAIN, "Data Select", str, NULL);
524 else if(G.qual==LR_CTRLKEY) {
528 if(ob) strcpy(str, ob->id.name);
530 activate_imageselect(FILE_MAIN, "Data Select", str, 0);
534 extern_set_butspace(event, 1);
538 if(G.qual==LR_SHIFTKEY) {
539 newspace(curarea, SPACE_VIEW3D);
543 extern_set_butspace(event, 1);
547 if(G.qual==LR_SHIFTKEY) {
548 newspace(curarea, SPACE_IPO);
552 extern_set_butspace(event, 1);
556 if(G.qual==LR_SHIFTKEY) {
557 newspace(curarea, SPACE_BUTS);
561 extern_set_butspace(event, 1);
565 if(G.qual==LR_SHIFTKEY) {
566 newspace(curarea, SPACE_SEQ);
570 extern_set_butspace(event, 1);
574 if(G.qual==LR_SHIFTKEY) {
575 newspace(curarea, SPACE_OOPS);
578 else if(G.qual==(LR_SHIFTKEY|LR_ALTKEY)) {
579 newspace(curarea, SPACE_OOPS+256);
583 extern_set_butspace(event, 1);
587 if(G.qual==LR_SHIFTKEY) {
588 newspace(curarea, SPACE_IMAGE);
592 extern_set_butspace(event, 1);
596 if(G.qual==LR_SHIFTKEY) {
597 newspace(curarea, SPACE_TEXT);
600 else if (G.qual==LR_CTRLKEY) {
604 BIF_toggle_render_display();
609 if(G.qual==LR_SHIFTKEY) {
610 newspace(curarea, SPACE_ACTION);
613 else if (G.qual==(LR_SHIFTKEY|LR_CTRLKEY)) {
614 newspace(curarea, SPACE_NLA);
617 else if (G.qual==LR_CTRLKEY) {
621 /* ctrl/alt + f12 should render too, for some macs have f12 assigned to cd eject */
628 if(G.qual==LR_ALTKEY || G.qual==LR_COMMANDKEY) {
631 update_for_newframe();
637 if(G.qual==LR_ALTKEY || G.qual==LR_COMMANDKEY) {
639 update_for_newframe();
646 if(textediting==0 && textspace==0) {
649 //#ifdef _WIN32 // FULLSCREEN
650 if(event==DOWNARROWKEY){
651 if (G.qual==LR_ALTKEY)
652 mainwindow_toggle_fullscreen(0);
654 CFRA-= G.scene->jumpframe;
657 if((event==DOWNARROWKEY)&&(G.qual==0))
658 CFRA-= G.scene->jumpframe;
660 else if((event==LEFTARROWKEY)&&(G.qual==0))
663 if(G.qual==LR_SHIFTKEY)
667 update_for_newframe();
674 if(textediting==0 && textspace==0) {
677 //#ifdef _WIN32 // FULLSCREEN
678 if(event==UPARROWKEY){
679 if(G.qual==LR_ALTKEY)
680 mainwindow_toggle_fullscreen(1);
682 CFRA+= G.scene->jumpframe;
685 if((event==UPARROWKEY)&&(G.qual==0))
686 CFRA+= G.scene->jumpframe;
688 else if((event==RIGHTARROWKEY)&&(G.qual==0))
691 if(G.qual==LR_SHIFTKEY)
694 update_for_newframe();
699 sound_stop_all_sounds(); // whats this?
701 /* stop playback on ESC always */
702 rem_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM);
704 allqueue(REDRAWALL, 0);
710 if(curarea->spacetype==SPACE_IPO)
711 set_editflag_editipo();
712 else if(curarea->spacetype==SPACE_SEQ)
714 else if(curarea->spacetype==SPACE_NODE)
717 /* also when Alt-E */
719 enter_editmode(EM_WAITCURSOR);
720 if(G.obedit) BIF_undo_push("Original"); // here, because all over code enter_editmode is abused
723 exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); // freedata, and undo
728 else if(G.qual==LR_CTRLKEY){
731 if(ob->type==OB_ARMATURE) {
732 if(ob->flag & OB_POSEMODE) exit_posemode();
733 else enter_posemode();
735 else if(ob->type==OB_MESH) {
736 if(ob==G.obedit) EM_selectmode_menu();
737 else if(G.f & G_PARTICLEEDIT)
738 PE_selectbrush_menu();
739 else if(G.f & G_SCULPTMODE)
740 sculptmode_selectbrush_menu();
745 else if(G.qual&LR_CTRLKEY && G.qual&LR_SHIFTKEY){
746 PE_set_particle_edit();
753 if (curarea && curarea->spacetype==SPACE_SEQ) {
754 SpaceSeq *sseq= curarea->spacedata.first;
755 if (G.qual==0 && sseq->mainb) {
762 if(textediting==0 && textspace==0) {
763 if ((G.qual==LR_ALTKEY) && (curarea && curarea->spacetype==SPACE_VIEW3D)) {
767 else if ((G.qual==LR_ALTKEY) || (G.qual==(LR_ALTKEY|LR_SHIFTKEY))){
774 if(G.qual==LR_ALTKEY) {
775 if(G.vd && textspace==0) {
777 enter_editmode(EM_WAITCURSOR);
778 BIF_undo_push("Original");
781 exit_editmode(EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); // freedata, and undo
787 if(textediting==0 && textspace==0 && !ELEM3(curarea->spacetype, SPACE_FILE, SPACE_IMASEL, SPACE_NODE)) {
788 if(G.f & G_SCULPTMODE) return 1;
796 if(textediting==0 && textspace==0) {
798 BIF_swap_render_rects();
805 if(textediting==0 && textspace==0) {
806 if(G.qual & LR_CTRLKEY);
807 else if(G.qual==0 || (G.qual & LR_SHIFTKEY)) {
808 if(curarea->spacetype==SPACE_VIEW3D); // is new panel, in view3d queue
809 else if(curarea->spacetype==SPACE_IPO); // is new panel, in ipo queue
810 else if(curarea->spacetype==SPACE_IMAGE); // is new panel, in ipo queue
811 else if(curarea->spacetype==SPACE_ACTION); // is own queue
812 else if(curarea->spacetype==SPACE_NLA); // is new panel
813 else if(curarea->spacetype==SPACE_SEQ); // is new panel
824 if(G.qual==LR_CTRLKEY) {
825 recentfile = recent_filelist();
827 BIF_read_file(recentfile);
836 if(G.qual==LR_CTRLKEY) {
839 activate_fileselect(FILE_BLENDER, "Save File", dir, BIF_write_file);
841 /* do NOT ask everytime for overwriting... */
844 free_filesel_spec(dir);
852 if (G.qual==(LR_SHIFTKEY|LR_ALTKEY|LR_CTRLKEY)) {
854 int event = pupmenu(ob?"Time%t|draw|recalc ob|recalc data":"Time%t|draw");
858 if (event < 0) return 0; /* cancelled by user */
862 stime= PIL_check_seconds_timer();
863 for(a=0; a<100000; a++) {
865 scrarea_do_windraw(curarea);
866 } else if (event==2) {
867 ob->recalc |= OB_RECALC_OB;
868 object_handle_update(ob);
869 } else if (event==3) {
870 ob->recalc |= OB_RECALC_DATA;
871 object_handle_update(ob);
874 delta= PIL_check_seconds_timer()-stime;
875 if (delta>5.0) break;
879 notice("%8.6f s/op - %6.2f ops/s - %d iterations", delta/a, a/delta, a);
882 else if(G.qual==(LR_ALTKEY|LR_CTRLKEY)) {
884 int event= pupmenu("10 Timer%t|draw|draw+swap|undo");
886 double stime= PIL_check_seconds_timer();
892 for(a=0; a<10; a++) {
894 scrarea_do_windraw(curarea);
895 } else if (event==2) {
896 scrarea_do_windraw(curarea);
897 screen_swapbuffers();
905 time= (int) ((PIL_check_seconds_timer()-stime)*1000);
907 if(event==1) sprintf(tmpstr, "draw %%t|%d ms", time);
908 if(event==2) sprintf(tmpstr, "d+sw %%t|%d ms", time);
909 if(event==3) sprintf(tmpstr, "undo %%t|%d ms", time);
921 if(G.qual==LR_CTRLKEY) {
922 if(okee("Save user defaults")) {
923 BIF_write_homefile();
927 else if(G.qual==LR_ALTKEY) {
928 if(curarea->spacetype!=SPACE_TEXT) {
938 if(G.qual==LR_CTRLKEY) {
941 activate_fileselect(FILE_BLENDER, "Save File", dir, BIF_write_file);
943 /* do NOT ask everytime for overwriting... */
946 free_filesel_spec(dir);
950 /* Python specials? ;)
951 else if(G.qual==LR_ALTKEY) {
952 write_videoscape_fs();
959 if(textspace==0 && textediting==0) {
960 if(G.qual==LR_CTRLKEY) {
961 if(okee("Erase all")) {
962 if( BIF_read_homefile(0)==0) error("No file ~/.B.blend");
965 * This isn't done when reading userdef, do it now
973 case YKEY: // redo alternative
975 if(G.qual==LR_CTRLKEY) {
983 if(G.qual & (LR_CTRLKEY|LR_COMMANDKEY)) { // all combos with ctrl/commandkey are accepted
984 if ELEM(G.qual, LR_CTRLKEY, LR_COMMANDKEY) BIF_undo();
985 else BIF_redo(); // all combos with ctrl is redo