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