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