Pydrivers: Ipo Drivers controlled by Python expressions
[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 WIN32
41 #include <shlobj.h> /* SHGetSpecialFolderPath, has to be done before BLI_winstuff for some reasons... */
42 #include "BLI_winstuff.h"
43 #include <process.h> /* getpid */
44 #else
45 #include <unistd.h> /* getpid */
46 #endif
47 #include "MEM_guardedalloc.h"
48 #include "MEM_CacheLimiterC-Api.h"
49
50 #include "BMF_Api.h"
51 #ifdef INTERNATIONAL
52 #include "BIF_language.h"
53 #include "FTF_Api.h"
54 #endif
55
56 #include "BLI_blenlib.h"
57 #include "BLI_arithb.h"
58 #include "BLI_linklist.h"
59
60 #include "IMB_imbuf_types.h"
61 #include "IMB_imbuf.h"
62
63 #include "DNA_object_types.h"
64 #include "DNA_space_types.h"
65 #include "DNA_userdef_types.h"
66 #include "DNA_sound_types.h"
67 #include "DNA_scene_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 "BLI_vfontdata.h"
81
82 #include "BIF_fsmenu.h"
83 #include "BIF_gl.h"
84 #include "BIF_interface.h"
85 #include "BIF_usiblender.h"
86 #include "BIF_drawtext.h"
87 #include "BIF_editarmature.h"
88 #include "BIF_editlattice.h"
89 #include "BIF_editfont.h"
90 #include "BIF_editmesh.h"
91 #include "BIF_editmode_undo.h"
92 #include "BIF_editsound.h"
93 #include "BIF_poseobject.h"
94 #include "BIF_previewrender.h"
95 #include "BIF_renderwin.h"
96 #include "BIF_resources.h"
97 #include "BIF_screen.h"
98 #include "BIF_space.h"
99 #include "BIF_toolbox.h"
100 #include "BIF_cursors.h"
101
102 #include "BSE_drawview.h"
103 #include "BSE_edit.h"
104 #include "BSE_editipo.h"
105 #include "BSE_filesel.h"
106 #include "BSE_headerbuttons.h"
107 #include "BSE_node.h"
108
109 #include "BLO_readfile.h"
110 #include "BLO_writefile.h"
111
112 #include "BDR_drawobject.h"
113 #include "BDR_editobject.h"
114 #include "BDR_editcurve.h"
115 #include "BDR_vpaint.h"
116
117 #include "BPY_extern.h"
118
119 #include "blendef.h"
120
121 #include "RE_pipeline.h"                /* RE_ free stuff */
122
123 #include "radio.h"
124 #include "datatoc.h"
125
126 #include "SYS_System.h"
127
128 #include "PIL_time.h"
129
130 /***/
131
132 /* define for setting colors in theme below */
133 #define SETCOL(col, r, g, b, a)  col[0]=r; col[1]=g; col[2]= b; col[3]= a;
134
135 /* patching UserDef struct, set globals for UI stuff */
136 static void init_userdef_file(void)
137 {
138         
139         BIF_InitTheme();        // sets default again
140         
141         mainwindow_set_filename_to_title("");   // empty string re-initializes title to "Blender"
142         countall();
143         G.save_over = 0;        // start with save preference untitled.blend
144         
145         /*  disable autoplay in .B.blend... */
146         G.fileflags &= ~G_FILE_AUTOPLAY;
147         
148         /* the UserDef struct is not corrected with do_versions() .... ugh! */
149         if(U.wheellinescroll == 0) U.wheellinescroll = 3;
150         if(U.menuthreshold1==0) {
151                 U.menuthreshold1= 5;
152                 U.menuthreshold2= 2;
153         }
154         if(U.tb_leftmouse==0) {
155                 U.tb_leftmouse= 5;
156                 U.tb_rightmouse= 5;
157         }
158         if(U.mixbufsize==0) U.mixbufsize= 2048;
159         if (BLI_streq(U.tempdir, "/")) {
160                 char *tmp= getenv("TEMP");
161                 
162                 strcpy(U.tempdir, tmp?tmp:"/tmp/");
163         }
164         if (U.savetime <= 0) {
165                 U.savetime = 1;
166                 error(".B.blend is buggy, please consider removing it.\n");
167         }
168         /* transform widget settings */
169         if(U.tw_hotspot==0) {
170                 U.tw_hotspot= 14;
171                 U.tw_size= 20;                  // percentage of window size
172                 U.tw_handlesize= 16;    // percentage of widget radius
173         }
174         
175         if (G.main->versionfile <= 191) {
176                 strcpy(U.plugtexdir, U.textudir);
177                 strcpy(U.sounddir, "/");
178         }
179         
180         /* patch to set Dupli Armature */
181         if (G.main->versionfile < 220) {
182                 U.dupflag |= USER_DUP_ARM;
183         }
184         
185         /* userdef new option */
186         if (G.main->versionfile <= 222) {
187                 U.vrmlflag= USER_VRML_LAYERS;
188         }
189         
190         /* added seam, normal color, undo */
191         if (G.main->versionfile <= 234) {
192                 bTheme *btheme;
193                 
194                 U.uiflag |= USER_GLOBALUNDO;
195                 
196                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
197                         /* check for alpha==0 is safe, then color was never set */
198                         if(btheme->tv3d.edge_seam[3]==0) {
199                                 SETCOL(btheme->tv3d.edge_seam, 230, 150, 50, 255);
200                         }
201                         if(btheme->tv3d.normal[3]==0) {
202                                 SETCOL(btheme->tv3d.normal, 0x22, 0xDD, 0xDD, 255);
203                         }
204                         if(btheme->tv3d.face_dot[3]==0) {
205                                 SETCOL(btheme->tv3d.face_dot, 255, 138, 48, 255);
206                                 btheme->tv3d.facedot_size= 4;
207                         }
208                 }
209         }
210         if (G.main->versionfile <= 235) {
211                 /* illegal combo... */
212                 if (U.flag & USER_LMOUSESELECT) 
213                         U.flag &= ~USER_TWOBUTTONMOUSE;
214         }
215         if (G.main->versionfile <= 236) {
216                 bTheme *btheme;
217                 /* new space type */
218                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
219                         /* check for alpha==0 is safe, then color was never set */
220                         if(btheme->ttime.back[3]==0) {
221                                 btheme->ttime = btheme->tsnd;   // copy from sound
222                         }
223                         if(btheme->text.syntaxn[3]==0) {
224                                 SETCOL(btheme->text.syntaxn,    0, 0, 200, 255);        /* Numbers  Blue*/
225                                 SETCOL(btheme->text.syntaxl,    100, 0, 0, 255);        /* Strings  red */
226                                 SETCOL(btheme->text.syntaxc,    0, 100, 50, 255);       /* Comments greenish */
227                                 SETCOL(btheme->text.syntaxv,    95, 95, 0, 255);        /* Special */
228                                 SETCOL(btheme->text.syntaxb,    128, 0, 80, 255);       /* Builtin, red-purple */
229                         }
230                 }
231         }
232         if (G.main->versionfile <= 237) {
233                 bTheme *btheme;
234                 /* bone colors */
235                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
236                         /* check for alpha==0 is safe, then color was never set */
237                         if(btheme->tv3d.bone_solid[3]==0) {
238                                 SETCOL(btheme->tv3d.bone_solid, 200, 200, 200, 255);
239                                 SETCOL(btheme->tv3d.bone_pose, 80, 200, 255, 80);
240                         }
241                 }
242         }
243         if (G.main->versionfile <= 238) {
244                 bTheme *btheme;
245                 /* bone colors */
246                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
247                         /* check for alpha==0 is safe, then color was never set */
248                         if(btheme->tnla.strip[3]==0) {
249                                 SETCOL(btheme->tnla.strip_select,       0xff, 0xff, 0xaa, 255);
250                                 SETCOL(btheme->tnla.strip, 0xe4, 0x9c, 0xc6, 255);
251                         }
252                 }
253         }
254         if (G.main->versionfile <= 239) {
255                 bTheme *btheme;
256                 
257                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
258                         /* Lamp theme, check for alpha==0 is safe, then color was never set */
259                         if(btheme->tv3d.lamp[3]==0) {
260                                 SETCOL(btheme->tv3d.lamp,       0, 0, 0, 40);
261 /* TEMPORAL, remove me! (ton) */                                
262                                 U.uiflag |= USER_PLAINMENUS;
263                         }
264                         
265                         /* check for text field selection highlight, set it to text editor highlight by default */
266                         if(btheme->tui.textfield_hi[3]==0) {
267                                 SETCOL(btheme->tui.textfield_hi,        
268                                         btheme->text.shade2[0], 
269                                         btheme->text.shade2[1], 
270                                         btheme->text.shade2[2],
271                                         255);
272                         }
273                 }
274                 if(U.obcenter_dia==0) U.obcenter_dia= 6;
275         }
276         if (G.main->versionfile <= 241) {
277                 bTheme *btheme;
278                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
279                         /* Node editor theme, check for alpha==0 is safe, then color was never set */
280                         if(btheme->tnode.syntaxn[3]==0) {
281                                 /* re-uses syntax color storage */
282                                 btheme->tnode= btheme->tv3d;
283                                 SETCOL(btheme->tnode.edge_select, 255, 255, 255, 255);
284                                 SETCOL(btheme->tnode.syntaxl, 150, 150, 150, 255);      /* TH_NODE, backdrop */
285                                 SETCOL(btheme->tnode.syntaxn, 95, 110, 145, 255);       /* in/output */
286                                 SETCOL(btheme->tnode.syntaxb, 135, 125, 120, 255);      /* operator */
287                                 SETCOL(btheme->tnode.syntaxv, 120, 120, 120, 255);      /* generator */
288                                 SETCOL(btheme->tnode.syntaxc, 120, 145, 120, 255);      /* group */
289                         }
290                         if(btheme->tv3d.group[3]==0) {
291                                 SETCOL(btheme->tv3d.group, 0x10, 0x40, 0x10, 255);
292                                 SETCOL(btheme->tv3d.group_active, 0x66, 0xFF, 0x66, 255);
293                         }
294                 }
295                 
296                 /* set defaults for 3D View rotating axis indicator */ 
297                 /* since size can't be set to 0, this indicates it's not saved in .B.blend */
298                 if (U.rvisize == 0) {
299                         U.rvisize = 15;
300                         U.rvibright = 8;
301                         U.uiflag |= USER_SHOW_ROTVIEWICON;
302                 }
303                 
304         }
305         
306         if (U.undosteps==0) U.undosteps=32;
307         
308         /* GL Texture Garbage Collection (variable abused above!) */
309         if (U.textimeout == 0) {
310                 U.texcollectrate = 60;
311                 U.textimeout = 120;
312         }
313         if (U.memcachelimit <= 0) {
314                 U.memcachelimit = 32;
315         }
316         if (U.frameserverport == 0) {
317                 U.frameserverport = 8080;
318         }
319
320         MEM_CacheLimiter_set_maximum(U.memcachelimit * 1024 * 1024);
321         
322         reset_autosave();
323         
324 #ifdef INTERNATIONAL
325         read_languagefile();
326         
327         refresh_interface_font();
328 #endif // INTERNATIONAL
329
330 }
331
332 void BIF_read_file(char *name)
333 {
334         extern short winqueue_break; /* editscreen.c */
335
336         //here?
337         //sound_end_all_sounds();
338
339         // first try to read exotic file formats...
340         if (BKE_read_exotic(name) == 0) { /* throws first error box */
341                 /* we didn't succeed, now try to read Blender file
342                    calls readfile, calls toolbox, throws one more,
343                    on failure calls the stream, and that is stubbed.... */
344                 int retval= BKE_read_file(name, NULL);
345
346                 mainwindow_set_filename_to_title(G.main->name);
347                 countall();
348                 sound_initialize_sounds();
349
350                 winqueue_break= 1;      /* leave queues everywhere */
351
352                 if(retval==2) init_userdef_file();      // in case a userdef is read from regular .blend
353                 
354                 undo_editmode_clear();
355                 BKE_reset_undo();
356                 BKE_write_undo("original");     /* save current state */
357                 refresh_interface_font();
358         }
359         else BIF_undo_push("Import file");
360 }
361
362 /* only here settings for fullscreen */
363 int BIF_read_homefile(void)
364 {
365         char tstr[FILE_MAXDIR+FILE_MAXFILE], scestr[FILE_MAXDIR];
366         char *home= BLI_gethome();
367         int success;
368         struct TmpFont *tf;
369         
370         BLI_clean(home);
371
372         tf= G.ttfdata.first;
373         while(tf)
374         {
375                 freePackedFile(tf->pf);
376                 tf->pf = NULL;
377                 tf->vfont = NULL;
378                 tf= tf->next;
379         }
380         BLI_freelistN(&G.ttfdata);
381         
382 #if 0
383 //#ifdef _WIN32 // FULLSCREEN
384         static int screenmode = -1;
385         
386         screenmode = U.uiflag & USER_FLIPFULLSCREEN;
387 #endif
388         
389         BLI_make_file_string(G.sce, tstr, home, ".B.blend");
390         strcpy(scestr, G.sce);  /* temporal store */
391         
392         /* prevent loading no UI */
393         G.fileflags &= ~G_FILE_NO_UI;
394         
395         if (BLI_exists(tstr)) {
396                 success = BKE_read_file(tstr, NULL);
397         } else {
398                 success = BKE_read_file_from_memory(datatoc_B_blend, datatoc_B_blend_size, NULL);
399         }
400         BLI_clean(scestr);
401         strcpy(G.sce, scestr);
402         
403 #if 0
404 //#ifdef _WIN32 // FULLSCREEN
405         /* choose window startmode */
406         switch (G.windowstate){
407                 case G_WINDOWSTATE_USERDEF: /* use the usersetting */
408                         break;
409                 case G_WINDOWSTATE_FULLSCREEN: /* force fullscreen */
410                         U.uiflag |= USER_FLIPFULLSCREEN;
411                         break;
412                 case G_WINDOWSTATE_BORDER: /* force with borders */
413                         U.uiflag &= ~USER_FLIPFULLSCREEN;
414         }
415         
416         if(screenmode != (U.uiflag & USER_FLIPFULLSCREEN)) {
417                 mainwindow_toggle_fullscreen ((U.uiflag & USER_FLIPFULLSCREEN));
418                 screenmode = (U.uiflag & USER_FLIPFULLSCREEN);
419         }
420 #endif
421         
422         space_set_commmandline_options();
423         
424         init_userdef_file();
425
426         undo_editmode_clear();
427         BKE_reset_undo();
428         BKE_write_undo("original");     /* save current state */
429         
430         return success;
431 }
432
433
434 static void get_autosave_location(char buf[FILE_MAXDIR+FILE_MAXFILE])
435 {
436         char pidstr[32];
437
438         sprintf(pidstr, "%d.blend", abs(getpid()));
439         BLI_make_file_string("/", buf, U.tempdir, pidstr);
440 }
441
442 void BIF_read_autosavefile(void)
443 {
444         char tstr[FILE_MAXDIR+FILE_MAXFILE], scestr[FILE_MAXDIR];
445         int save_over;
446
447         strcpy(scestr, G.sce);  /* temporal store */
448         
449         get_autosave_location(tstr);
450
451         save_over = G.save_over;
452         BKE_read_file(tstr, NULL);
453         G.save_over = save_over;
454         strcpy(G.sce, scestr);
455 }
456
457 /***/
458
459 static void readBlog(void)
460 {
461         char name[FILE_MAXDIR+FILE_MAXFILE], filename[FILE_MAXFILE];
462         LinkNode *l, *lines;
463
464         BLI_make_file_string("/", name, BLI_gethome(), ".Blog");
465         lines= BLI_read_file_as_lines(name);
466
467         if (lines && !BLI_streq(lines->link, "")) {
468                 strcpy(G.sce, lines->link);
469         } else {
470                 BLI_make_file_string("/", G.sce, BLI_gethome(), "untitled.blend");
471         }
472
473         BLI_free_file_lines(lines);
474
475 #ifdef WIN32
476         /* Add the drive names to the listing */
477         {
478                 __int64 tmp;
479                 char folder[MAX_PATH];
480                 char tmps[4];
481                 int i;
482                         
483                 tmp= GetLogicalDrives();
484                 
485                 for (i=2; i < 26; i++) {
486                         if ((tmp>>i) & 1) {
487                                 tmps[0]='a'+i;
488                                 tmps[1]=':';
489                                 tmps[2]='\\';
490                                 tmps[3]=0;
491                                 
492                                 fsmenu_insert_entry(tmps, 0);
493                         }
494                 }
495
496                 /* Adding Desktop and My Documents */
497                 fsmenu_append_seperator();
498                 SHGetFolderPath(0, CSIDL_PERSONAL,NULL, 0, folder);
499                 fsmenu_insert_entry(folder, 0);
500                 SHGetFolderPath(0, CSIDL_DESKTOPDIRECTORY,NULL, 0, folder);
501                 fsmenu_insert_entry(folder, 0);
502
503                 fsmenu_append_seperator();
504         }
505 #endif
506
507         BLI_make_file_string(G.sce, name, BLI_gethome(), ".Bfs");
508         lines= BLI_read_file_as_lines(name);
509
510         for (l= lines; l; l= l->next) {
511                 char *line= l->link;
512                         
513                 if (!BLI_streq(line, "")) {
514                         fsmenu_insert_entry(line, 0);
515                 }
516         }
517
518         fsmenu_append_seperator();
519         
520         /* add last saved file */
521         BLI_split_dirfile(G.sce, name, filename);
522         
523         fsmenu_insert_entry(name, 0);
524         
525         BLI_free_file_lines(lines);
526 }
527
528
529 static void writeBlog(void)
530 {
531         char name[FILE_MAXDIR+FILE_MAXFILE];
532         FILE *fp;
533
534         BLI_make_file_string("/", name, BLI_gethome(), ".Blog");
535
536         fp= fopen(name, "w");
537         if (fp) {
538                 fprintf(fp, G.sce);
539                 fclose(fp);
540         }
541 }
542
543 static void do_history(char *name)
544 {
545         char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE];
546         int hisnr= U.versions;
547         
548         if(U.versions==0) return;
549         if(strlen(name)<2) return;
550                 
551         while(  hisnr > 1) {
552                 sprintf(tempname1, "%s%d", name, hisnr-1);
553                 sprintf(tempname2, "%s%d", name, hisnr);
554         
555                 if(BLI_rename(tempname1, tempname2))
556                         error("Unable to make version backup");
557                         
558                 hisnr--;
559         }
560                 
561         /* is needed when hisnr==1 */
562         sprintf(tempname1, "%s%d", name, hisnr);
563         
564         if(BLI_rename(name, tempname1))
565                 error("Unable to make version backup");
566 }
567
568 void BIF_write_file(char *target)
569 {
570         Library *li;
571         int writeflags;
572         char di[FILE_MAXDIR];
573         char *err;
574         
575         if (BLI_streq(target, "")) return;
576  
577         /* send the OnSave event */
578         if (G.f & G_DOSCRIPTLINKS) BPY_do_pyscript(&G.scene->id, SCRIPT_ONSAVE);
579
580         for (li= G.main->library.first; li; li= li->id.next) {
581                 if (BLI_streq(li->name, target)) {
582                         error("Cannot overwrite used library");
583                         return;
584                 }
585         }
586         
587         if (!BLO_has_bfile_extension(target)) {
588                 sprintf(di, "%s.blend", target);
589         } else {
590                 strcpy(di, target);
591         }
592
593         if (BLI_exists(di)) {
594                 if(!saveover(di))
595                         return; 
596         }
597         
598         if(G.obedit) {
599                 exit_editmode(0);       /* 0 = no free data */
600         }
601         if (G.fileflags & G_AUTOPACK) {
602                 packAll();
603         }
604         
605         waitcursor(1);  // exit_editmode sets cursor too
606
607         do_history(di);
608         
609         /* we use the UserDef to define compression flag */
610         writeflags= G.fileflags & ~G_FILE_COMPRESS;
611         if(U.flag & USER_FILECOMPRESS)
612                 writeflags |= G_FILE_COMPRESS;
613         
614         if (BLO_write_file(di, writeflags, &err)) {
615                 strcpy(G.sce, di);
616                 strcpy(G.main->name, di);       /* is guaranteed current file */
617
618                 mainwindow_set_filename_to_title(G.main->name);
619
620                 G.save_over = 1;
621
622                 writeBlog();
623         } else {
624                 error("%s", err);
625         }
626
627         waitcursor(0);
628 }
629
630 void BIF_write_homefile(void)
631 {
632         char *err, tstr[FILE_MAXDIR+FILE_MAXFILE];
633         int write_flags;
634         
635         BLI_make_file_string("/", tstr, BLI_gethome(), ".B.blend");
636                 
637         /*  force save as regular blend file */
638         write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
639         BLO_write_file(tstr, write_flags, &err);
640 }
641
642 void BIF_write_autosave(void)
643 {
644         char *err, tstr[FILE_MAXDIR+FILE_MAXFILE];
645         int write_flags;
646         
647         get_autosave_location(tstr);
648
649                 /*  force save as regular blend file */
650         write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
651         BLO_write_file(tstr, write_flags, &err);
652 }
653
654 /* if global undo; remove tempsave, otherwise rename */
655 static void delete_autosave(void)
656 {
657         char tstr[FILE_MAXDIR+FILE_MAXFILE];
658         
659         get_autosave_location(tstr);
660
661         if (BLI_exists(tstr)) {
662                 char str[FILE_MAXDIR+FILE_MAXFILE];
663                 BLI_make_file_string("/", str, U.tempdir, "quit.blend");
664
665                 if(U.uiflag & USER_GLOBALUNDO) BLI_delete(tstr, 0, 0);
666                 else BLI_rename(tstr, str);
667         }
668 }
669
670 /***/
671
672 static void initbuttons(void)
673 {
674         uiDefFont(UI_HELVB, 
675                                 BMF_GetFont(BMF_kHelveticaBold14), 
676                                 BMF_GetFont(BMF_kHelveticaBold12), 
677                                 BMF_GetFont(BMF_kHelveticaBold10), 
678                                 BMF_GetFont(BMF_kHelveticaBold8));
679         uiDefFont(UI_HELV, 
680                                 BMF_GetFont(BMF_kHelvetica12), 
681                                 BMF_GetFont(BMF_kHelvetica12), 
682                                 BMF_GetFont(BMF_kHelvetica10), 
683                                 BMF_GetFont(BMF_kHelveticaBold8));
684         
685         BIF_resources_init();
686
687         glClearColor(.7f, .7f, .6f, 0.0);
688         
689         G.font= BMF_GetFont(BMF_kHelvetica12);
690         G.fonts= BMF_GetFont(BMF_kHelvetica10);
691         G.fontss= BMF_GetFont(BMF_kHelveticaBold8);
692
693         clear_matcopybuf();
694         
695         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
696 }
697
698
699 static void sound_init_listener(void)
700 {
701         G.listener = MEM_callocN(sizeof(bSoundListener), "soundlistener");
702         G.listener->gain = 1.0;
703         G.listener->dopplerfactor = 1.0;
704         G.listener->dopplervelocity = 340.29f;
705 }
706
707 void BIF_init(void)
708 {
709
710         initscreen();   /* for (visuele) speed, this first, then setscreen */
711         initbuttons();
712         InitCursorData();
713         sound_init_listener();
714         init_node_butfuncs();
715         
716         BIF_preview_init_dbase();
717         BIF_read_homefile();
718         
719         init_gl_stuff();        /* drawview.c, after homefile */
720         readBlog();
721         strcpy(G.lib, G.sce);
722
723 }
724
725 /***/
726
727 extern ListBase editNurb;
728 extern ListBase editelems;
729
730 void exit_usiblender(void)
731 {
732         struct TmpFont *tf;
733         tf= G.ttfdata.first;
734         while(tf)
735         {
736                 freePackedFile(tf->pf);
737                 tf->pf= NULL;
738                 tf->vfont= NULL;
739                 tf= tf->next;
740         }
741         BLI_freelistN(&G.ttfdata);
742
743         freeAllRad();
744         BKE_freecubetable();
745
746         if (G.background == 0)
747                 sound_end_all_sounds();
748
749         if(G.obedit) {
750                 if(G.obedit->type==OB_FONT) {
751                         free_editText();
752                 }
753                 else if(G.obedit->type==OB_MBALL) BLI_freelistN(&editelems);
754                 free_editMesh(G.editMesh);
755         }
756
757         free_editLatt();
758         free_editArmature();
759         free_posebuf();
760
761         /* before free_blender so py's gc happens while library still exists */
762         /* needed at least for a rare sigsegv that can happen in pydrivers */
763         BPY_end_python();
764
765         free_blender(); /* blender.c, does entire library */
766         free_matcopybuf();
767         free_ipocopybuf();
768         freefastshade();
769         free_vertexpaint();
770         
771         /* editnurb can remain to exist outside editmode */
772         freeNurblist(&editNurb);
773
774         fsmenu_free();
775 #ifdef INTERNATIONAL
776         free_languagemenu();
777 #endif  
778         
779         RE_FreeAllRender();
780         
781         free_txt_data();
782
783         sound_exit_audio();
784         if(G.listener) MEM_freeN(G.listener);
785
786         libtiff_exit();
787
788 #ifdef WITH_QUICKTIME
789         quicktime_exit();
790 #endif
791
792         if (!G.background) {
793                 BIF_resources_free();
794         
795                 BIF_close_render_display();
796                 mainwindow_close();
797         }
798
799 #ifdef INTERNATIONAL
800         FTF_End();
801 #endif
802
803         if (copybuf) MEM_freeN(copybuf);
804         if (copybufinfo) MEM_freeN(copybufinfo);
805
806         /* undo free stuff */
807         undo_editmode_clear();
808         
809         BKE_undo_save_quit();   // saves quit.blend if global undo is on
810         BKE_reset_undo(); 
811         
812         BLI_freelistN(&U.themes);
813         BIF_preview_free_dbase();
814                 
815         if(totblock!=0) {
816                 printf("Error Totblock: %d\n",totblock);
817                 MEM_printmemlist();
818         }
819         delete_autosave();
820         
821         printf("\nBlender quit\n");
822
823 #ifdef WIN32   
824         /* ask user to press enter when in debug mode */
825         if(G.f & G_DEBUG) {
826                 printf("press enter key to exit...\n\n");
827                 getchar();
828         }
829 #endif 
830
831
832         SYS_DeleteSystem(SYS_GetSystem());
833
834         exit(G.afbreek==1);
835 }