* doing some warning cleaning
[blender.git] / source / blender / blenkernel / intern / blender.c
1 /*  blender.c   jan 94     MIXED MODEL
2  * 
3  * common help functions and data
4  * 
5  * $Id$
6  *
7  * ***** BEGIN GPL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
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 LICENSE BLOCK *****
31  */
32
33 #ifndef _WIN32 
34         #include <unistd.h> // for read close
35         #include <sys/param.h> // for MAXPATHLEN
36 #else
37         #include <io.h> // for open close read
38         #define open _open
39         #define read _read
40         #define close _close
41         #define write _write
42 #endif
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <fcntl.h> // for open
48
49 #include "MEM_guardedalloc.h"
50
51 #include "DNA_listBase.h"
52 #include "DNA_sdna_types.h"
53 #include "DNA_userdef_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_curve_types.h"
56 #include "DNA_scene_types.h"
57
58 #include "BLI_blenlib.h"
59 #include "BLI_dynstr.h"
60
61 #include "IMB_imbuf_types.h"
62 #include "IMB_imbuf.h"
63
64 #include "DNA_mesh_types.h"
65 #include "DNA_screen_types.h"
66
67 #include "BKE_action.h"
68 #include "BKE_blender.h"
69 #include "BKE_curve.h"
70 #include "BKE_depsgraph.h"
71 #include "BKE_displist.h"
72 #include "BKE_font.h"
73 #include "BKE_global.h"
74 #include "BKE_library.h"
75 #include "BKE_main.h"
76 #include "BKE_node.h"
77 #include "BKE_object.h"
78 #include "BKE_scene.h"
79 #include "BKE_sound.h"
80
81 #include "BLI_editVert.h"
82
83 #include "BLO_undofile.h"
84 #include "BLO_readfile.h" 
85 #include "BLO_writefile.h" 
86
87 #include "BKE_bad_level_calls.h" // for freeAllRad editNurb free_editMesh free_editText free_editArmature
88 #include "BKE_utildefines.h" // O_BINARY FALSE
89 #include "BIF_mainqueue.h" // mainqenter for onload script
90 #include "mydevice.h"
91 #include "nla.h"
92 #include "blendef.h"
93
94 Global G;
95 UserDef U;
96
97 char versionstr[48]= "";
98
99 /* ************************************************ */
100 /* pushpop facility: to store data temporally, FIFO! */
101
102 ListBase ppmain={0, 0};
103
104 typedef struct PushPop {
105         struct PushPop *next, *prev;
106         void *data;
107         int len;
108 } PushPop;
109
110 void pushdata(void *data, int len)
111 {
112         PushPop *pp;
113         
114         pp= MEM_mallocN(sizeof(PushPop), "pushpop");
115         BLI_addtail(&ppmain, pp);
116         pp->data= MEM_mallocN(len, "pushpop");
117         pp->len= len;
118         memcpy(pp->data, data, len);
119 }
120
121 void popfirst(void *data)
122 {
123         PushPop *pp;
124         
125         pp= ppmain.first;
126         if(pp) {
127                 memcpy(data, pp->data, pp->len);
128                 BLI_remlink(&ppmain, pp);
129                 MEM_freeN(pp->data);
130                 MEM_freeN(pp);
131         }
132         else printf("error in popfirst\n");
133 }
134
135 void poplast(void *data)
136 {
137         PushPop *pp;
138         
139         pp= ppmain.last;
140         if(pp) {
141                 memcpy(data, pp->data, pp->len);
142                 BLI_remlink(&ppmain, pp);
143                 MEM_freeN(pp->data);
144                 MEM_freeN(pp);
145         }
146         else printf("error in poplast\n");
147 }
148
149 void free_pushpop()
150 {
151         PushPop *pp;
152
153         pp= ppmain.first;
154         while(pp) {
155                 BLI_remlink(&ppmain, pp);
156                 MEM_freeN(pp->data);
157                 MEM_freeN(pp);
158         }       
159 }
160
161 void pushpop_test()
162 {
163         if(ppmain.first) printf("pushpop not empty\n");
164         free_pushpop();
165 }
166
167
168
169 /* ********** free ********** */
170
171 void free_blender(void)
172 {
173         /* samples are in a global list..., also sets G.main->sound->sample NULL */
174         sound_free_all_samples();
175         
176         free_main(G.main);
177         G.main= NULL;
178
179         IMB_freeImBufdata();            /* imbuf lib */
180         
181         free_nodesystem();      
182 }
183
184 void duplicatelist(ListBase *list1, ListBase *list2)  /* copy from 2 to 1 */
185 {
186         struct Link *link1, *link2;
187         
188         list1->first= list1->last= 0;
189         
190         link2= list2->first;
191         while(link2) {
192
193                 link1= MEM_dupallocN(link2);
194                 BLI_addtail(list1, link1);
195                 
196                 link2= link2->next;
197         }       
198 }
199
200 static EditMesh theEditMesh;
201
202 void initglobals(void)
203 {
204         memset(&G, 0, sizeof(Global));
205         
206         memset(&theEditMesh, 0, sizeof(theEditMesh));
207         G.editMesh = &theEditMesh;
208
209         U.savetime= 1;
210
211         G.main= MEM_callocN(sizeof(Main), "initglobals");
212
213         strcpy(G.ima, "//");
214
215         G.version= BLENDER_VERSION;
216
217         G.order= 1;
218         G.order= (((char*)&G.order)[0])?L_ENDIAN:B_ENDIAN;
219
220         if(BLENDER_SUBVERSION)
221                 sprintf(versionstr, "www.blender.org %d.%d", G.version, BLENDER_SUBVERSION);
222         else
223                 sprintf(versionstr, "www.blender.org %d", G.version);
224
225 #ifdef _WIN32   // FULLSCREEN
226         G.windowstate = G_WINDOWSTATE_USERDEF;
227 #endif
228
229         clear_workob(); /* object.c */
230
231         G.charstart = 0x0000;
232         G.charmin = 0x0000;
233         G.charmax = 0xffff;
234 }
235
236 /***/
237
238 static void clear_global(void) 
239 {
240         extern short winqueue_break;    /* screen.c */
241
242         freeAllRad();
243         fastshade_free_render();        /* lamps hang otherwise */
244         free_main(G.main);                      /* free all lib data */
245
246         /* force all queues to be left */
247         winqueue_break= 1;
248         
249         if (G.obedit) {
250                 freeNurblist(&editNurb);
251                 free_editMesh(G.editMesh);
252                 free_editText();
253                 free_editArmature();
254         }
255
256         G.curscreen= NULL;
257         G.scene= NULL;
258         G.main= NULL;
259         
260         G.obedit= NULL;
261         G.saction= NULL;
262         G.buts= NULL;
263         G.v2d= NULL;
264         G.vd= NULL;
265         G.soops= NULL;
266         G.sima= NULL;
267         G.sipo= NULL;
268         
269         free_vertexpaint();
270         
271         G.f &= ~(G_WEIGHTPAINT + G_VERTEXPAINT + G_FACESELECT + G_PARTICLEEDIT);
272 }
273
274 /* make sure path names are correct for OS */
275 static void clean_paths(Main *main)
276 {
277         Image *image= main->image.first;
278         bSound *sound= main->sound.first;
279         Scene *scene= main->scene.first;
280         Editing *ed;
281         Sequence *seq;
282         Strip *strip;
283         
284         while(image) {
285                 BLI_clean(image->name);
286                 image= image->id.next;
287         }
288         
289         while(sound) {
290                 BLI_clean(sound->name);
291                 sound= sound->id.next;
292         }
293         
294         while(scene) {
295                 ed= scene->ed;
296                 if(ed) {
297                         seq= ed->seqbasep->first;
298                         while(seq) {
299                                 if(seq->plugin) {
300                                         BLI_clean(seq->plugin->name);
301                                 }
302                                 strip= seq->strip;
303                                 while(strip) {
304                                         BLI_clean(strip->dir);
305                                         strip= strip->next;
306                                 }
307                                 seq= seq->next;
308                         }
309                 }
310                 BLI_clean(scene->r.backbuf);
311                 BLI_clean(scene->r.pic);
312                 
313                 scene= scene->id.next;
314         }
315 }
316
317 static void setup_app_data(BlendFileData *bfd, char *filename) 
318 {
319         Object *ob;
320         bScreen *curscreen= NULL;
321         Scene *curscene= NULL;
322         char mode;
323         
324         /* 'u' = undo save, 'n' = no UI load */
325         if(bfd->main->screen.first==NULL) mode= 'u';
326         else if(G.fileflags & G_FILE_NO_UI) mode= 'n';
327         else mode= 0;
328         
329         clean_paths(bfd->main);
330         
331         /* no load screens? */
332         if(mode) {
333                 /* comes from readfile.c */
334                 extern void lib_link_screen_restore(Main *, Scene *);
335                 
336                 SWAP(ListBase, G.main->screen, bfd->main->screen);
337                 SWAP(ListBase, G.main->script, bfd->main->script);
338                 
339                 /* we re-use current screen */
340                 curscreen= G.curscreen;
341                 /* but use new Scene pointer */
342                 curscene= bfd->curscene;
343                 if(curscene==NULL) curscene= bfd->main->scene.first;
344                 /* and we enforce curscene to be in current screen */
345                 curscreen->scene= curscene;
346
347                 /* clear_global will free G.main, here we can still restore pointers */
348                 lib_link_screen_restore(bfd->main, curscene);
349         }
350         
351         clear_global(); /* free Main database */
352         
353         if(mode!='u') G.save_over = 1;
354         
355         G.main= bfd->main;
356         if (bfd->user) {
357                 
358                 /* only here free userdef themes... */
359                 BLI_freelistN(&U.themes);
360
361                 U= *bfd->user;
362                 MEM_freeN(bfd->user);
363                 
364         }
365         
366         /* samples is a global list... */
367         sound_free_all_samples();
368         
369         /* case G_FILE_NO_UI or no screens in file */
370         if(mode) {
371                 G.curscreen= curscreen;
372                 G.scene= curscene;
373         }
374         else {
375                 G.winpos= bfd->winpos;
376                 G.displaymode= bfd->displaymode;
377                 G.fileflags= bfd->fileflags;
378                 G.curscreen= bfd->curscreen;
379                 G.scene= G.curscreen->scene;
380         }
381         /* this can happen when active scene was lib-linked, and doesnt exist anymore */
382         if(G.scene==NULL) {
383                 G.scene= G.main->scene.first;
384                 G.curscreen->scene= G.scene;
385         }
386
387         /* special cases, override loaded flags: */
388         if (G.f & G_DEBUG) bfd->globalf |= G_DEBUG;
389         else bfd->globalf &= ~G_DEBUG;
390
391         if ((U.flag & USER_DONT_DOSCRIPTLINKS)) bfd->globalf &= ~G_DOSCRIPTLINKS;
392
393         G.f= bfd->globalf;
394
395         if (!G.background) {
396                 setscreen(G.curscreen);
397         }
398         
399         /* baseflags, groups, make depsgraph, etc */
400         set_scene_bg(G.scene);
401
402         /* clear BONE_UNKEYED flags, these are not valid anymore for proxies */
403         framechange_poses_clear_unkeyed();
404
405         /* last stage of do_versions actually, that sets recalc flags for recalc poses */
406         for(ob= G.main->object.first; ob; ob= ob->id.next) {
407                 if(ob->type==OB_ARMATURE)
408                         if(ob->recalc) object_handle_update(ob);
409         }
410         
411         /* now tag update flags, to ensure deformers get calculated on redraw */
412         DAG_scene_update_flags(G.scene, G.scene->lay);
413         
414         if (G.f & G_DOSCRIPTLINKS) {
415                 /* there's an onload scriptlink to execute in screenmain */
416                 mainqenter(ONLOAD_SCRIPT, 1);
417         }
418         if (G.sce != filename) /* these are the same at times, should never copy to the same location */
419                 strcpy(G.sce, filename);
420         
421         BLI_strncpy(G.main->name, filename, FILE_MAX); /* is guaranteed current file */
422         
423         MEM_freeN(bfd);
424 }
425
426 static void handle_subversion_warning(Main *main)
427 {
428         if(main->minversionfile > BLENDER_VERSION ||
429            (main->minversionfile == BLENDER_VERSION && 
430                  main->minsubversionfile > BLENDER_SUBVERSION)) {
431                 
432                 char str[128];
433                 
434                 sprintf(str, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile);
435                 error(str);
436         }
437                 
438 }
439
440 /* returns:
441    0: no load file
442    1: OK
443    2: OK, and with new user settings
444 */
445
446 int BKE_read_file(char *dir, void *type_r) 
447 {
448         BlendReadError bre;
449         BlendFileData *bfd;
450         int retval= 1;
451         
452         if (!G.background)
453                 waitcursor(1);
454                 
455         bfd= BLO_read_from_file(dir, &bre);
456         if (bfd) {
457                 if(bfd->user) retval= 2;
458                 if (type_r)
459                         *((BlenFileType*)type_r)= bfd->type;
460                 
461                 setup_app_data(bfd, dir);
462                 
463                 handle_subversion_warning(G.main);
464         } 
465         else {
466                 error("Loading %s failed: %s", dir, BLO_bre_as_string(bre));
467         }
468         
469         if (!G.background)
470                 waitcursor(0);
471         
472         return (bfd?retval:0);
473 }
474
475 int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r)
476 {
477         BlendReadError bre;
478         BlendFileData *bfd;
479         
480         if (!G.background)
481                 waitcursor(1);
482                 
483         bfd= BLO_read_from_memory(filebuf, filelength, &bre);
484         if (bfd) {
485                 if (type_r)
486                         *((BlenFileType*)type_r)= bfd->type;
487                 
488                 setup_app_data(bfd, "<memory2>");
489         } else {
490                 error("Loading failed: %s", BLO_bre_as_string(bre));
491         }
492         
493         if (!G.background)
494                 waitcursor(0);
495         
496         return (bfd?1:0);
497 }
498
499 /* memfile is the undo buffer */
500 int BKE_read_file_from_memfile(MemFile *memfile)
501 {
502         BlendReadError bre;
503         BlendFileData *bfd;
504         
505         if (!G.background)
506                 waitcursor(1);
507                 
508         bfd= BLO_read_from_memfile(G.sce, memfile, &bre);
509         if (bfd) {
510                 setup_app_data(bfd, "<memory1>");
511         } else {
512                 error("Loading failed: %s", BLO_bre_as_string(bre));
513         }
514         
515         if (!G.background)
516                 waitcursor(0);
517         
518         return (bfd?1:0);
519 }
520
521
522 /* ***************** GLOBAL UNDO *************** */
523
524 #define UNDO_DISK       0
525
526 #define MAXUNDONAME     64
527 typedef struct UndoElem {
528         struct UndoElem *next, *prev;
529         char str[FILE_MAXDIR+FILE_MAXFILE];
530         char name[MAXUNDONAME];
531         MemFile memfile;
532         uintptr_t undosize;
533 } UndoElem;
534
535 static ListBase undobase={NULL, NULL};
536 static UndoElem *curundo= NULL;
537
538
539 static int read_undosave(UndoElem *uel)
540 {
541         char scestr[FILE_MAXDIR+FILE_MAXFILE];
542         int success=0, fileflags;
543         
544         strcpy(scestr, G.sce);  /* temporal store */
545         fileflags= G.fileflags;
546         G.fileflags |= G_FILE_NO_UI;
547
548         if(UNDO_DISK) 
549                 success= BKE_read_file(uel->str, NULL);
550         else
551                 success= BKE_read_file_from_memfile(&uel->memfile);
552         
553         /* restore */
554         strcpy(G.sce, scestr);
555         G.fileflags= fileflags;
556
557         return success;
558 }
559
560 /* name can be a dynamic string */
561 void BKE_write_undo(char *name)
562 {
563         uintptr_t maxmem, totmem, memused;
564         int nr, success;
565         UndoElem *uel;
566         
567         if( (U.uiflag & USER_GLOBALUNDO)==0) return;
568         if( U.undosteps==0) return;
569         
570         /* remove all undos after (also when curundo==NULL) */
571         while(undobase.last != curundo) {
572                 uel= undobase.last;
573                 BLI_remlink(&undobase, uel);
574                 BLO_free_memfile(&uel->memfile);
575                 MEM_freeN(uel);
576         }
577         
578         /* make new */
579         curundo= uel= MEM_callocN(sizeof(UndoElem), "undo file");
580         strncpy(uel->name, name, MAXUNDONAME-1);
581         BLI_addtail(&undobase, uel);
582         
583         /* and limit amount to the maximum */
584         nr= 0;
585         uel= undobase.last;
586         while(uel) {
587                 nr++;
588                 if(nr==U.undosteps) break;
589                 uel= uel->prev;
590         }
591         if(uel) {
592                 while(undobase.first!=uel) {
593                         UndoElem *first= undobase.first;
594                         BLI_remlink(&undobase, first);
595                         /* the merge is because of compression */
596                         BLO_merge_memfile(&first->memfile, &first->next->memfile);
597                         MEM_freeN(first);
598                 }
599         }
600
601
602         /* disk save version */
603         if(UNDO_DISK) {
604                 static int counter= 0;
605                 char *err, tstr[FILE_MAXDIR+FILE_MAXFILE];
606                 char numstr[32];
607                 
608                 /* calculate current filename */
609                 counter++;
610                 counter= counter % U.undosteps; 
611         
612                 sprintf(numstr, "%d.blend", counter);
613                 BLI_make_file_string("/", tstr, btempdir, numstr);
614         
615                 success= BLO_write_file(tstr, G.fileflags, &err);
616                 
617                 strcpy(curundo->str, tstr);
618         }
619         else {
620                 MemFile *prevfile=NULL;
621                 char *err;
622                 
623                 if(curundo->prev) prevfile= &(curundo->prev->memfile);
624                 
625                 memused= MEM_get_memory_in_use();
626                 success= BLO_write_file_mem(prevfile, &curundo->memfile, G.fileflags, &err);
627                 curundo->undosize= MEM_get_memory_in_use() - memused;
628         }
629
630         if(U.undomemory != 0) {
631                 /* limit to maximum memory (afterwards, we can't know in advance) */
632                 totmem= 0;
633                 maxmem= ((uintptr_t)U.undomemory)*1024*1024;
634
635                 /* keep at least two (original + other) */
636                 uel= undobase.last;
637                 while(uel && uel->prev) {
638                         totmem+= uel->undosize;
639                         if(totmem>maxmem) break;
640                         uel= uel->prev;
641                 }
642
643                 if(uel) {
644                         if(uel->prev && uel->prev->prev)
645                                 uel= uel->prev;
646
647                         while(undobase.first!=uel) {
648                                 UndoElem *first= undobase.first;
649                                 BLI_remlink(&undobase, first);
650                                 /* the merge is because of compression */
651                                 BLO_merge_memfile(&first->memfile, &first->next->memfile);
652                                 MEM_freeN(first);
653                         }
654                 }
655         }
656 }
657
658 /* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation
659  * Note, ALWAYS call sound_initialize_sounds after BKE_undo_step() */
660 void BKE_undo_step(int step)
661 {
662         
663         if(step==0) {
664                 read_undosave(curundo);
665         }
666         else if(step==1) {
667                 /* curundo should never be NULL, after restart or load file it should call undo_save */
668                 if(curundo==NULL || curundo->prev==NULL) error("No undo available");
669                 else {
670                         if(G.f & G_DEBUG) printf("undo %s\n", curundo->name);
671                         curundo= curundo->prev;
672                         read_undosave(curundo);
673                 }
674         }
675         else {
676                 
677                 /* curundo has to remain current situation! */
678                 
679                 if(curundo==NULL || curundo->next==NULL) error("No redo available");
680                 else {
681                         read_undosave(curundo->next);
682                         curundo= curundo->next;
683                         if(G.f & G_DEBUG) printf("redo %s\n", curundo->name);
684                 }
685         }
686 }
687
688 void BKE_reset_undo(void)
689 {
690         UndoElem *uel;
691         
692         uel= undobase.first;
693         while(uel) {
694                 BLO_free_memfile(&uel->memfile);
695                 uel= uel->next;
696         }
697         
698         BLI_freelistN(&undobase);
699         curundo= NULL;
700 }
701
702 /* based on index nr it does a restore */
703 void BKE_undo_number(int nr)
704 {
705         UndoElem *uel;
706         int a=1;
707         
708         for(uel= undobase.first; uel; uel= uel->next, a++) {
709                 if(a==nr) break;
710         }
711         curundo= uel;
712         BKE_undo_step(0);
713 }
714
715 char *BKE_undo_menu_string(void)
716 {
717         UndoElem *uel;
718         DynStr *ds= BLI_dynstr_new();
719         char *menu;
720
721         BLI_dynstr_append(ds, "Global Undo History %t");
722         
723         for(uel= undobase.first; uel; uel= uel->next) {
724                 BLI_dynstr_append(ds, "|");
725                 BLI_dynstr_append(ds, uel->name);
726         }
727
728         menu= BLI_dynstr_get_cstring(ds);
729         BLI_dynstr_free(ds);
730
731         return menu;
732 }
733
734         /* saves quit.blend */
735 void BKE_undo_save_quit(void)
736 {
737         UndoElem *uel;
738         MemFileChunk *chunk;
739         int file;
740         char str[FILE_MAXDIR+FILE_MAXFILE];
741         
742         if( (U.uiflag & USER_GLOBALUNDO)==0) return;
743         
744         uel= curundo;
745         if(uel==NULL) {
746                 printf("No undo buffer to save recovery file\n");
747                 return;
748         }
749         
750         /* no undo state to save */
751         if(undobase.first==undobase.last) return;
752                 
753         BLI_make_file_string("/", str, btempdir, "quit.blend");
754
755         file = open(str,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
756         if(file == -1) {
757                 error("Unable to save %s, check you have permissions", str);
758                 return;
759         }
760
761         chunk= uel->memfile.chunks.first;
762         while(chunk) {
763                 if( write(file, chunk->buf, chunk->size) != chunk->size) break;
764                 chunk= chunk->next;
765         }
766         
767         close(file);
768         
769         if(chunk) error("Unable to save %s, internal error", str);
770         else printf("Saved session recovery to %s\n", str);
771 }
772