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