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