Second itteration of global undo system. Now based on:
[blender-staging.git] / source / blender / blenkernel / intern / blender.c
1
2 /*  blender.c   jan 94     MIXED MODEL
3  * 
4  * common help functions and data
5  * 
6  * $Id$
7  *
8  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version. The Blender
14  * Foundation also sells licenses for use in proprietary software under
15  * the Blender License.  See http://www.blender.org/BL/ for information
16  * about this.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  *
27  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
28  * All rights reserved.
29  *
30  * The Original Code is: all of this file.
31  *
32  * Contributor(s): none yet.
33  *
34  * ***** END GPL/BL DUAL LICENSE BLOCK *****
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifndef WIN32 
42     #include <unistd.h> // for read close
43     #include <sys/param.h> // for MAXPATHLEN
44 #else
45     #include <io.h> // for open close read
46 #endif
47
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <fcntl.h> // for open
52
53 #include "MEM_guardedalloc.h"
54 #include "DNA_listBase.h"
55 #include "DNA_sdna_types.h"
56 #include "DNA_userdef_types.h"
57 #include "DNA_object_types.h"
58 #include "DNA_curve_types.h"
59
60 #include "BLI_blenlib.h"
61 #include "IMB_imbuf_types.h"
62 #include "IMB_imbuf.h"
63
64 #ifdef WIN32
65 #include "BLI_winstuff.h"
66 #endif
67
68 #include "DNA_mesh_types.h"
69 #include "DNA_screen_types.h"
70
71 #include "BKE_library.h"
72 #include "BKE_blender.h"
73 #include "BKE_displist.h"
74 #include "BKE_global.h"
75 #include "BKE_main.h"
76 #include "BKE_object.h"
77 #include "BKE_scene.h"
78 #include "BKE_effect.h"
79 #include "BKE_curve.h"
80 #include "BKE_font.h"
81
82 #include "BLI_editVert.h"
83
84 #include "BLO_undofile.h"
85 #include "BLO_readfile.h" /* for BLO_read_file */
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
93 Global G;
94 UserDef U;
95
96 char versionstr[48]= "";
97
98 /* ************************************************ */
99 /* pushpop facility: to store data temporally, FIFO! */
100
101 ListBase ppmain={0, 0};
102
103 typedef struct PushPop {
104         struct PushPop *next, *prev;
105         void *data;
106         int len;
107 } PushPop;
108
109 void pushdata(void *data, int len)
110 {
111         PushPop *pp;
112         
113         pp= MEM_mallocN(sizeof(PushPop), "pushpop");
114         BLI_addtail(&ppmain, pp);
115         pp->data= MEM_mallocN(len, "pushpop");
116         pp->len= len;
117         memcpy(pp->data, data, len);
118 }
119
120 void popfirst(void *data)
121 {
122         PushPop *pp;
123         
124         pp= ppmain.first;
125         if(pp) {
126                 memcpy(data, pp->data, pp->len);
127                 BLI_remlink(&ppmain, pp);
128                 MEM_freeN(pp->data);
129                 MEM_freeN(pp);
130         }
131         else printf("error in popfirst\n");
132 }
133
134 void poplast(void *data)
135 {
136         PushPop *pp;
137         
138         pp= ppmain.last;
139         if(pp) {
140                 memcpy(data, pp->data, pp->len);
141                 BLI_remlink(&ppmain, pp);
142                 MEM_freeN(pp->data);
143                 MEM_freeN(pp);
144         }
145         else printf("error in poplast\n");
146 }
147
148 void free_pushpop()
149 {
150         PushPop *pp;
151
152         pp= ppmain.first;
153         while(pp) {
154                 BLI_remlink(&ppmain, pp);
155                 MEM_freeN(pp->data);
156                 MEM_freeN(pp);
157         }       
158 }
159
160 void pushpop_test()
161 {
162         if(ppmain.first) printf("pushpop not empty\n");
163         free_pushpop();
164 }
165
166
167
168 /* ********** free ********** */
169
170 void free_blender(void)
171 {
172         free_main(G.main);
173         G.main= NULL;
174
175         IMB_freeImBufdata();            /* imbuf lib */
176 }
177
178 void duplicatelist(ListBase *list1, ListBase *list2)  /* copy from 2 to 1 */
179 {
180         struct Link *link1, *link2;
181         
182         list1->first= list1->last= 0;
183         
184         link2= list2->first;
185         while(link2) {
186
187                 link1= MEM_dupallocN(link2);
188                 BLI_addtail(list1, link1);
189                 
190                 link2= link2->next;
191         }       
192 }
193
194 static EditMesh theEditMesh;
195
196 void initglobals(void)
197 {
198         memset(&G, 0, sizeof(Global));
199         
200         G.editMesh = &theEditMesh;
201         memset(G.editMesh, 0, sizeof(G.editMesh));
202
203         U.savetime= 1;
204
205         G.animspeed= 4;
206
207         G.main= MEM_callocN(sizeof(Main), "initglobals");
208
209         strcpy(G.ima, "//");
210
211         G.version= BLENDER_VERSION;
212
213         G.order= 1;
214         G.order= (((char*)&G.order)[0])?L_ENDIAN:B_ENDIAN;
215
216         sprintf(versionstr, "www.blender.org %d", G.version);
217
218 #ifdef _WIN32   // FULLSCREEN
219         G.windowstate = G_WINDOWSTATE_USERDEF;
220 #endif
221
222         clear_workob(); /* object.c */
223 }
224
225 /***/
226
227 static void clear_global(void) 
228 {
229         extern short winqueue_break;    /* screen.c */
230
231         freeAllRad();
232         free_main(G.main); /* free all lib data */
233         freefastshade();        /* othwerwise old lamp settings stay active */
234
235
236         /* prevent hanging vars */      
237         R.backbuf= 0;
238         
239         /* force all queues to be left */
240         winqueue_break= 1;
241         
242         if (G.obedit) {
243                 freeNurblist(&editNurb);
244                 free_editMesh();
245                 free_editText();
246                 free_editArmature();
247         }
248
249         G.curscreen= NULL;
250         G.scene= NULL;
251         G.main= NULL;
252         
253         G.obedit= NULL;
254         G.obpose= NULL;
255         G.saction= NULL;
256         G.buts= NULL;
257         G.v2d= NULL;
258         G.vd= NULL;
259         G.soops= NULL;
260         G.sima= NULL;
261         G.sipo= NULL;
262         
263         G.f &= ~(G_WEIGHTPAINT + G_VERTEXPAINT + G_FACESELECT);
264 }
265
266 static void setup_app_data(BlendFileData *bfd, char *filename) 
267 {
268         Object *ob;
269         bScreen *curscreen= NULL;
270         Scene *curscene= NULL;
271         char mode;
272         
273         /* 'u' = undo save, 'n' = no UI load */
274         if(bfd->main->screen.first==NULL) mode= 'u';
275         else if(G.fileflags & G_FILE_NO_UI) mode= 'n';
276         else mode= 0;
277         
278         /* no load screens? */
279         if(mode) {
280                 /* comes from readfile.c */
281                 extern void lib_link_screen_restore(Main *, char, Scene *);
282                 
283                 SWAP(ListBase, G.main->screen, bfd->main->screen);
284                 
285                 /* we re-use current screen */
286                 curscreen= G.curscreen;
287                 /* but use new Scene pointer */
288                 curscene= bfd->curscene;
289                 if(curscene==NULL) curscene= bfd->main->scene.first;
290                 /* and we enforce curscene to be in current screen */
291                 curscreen->scene= curscene;
292
293                 /* clear_global will free G.main, here we can still restore pointers */
294                 lib_link_screen_restore(bfd->main, mode, curscene);
295         }
296         
297         clear_global();
298         
299         G.save_over = 1;
300         
301         G.main= bfd->main;
302         if (bfd->user) {
303                 U= *bfd->user;
304                 MEM_freeN(bfd->user);
305                 
306                 /* the UserDef struct is not corrected with do_versions() .... ugh! */
307                 if(U.wheellinescroll == 0) U.wheellinescroll = 3;
308                 if(U.menuthreshold1==0) {
309                         U.menuthreshold1= 5;
310                         U.menuthreshold2= 2;
311                 }
312                 if(U.tb_leftmouse==0) {
313                         U.tb_leftmouse= 5;
314                         U.tb_rightmouse= 5;
315                 }
316                 if(U.mixbufsize==0) U.mixbufsize= 2048;
317         }
318         
319         /* case G_FILE_NO_UI or no screens in file */
320         if(mode) {
321                 G.curscreen= curscreen;
322                 G.scene= curscene;
323         }
324         else {
325                 R.winpos= bfd->winpos;
326                 R.displaymode= bfd->displaymode;
327                 G.fileflags= bfd->fileflags;
328                 G.curscreen= bfd->curscreen;
329                 G.scene= G.curscreen->scene;
330         }
331         
332         /* special cases, override loaded flags: */
333         if (G.f & G_DEBUG) bfd->globalf |= G_DEBUG;
334         else bfd->globalf &= ~G_DEBUG;
335         if (G.f & G_SCENESCRIPT) bfd->globalf |= G_SCENESCRIPT;
336         else bfd->globalf &= ~G_SCENESCRIPT;
337
338         G.f= bfd->globalf;
339         
340                 /* few DispLists, but do text_to_curve */
341         // this should be removed!!! But first a better displist system (ton)
342         for (ob= G.main->object.first; ob; ob= ob->id.next) {
343                 if(ob->type==OB_FONT) {
344                         Curve *cu= ob->data;
345                         if(cu->nurb.first==0) text_to_curve(ob, 0);
346                 }
347                 else if(ob->type==OB_MESH) {
348                         makeDispList(ob);
349                         if(ob->effect.first) object_wave(ob);
350                 }
351         }
352         
353         if (!G.background) {
354                 setscreen(G.curscreen);
355         }
356                 /* baseflags */
357         set_scene_bg(G.scene);
358
359         if (G.f & G_SCENESCRIPT) {
360                 /* there's an onload scriptlink to execute in screenmain */
361                 mainqenter(ONLOAD_SCRIPT, 1);
362         }
363
364         strcpy(G.sce, filename);
365         strcpy(G.main->name, filename); /* is guaranteed current file */
366         
367         MEM_freeN(bfd);
368 }
369
370 int BKE_read_file(char *dir, void *type_r) 
371 {
372         BlendReadError bre;
373         BlendFileData *bfd;
374         
375         if (!G.background)
376                 waitcursor(1);
377                 
378         bfd= BLO_read_from_file(dir, &bre);
379         if (bfd) {
380                 if (type_r)
381                         *((BlenFileType*)type_r)= bfd->type;
382                 
383                 setup_app_data(bfd, dir);
384         } else {
385                 error("Loading %s failed: %s", dir, BLO_bre_as_string(bre));
386         }
387         
388         if (!G.background)
389                 waitcursor(0);
390         
391         return (bfd?1:0);
392 }
393
394 int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r)
395 {
396         BlendReadError bre;
397         BlendFileData *bfd;
398         
399         if (!G.background)
400                 waitcursor(1);
401                 
402         bfd= BLO_read_from_memory(filebuf, filelength, &bre);
403         if (bfd) {
404                 if (type_r)
405                         *((BlenFileType*)type_r)= bfd->type;
406                 
407                 setup_app_data(bfd, "<memory>");
408         } else {
409                 error("Loading failed: %s", BLO_bre_as_string(bre));
410         }
411         
412         if (!G.background)
413                 waitcursor(0);
414         
415         return (bfd?1:0);
416 }
417
418 int BKE_read_file_from_memfile(MemFile *memfile)
419 {
420         BlendReadError bre;
421         BlendFileData *bfd;
422         
423         if (!G.background)
424                 waitcursor(1);
425                 
426         bfd= BLO_read_from_memfile(memfile, &bre);
427         if (bfd) {
428                 setup_app_data(bfd, "<memory>");
429         } else {
430                 error("Loading failed: %s", BLO_bre_as_string(bre));
431         }
432         
433         if (!G.background)
434                 waitcursor(0);
435         
436         return (bfd?1:0);
437 }
438