8c1632b88d9d332889cd4507b3f7e04489c47606
[blender.git] / source / blender / src / usiblender.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         /* placed up here because of crappy
34          * winsock stuff.
35          */
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif
43
44 #ifdef WIN32
45 #include "BLI_winstuff.h"
46 #include <process.h> /* getpid */
47 #else
48 #include <unistd.h> /* getpid */
49 #endif
50 #include "MEM_guardedalloc.h"
51
52 #include "BMF_Api.h"
53 #ifdef INTERNATIONAL
54 #include "BIF_language.h"
55 #include "FTF_Api.h"
56 #endif
57
58 #include "BLI_blenlib.h"
59 #include "BLI_arithb.h"
60 #include "BLI_linklist.h"
61
62 #include "IMB_imbuf_types.h"
63 #include "IMB_imbuf.h"
64
65 #include "DNA_object_types.h"
66 #include "DNA_space_types.h"
67 #include "DNA_userdef_types.h"
68 #include "DNA_sound_types.h"
69
70 #include "BKE_blender.h"
71 #include "BKE_curve.h"
72 #include "BKE_displist.h"
73 #include "BKE_exotic.h"
74 #include "BKE_font.h"
75 #include "BKE_global.h"
76 #include "BKE_main.h"
77 #include "BKE_mball.h"
78 #include "BKE_packedFile.h"
79 #include "BKE_utildefines.h"
80
81 #include "BIF_fsmenu.h"
82 #include "BIF_gl.h"
83 #include "BIF_interface.h"
84 #include "BIF_usiblender.h"
85 #include "BIF_drawtext.h"
86 #include "BIF_editarmature.h"
87 #include "BIF_editlattice.h"
88 #include "BIF_editfont.h"
89 #include "BIF_editmesh.h"
90 #include "BIF_editmode_undo.h"
91 #include "BIF_editsound.h"
92 #include "BIF_renderwin.h"
93 #include "BIF_resources.h"
94 #include "BIF_screen.h"
95 #include "BIF_space.h"
96 #include "BIF_toolbox.h"
97 #include "BIF_cursors.h"
98
99 #include "BSE_drawview.h"
100 #include "BSE_headerbuttons.h"
101 #include "BSE_editipo.h"
102 #include "BSE_editaction.h"
103 #include "BSE_filesel.h"
104 #include "BSE_edit.h"
105
106 #include "BLO_readfile.h"
107 #include "BLO_writefile.h"
108
109 #include "BDR_drawobject.h"
110 #include "BDR_editobject.h"
111 #include "BDR_editcurve.h"
112 #include "BDR_vpaint.h"
113
114 #include "BPY_extern.h"
115
116 #include "blendef.h"
117
118 #include "radio.h"
119 #include "render.h"
120 #include "datatoc.h"
121
122 #include "SYS_System.h"
123
124 #include "PIL_time.h"
125
126 /***/
127
128 void BIF_read_file(char *name)
129 {
130         extern short winqueue_break; /* editscreen.c */
131
132         //here?
133         //sound_end_all_sounds();
134
135         // first try to read exotic file formats...
136         if (BKE_read_exotic(name) == 0) { /* throws first error box */
137                 /* we didn't succeed, now try to read Blender file
138                    calls readfile, calls toolbox, throws one more,
139                    on failure calls the stream, and that is stubbed.... */
140                 BKE_read_file(name, NULL);
141
142                         
143                 mainwindow_set_filename_to_title(G.main->name);
144                 countall();
145                 sound_initialize_sounds();
146
147                 winqueue_break= 1;      /* leave queues everywhere */
148
149                 undo_editmode_clear();
150                 BKE_reset_undo();
151                 BKE_write_undo("original");     /* save current state */
152         }
153         else BIF_undo_push("Import file");
154 }
155
156 int BIF_read_homefile(void)
157 {
158         char tstr[FILE_MAXDIR+FILE_MAXFILE], scestr[FILE_MAXDIR];
159         char *home= BLI_gethome();
160         int success;
161 #ifdef _WIN32   // FULLSCREEN
162         static int screenmode = -1;
163
164         screenmode = U.uiflag & USER_FLIPFULLSCREEN;
165 #endif
166
167         BLI_make_file_string(G.sce, tstr, home, ".B.blend");
168         strcpy(scestr, G.sce);  /* temporal store */
169
170         /* only here free userdef themes... */
171         BLI_freelistN(&U.themes);
172         
173         /* prevent loading no UI */
174         G.fileflags &= ~G_FILE_NO_UI;
175         
176         if (BLI_exists(tstr)) {
177                 success = BKE_read_file(tstr, NULL);
178         } else {
179                 success = BKE_read_file_from_memory(datatoc_B_blend, datatoc_B_blend_size, NULL);
180         }
181         strcpy(G.sce, scestr);
182
183         BIF_InitTheme();        // sets default again
184
185         if (success) {
186                 mainwindow_set_filename_to_title(tstr);
187                 countall();
188                 G.save_over = 0;
189
190                 /*  disable autoplay in .B.blend... */
191                 G.fileflags &= ~G_FILE_AUTOPLAY;
192
193 #ifdef _WIN32   // FULLSCREEN
194                 /* choose window startmode */
195                 switch (G.windowstate){
196                         case G_WINDOWSTATE_USERDEF: /* use the usersetting */
197                                 break;
198                         case G_WINDOWSTATE_FULLSCREEN: /* force fullscreen */
199                                 U.uiflag |= USER_FLIPFULLSCREEN;
200                                 break;
201                         case G_WINDOWSTATE_BORDER: /* force with borders */
202                                 U.uiflag &= ~USER_FLIPFULLSCREEN;
203                 }
204
205                 if(screenmode != (U.uiflag & USER_FLIPFULLSCREEN)) {
206                         mainwindow_toggle_fullscreen ((U.uiflag & USER_FLIPFULLSCREEN));
207                         screenmode = (U.uiflag & USER_FLIPFULLSCREEN);
208                 }
209 #endif
210
211                 if (BLI_streq(U.tempdir, "/")) {
212                         char *tmp= getenv("TEMP");
213
214                         strcpy(U.tempdir, tmp?tmp:"/tmp/");
215                 }
216                 if (U.savetime <= 0) {
217                         U.savetime = 1;
218                         error("%s is buggy, please consider removing it.\n",
219                                 tstr);
220                 }
221                 if (G.main->versionfile <= 191) {
222                         strcpy(U.plugtexdir, U.textudir);
223                         strcpy(U.sounddir, "/");
224                 }
225
226                         /* patch to set Dupli Armature */
227                 if (G.main->versionfile < 220) {
228                         U.dupflag |= USER_DUP_ARM;
229                 }
230
231                         /* userdef new option */
232                 if (G.main->versionfile <= 222) {
233                         U.vrmlflag= USER_VRML_LAYERS;
234                 }
235
236                         /* added seam, normal color, undo */
237                 if (G.main->versionfile <= 234) {
238                         bTheme *btheme;
239                         
240                         U.uiflag |= USER_GLOBALUNDO;
241                         
242                         for(btheme= U.themes.first; btheme; btheme= btheme->next) {
243                                 /* check for alpha==0 is safe, then color was never set */
244                                 if(btheme->tv3d.edge_seam[3]==0) {
245                                         btheme->tv3d.edge_seam[0]= 230;
246                                         btheme->tv3d.edge_seam[1]= 150;
247                                         btheme->tv3d.edge_seam[2]= 50;
248                                         btheme->tv3d.edge_seam[3]= 255;
249                                 }
250                                 if(btheme->tv3d.normal[3]==0) {
251                                         btheme->tv3d.normal[0]= 0x22;
252                                         btheme->tv3d.normal[1]= 0xDD;
253                                         btheme->tv3d.normal[2]= 0xDD;
254                                         btheme->tv3d.normal[3]= 255;
255                                 }
256                                 if(btheme->tv3d.face_dot[3]==0) {
257                                         btheme->tv3d.face_dot[0]= 255;
258                                         btheme->tv3d.face_dot[1]= 138;
259                                         btheme->tv3d.face_dot[2]= 48;
260                                         btheme->tv3d.face_dot[3]= 255;
261                                         btheme->tv3d.facedot_size= 4;
262                                 }
263                         }
264                 }
265                 if (G.main->versionfile <= 235) {
266                         /* illegal combo... */
267                         if (U.flag & USER_LMOUSESELECT) 
268                                 U.flag &= ~USER_TWOBUTTONMOUSE;
269                 }
270                 
271                 space_set_commmandline_options();
272
273                 if (U.undosteps==0) U.undosteps=32;
274                 undo_editmode_clear();
275                 BKE_reset_undo();
276                 BKE_write_undo("original");     /* save current state */
277
278                 reset_autosave();
279
280 #ifdef INTERNATIONAL
281                 read_languagefile();
282         
283                 if(U.transopts & USER_DOTRANSLATE)
284                         start_interface_font();
285                 else
286                         G.ui_international = FALSE;
287 #endif // INTERNATIONAL
288
289         }
290
291         return success;
292 }
293
294 static void get_autosave_location(char buf[FILE_MAXDIR+FILE_MAXFILE])
295 {
296         char pidstr[32];
297
298         sprintf(pidstr, "%d.blend", abs(getpid()));
299         BLI_make_file_string("/", buf, U.tempdir, pidstr);
300 }
301
302 void BIF_read_autosavefile(void)
303 {
304         char tstr[FILE_MAXDIR+FILE_MAXFILE], scestr[FILE_MAXDIR];
305         int save_over;
306
307         strcpy(scestr, G.sce);  /* temporal store */
308         
309         get_autosave_location(tstr);
310
311         save_over = G.save_over;
312         BKE_read_file(tstr, NULL);
313         G.save_over = save_over;
314         strcpy(G.sce, scestr);
315 }
316
317 /***/
318
319 static void readBlog(void)
320 {
321         char name[FILE_MAXDIR+FILE_MAXFILE];
322         LinkNode *l, *lines;
323
324         BLI_make_file_string("/", name, BLI_gethome(), ".Blog");
325         lines= BLI_read_file_as_lines(name);
326
327         if (lines && !BLI_streq(lines->link, "")) {
328                 strcpy(G.sce, lines->link);
329         } else {
330                 BLI_make_file_string("/", G.sce, BLI_gethome(), "untitled.blend");
331         }
332
333         BLI_free_file_lines(lines);
334
335 #ifdef WIN32
336         /* Add the drive names to the listing */
337         {
338                 __int64 tmp;
339                 char tmps[4];
340                 int i;
341                         
342                 tmp= GetLogicalDrives();
343                 
344                 for (i=2; i < 26; i++) {
345                         if ((tmp>>i) & 1) {
346                                 tmps[0]='a'+i;
347                                 tmps[1]=':';
348                                 tmps[2]='\\';
349                                 tmps[3]=0;
350                                 
351                                 fsmenu_insert_entry(tmps, 0);
352                         }
353                 }
354                 
355                 fsmenu_append_seperator();
356         }
357 #endif
358
359         BLI_make_file_string(G.sce, name, BLI_gethome(), ".Bfs");
360         lines= BLI_read_file_as_lines(name);
361
362         for (l= lines; l; l= l->next) {
363                 char *line= l->link;
364                         
365                 if (!BLI_streq(line, "")) {
366                         fsmenu_insert_entry(line, 0);
367                 }
368         }
369
370         fsmenu_append_seperator();
371         BLI_free_file_lines(lines);
372 }
373
374
375 static void writeBlog(void)
376 {
377         char name[FILE_MAXDIR+FILE_MAXFILE];
378         FILE *fp;
379
380         BLI_make_file_string("/", name, BLI_gethome(), ".Blog");
381
382         fp= fopen(name, "w");
383         if (fp) {
384                 fprintf(fp, G.sce);
385                 fclose(fp);
386         }
387 }
388
389 static void do_history(char *name)
390 {
391         char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE];
392         int hisnr= U.versions;
393         
394         if(U.versions==0) return;
395         if(strlen(name)<2) return;
396                 
397         while(  hisnr > 1) {
398                 sprintf(tempname1, "%s%d", name, hisnr-1);
399                 sprintf(tempname2, "%s%d", name, hisnr);
400         
401                 if(BLI_rename(tempname1, tempname2))
402                         error("Unable to make version backup");
403                         
404                 hisnr--;
405         }
406                 
407         /* is needed when hisnr==1 */
408         sprintf(tempname1, "%s%d", name, hisnr);
409         
410         if(BLI_rename(name, tempname1))
411                 error("Unable to make version backup");
412 }
413
414 void BIF_write_file(char *target)
415 {
416         Library *li;
417         char di[FILE_MAXDIR];
418         char *err;
419         
420         if (BLI_streq(target, "")) return;
421  
422         /*Send the OnSave event*/
423         if (G.f & G_SCENESCRIPT) {
424                 BPY_do_pyscript(&G.scene->id, SCRIPT_ONSAVE);
425         }
426
427         for (li= G.main->library.first; li; li= li->id.next) {
428                 if (BLI_streq(li->name, target)) {
429                         error("Cannot overwrite used library");
430                         return;
431                 }
432         }
433         
434         if (!BLO_has_bfile_extension(target)) {
435                 sprintf(di, "%s.blend", target);
436         } else {
437                 strcpy(di, target);
438         }
439
440         if (BLI_exists(di)) {
441                 if(!saveover(di))
442                         return; 
443         }
444         
445         waitcursor(1);
446         
447         if(G.obedit) {
448                 exit_editmode(0);       /* 0 = no free data */
449         }
450         if (G.fileflags & G_AUTOPACK) {
451                 packAll();
452         }
453
454         do_history(di);
455                 
456         if (BLO_write_file(di, G.fileflags, &err)) {
457                 strcpy(G.sce, di);
458                 strcpy(G.main->name, di);       /* is guaranteed current file */
459
460                 mainwindow_set_filename_to_title(G.main->name);
461
462                 G.save_over = 1;
463
464                 writeBlog();
465         } else {
466                 error("%s", err);
467         }
468
469         waitcursor(0);
470 }
471
472 void BIF_write_homefile(void)
473 {
474         char *err, tstr[FILE_MAXDIR+FILE_MAXFILE];
475         int write_flags;
476         
477         BLI_make_file_string("/", tstr, BLI_gethome(), ".B.blend");
478                 
479         /*  force save as regular blend file */
480         write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
481         BLO_write_file(tstr, write_flags, &err);
482 }
483
484 void BIF_write_autosave(void)
485 {
486         char *err, tstr[FILE_MAXDIR+FILE_MAXFILE];
487         int write_flags;
488         
489         get_autosave_location(tstr);
490
491                 /*  force save as regular blend file */
492         write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
493         BLO_write_file(tstr, write_flags, &err);
494 }
495
496 /* if global undo; remove tempsave, otherwise rename */
497 static void delete_autosave(void)
498 {
499         char tstr[FILE_MAXDIR+FILE_MAXFILE];
500         
501         get_autosave_location(tstr);
502
503         if (BLI_exists(tstr)) {
504                 char str[FILE_MAXDIR+FILE_MAXFILE];
505                 BLI_make_file_string("/", str, U.tempdir, "quit.blend");
506
507                 if(U.uiflag & USER_GLOBALUNDO) BLI_delete(tstr, 0, 0);
508                 else BLI_rename(tstr, str);
509         }
510 }
511
512 /***/
513
514 static void initbuttons(void)
515 {
516         uiDefFont(UI_HELVB, 
517                                 BMF_GetFont(BMF_kHelveticaBold14), 
518                                 BMF_GetFont(BMF_kHelveticaBold12), 
519                                 BMF_GetFont(BMF_kHelveticaBold10), 
520                                 BMF_GetFont(BMF_kHelveticaBold8));
521         uiDefFont(UI_HELV, 
522                                 BMF_GetFont(BMF_kHelvetica12), 
523                                 BMF_GetFont(BMF_kHelvetica12), 
524                                 BMF_GetFont(BMF_kHelvetica10), 
525                                 BMF_GetFont(BMF_kHelveticaBold8));
526         
527         BIF_resources_init();
528
529         glClearColor(.7, .7, .6, 0.0);
530         
531         G.font= BMF_GetFont(BMF_kHelvetica12);
532         G.fonts= BMF_GetFont(BMF_kHelvetica10);
533         G.fontss= BMF_GetFont(BMF_kHelveticaBold8);
534
535         clear_matcopybuf();
536 }
537
538
539 static void sound_init_listener(void)
540 {
541         G.listener = MEM_callocN(sizeof(bSoundListener), "soundlistener");
542         G.listener->gain = 1.0;
543         G.listener->dopplerfactor = 1.0;
544         G.listener->dopplervelocity = 1.0;
545 }
546
547 void BIF_init(void)
548 {
549
550         initscreen();   /* for (visuele) speed, this first, then setscreen */
551         initbuttons();
552         InitCursorData();
553         sound_init_listener();
554         
555         init_draw_rects();      /* drawobject.c */
556         BIF_read_homefile();
557         init_gl_stuff();        /* drawview.c, after homefile */
558         readBlog();
559         strcpy(G.lib, G.sce);
560
561 }
562
563 /***/
564
565 extern ListBase editNurb;
566 extern ListBase editelems;
567
568 void exit_usiblender(void)
569 {
570         freeAllRad();
571         BKE_freecubetable();
572
573         if (G.background == 0)
574                 sound_end_all_sounds();
575
576         if(G.obedit) {
577                 if(G.obedit->type==OB_FONT) {
578                         free_editText();
579                 }
580                 else if(G.obedit->type==OB_MBALL) BLI_freelistN(&editelems);
581                 free_editMesh(G.editMesh);
582         }
583
584         free_editLatt();
585         free_editArmature();
586         free_posebuf();
587
588         free_blender(); /* blender.c, does entire library */
589         free_matcopybuf();
590         free_ipocopybuf();
591         freefastshade();
592         free_vertexpaint();
593         
594         /* editnurb can remain to exist outside editmode */
595         freeNurblist(&editNurb);
596
597         fsmenu_free();
598 #ifdef INTERNATIONAL
599         free_languagemenu();
600 #endif  
601         
602         RE_free_render_data();
603         RE_free_filt_mask();
604         
605         free_txt_data();
606
607         sound_exit_audio();
608         if(G.listener) MEM_freeN(G.listener);
609
610 #ifdef WITH_QUICKTIME
611         quicktime_exit();
612 #endif
613                 
614         BPY_end_python();
615
616         if (!G.background) {
617                 BIF_resources_free();
618         
619                 BIF_close_render_display();
620                 mainwindow_close();
621         }
622
623 #ifdef INTERNATIONAL
624         FTF_End();
625 #endif
626
627         /* undo free stuff */
628         undo_editmode_clear();
629         
630         BKE_undo_save_quit();   // saves quit.blend if global undo is on
631         BKE_reset_undo(); 
632         
633         BLI_freelistN(&U.themes);
634         
635         if(totblock!=0) {
636                 printf("Error Totblock: %d\n",totblock);
637                 MEM_printmemlist();
638         }
639         delete_autosave();
640         
641         printf("\nBlender quit\n");
642
643 #ifdef WIN32   
644         /* ask user to press enter when in debug mode */
645         if(G.f & G_DEBUG) {
646                 printf("press enter key to exit...\n\n");
647                 getchar();
648         }
649 #endif 
650
651
652         SYS_DeleteSystem(SYS_GetSystem());
653
654         exit(G.afbreek==1);
655 }