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