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