Added baking for softbodies.
[blender.git] / source / blender / blenloader / intern / writefile.c
1 /* writefile.c
2  *
3  * .blend file writing
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 /*
37 FILEFORMAT: IFF-style structure  (but not IFF compatible!)
38
39 start file:
40         BLENDER_V100    12 bytes  (versie 1.00)
41                                         V = big endian, v = little endian
42                                         _ = 4 byte pointer, - = 8 byte pointer
43
44 datablocks:             also see struct BHead
45         <bh.code>                       4 chars
46         <bh.len>                        int,  len data after BHead
47         <bh.old>                        void,  old pointer
48         <bh.SDNAnr>                     int
49         <bh.nr>                         int, in case of array: amount of structs
50         data
51         ...
52         ...
53
54 Almost all data in Blender are structures. Each struct saved
55 gets a BHead header.  With BHead the struct can be linked again
56 and compared with StructDNA .
57
58 WRITE
59
60 Preferred writing order: (not really a must, but why would you do it random?)
61 Any case: direct data is ALWAYS after the lib block
62
63 (Local file data)
64 - for each LibBlock
65         - write LibBlock
66         - write associated direct data
67 (External file data)
68 - per library
69         - write library block
70         - per LibBlock
71                 - write the ID of LibBlock
72 - write FileGlobal (some global vars)
73 - write SDNA
74 - write USER if filename is ~/.B.blend
75 */
76
77 /* for version 2.2+
78 Important to know is that 'streaming' has been added to files, for Blender Publisher
79 */
80
81
82 #ifdef HAVE_CONFIG_H
83 #include <config.h>
84 #endif
85
86 #ifndef WIN32
87 #include <unistd.h>
88 #else
89 #include "winsock2.h"
90 #include "BLI_winstuff.h"
91 #include <io.h>
92 #include <process.h> // for getpid
93 #endif
94
95 #include <math.h>
96 #include <fcntl.h>
97 #include <stdio.h>
98 #include <string.h>
99 #include <stdlib.h>
100
101 #include "nla.h" //  __NLA is defined
102
103 #include "DNA_armature_types.h"
104 #include "DNA_action_types.h"
105 #include "DNA_actuator_types.h"
106 #include "DNA_controller_types.h"
107 #include "DNA_curve_types.h"
108 #include "DNA_constraint_types.h"
109 #include "DNA_camera_types.h"
110 #include "DNA_effect_types.h"
111 #include "DNA_group_types.h"
112 #include "DNA_image_types.h"
113 #include "DNA_ika_types.h"
114 #include "DNA_ipo_types.h"
115 #include "DNA_fileglobal_types.h"
116 #include "DNA_key_types.h"
117 #include "DNA_lattice_types.h"
118 #include "DNA_listBase.h" /* for Listbase, the type of samples, ...*/
119 #include "DNA_lamp_types.h"
120 #include "DNA_meta_types.h"
121 #include "DNA_mesh_types.h"
122 #include "DNA_meshdata_types.h"
123 #include "DNA_material_types.h"
124 #include "DNA_nla_types.h"
125 #include "DNA_object_types.h"
126 #include "DNA_object_force.h"
127 #include "DNA_oops_types.h"
128 #include "DNA_packedFile_types.h"
129 #include "DNA_property_types.h"
130 #include "DNA_scene_types.h"
131 #include "DNA_sdna_types.h"
132 #include "DNA_sequence_types.h"
133 #include "DNA_sensor_types.h"
134 #include "DNA_space_types.h"
135 #include "DNA_screen_types.h"
136 #include "DNA_sound_types.h"
137 #include "DNA_texture_types.h"
138 #include "DNA_text_types.h"
139 #include "DNA_view3d_types.h"
140 #include "DNA_vfont_types.h"
141 #include "DNA_userdef_types.h"
142
143 #include "MEM_guardedalloc.h" // MEM_freeN
144 #include "BLI_blenlib.h"
145 #include "BLI_linklist.h"
146
147 #include "BKE_action.h"
148 #include "BKE_bad_level_calls.h" // build_seqar (from WHILE_SEQ) free_oops error
149 #include "BKE_curve.h"
150 #include "BKE_constraint.h"
151 #include "BKE_global.h" // for G
152 #include "BKE_library.h" // for  set_listbasepointers
153 #include "BKE_main.h" // G.main
154 #include "BKE_packedFile.h" // for packAll
155 #include "BKE_screen.h" // for waitcursor
156 #include "BKE_scene.h" // for do_seq
157 #include "BKE_sound.h" /* ... and for samples */
158 #include "BKE_utildefines.h" // for defines
159
160 #include "GEN_messaging.h"
161
162 #include "BLO_writefile.h"
163 #include "BLO_readfile.h"
164 #include "BLO_undofile.h"
165
166 #include "readfile.h"
167 #include "genfile.h"
168
169
170 /* ********* my write, buffered writing with minimum 50k chunks ************ */
171
172 typedef struct {
173         struct SDNA *sdna;
174
175         int file;
176         unsigned char *buf;
177         MemFile *compare, *current;
178         
179         int tot, count, error, memsize;
180 } WriteData;
181
182 static WriteData *writedata_new(int file)
183 {
184         extern char DNAstr[];   /* DNA.c */
185         extern int DNAlen;
186
187         WriteData *wd= MEM_callocN(sizeof(*wd), "writedata");
188
189                 /* XXX, see note about this in readfile.c, remove
190                  * once we have an xp lock - zr
191                  */
192         wd->sdna= dna_sdna_from_data(DNAstr, DNAlen, 0);
193
194         wd->file= file;
195
196         wd->buf= MEM_mallocN(100000, "wd->buf");
197
198         return wd;
199 }
200
201 static void writedata_do_write(WriteData *wd, void *mem, int memlen)
202 {
203         if (wd->error) return;
204
205         /* memory based save */
206         if(wd->current) {
207                 add_memfilechunk(NULL, wd->current, mem, memlen);
208         }
209         else {
210                 if (write(wd->file, mem, memlen) != memlen)
211                         wd->error= 1;
212                 
213         }
214 }
215
216 static void writedata_free(WriteData *wd)
217 {
218         dna_freestructDNA(wd->sdna);
219
220         MEM_freeN(wd->buf);
221         MEM_freeN(wd);
222 }
223
224 /***/
225
226 int mywfile;
227
228 /**
229  * Low level WRITE(2) wrapper that buffers data
230  * @param adr Pointer to new chunk of data
231  * @param len Length of new chunk of data
232  * @warning Talks to other functions with global parameters
233  */
234  
235 #define MYWRITE_FLUSH   NULL
236
237 static void mywrite( WriteData *wd, void *adr, int len)
238 {
239         if (wd->error) return;
240
241         if(adr==MYWRITE_FLUSH) {
242                 if(wd->count) {
243                         writedata_do_write(wd, wd->buf, wd->count);
244                         wd->count= 0;
245                 }
246                 return;
247         }
248
249         wd->tot+= len;
250         
251         if(len>50000) {
252                 if(wd->count) {
253                         writedata_do_write(wd, wd->buf, wd->count);
254                         wd->count= 0;
255                 }
256                 writedata_do_write(wd, adr, len);
257                 return;
258         }
259         if(len+wd->count>99999) {
260                 writedata_do_write(wd, wd->buf, wd->count);
261                 wd->count= 0;
262         }
263         memcpy(&wd->buf[wd->count], adr, len);
264         wd->count+= len;
265
266 }
267
268 /**
269  * BeGiN initializer for mywrite
270  * @param file File descriptor
271  * @param write_flags Write parameters
272  * @warning Talks to other functions with global parameters
273  */
274 static WriteData *bgnwrite(int file, MemFile *compare, MemFile *current, int write_flags)
275 {
276         WriteData *wd= writedata_new(file);
277
278         wd->compare= compare;
279         wd->current= current;
280         /* this inits comparing */
281         add_memfilechunk(compare, NULL, NULL, 0);
282         
283         return wd;
284 }
285
286 /**
287  * END the mywrite wrapper
288  * @return 1 if write failed
289  * @return unknown global variable otherwise
290  * @warning Talks to other functions with global parameters
291  */
292 static int endwrite(WriteData *wd)
293 {
294         int err;
295
296         if (wd->count) {
297                 writedata_do_write(wd, wd->buf, wd->count);
298                 wd->count= 0;
299         }
300         
301         err= wd->error;
302         writedata_free(wd);
303 /* blender gods may live forever but this parent pointer died in the statement above
304 if(wd->current) printf("undo size %d\n", wd->current->size);
305 */
306         return err;
307 }
308
309 /* ********** WRITE FILE ****************** */
310
311 static void writestruct(WriteData *wd, int filecode, char *structname, int nr, void *adr)
312 {
313         BHead bh;
314         short *sp;
315
316         if(adr==0 || nr==0) return;
317
318         /* init BHead */
319         bh.code= filecode;
320         bh.old= adr;
321         bh.nr= nr;
322
323         bh.SDNAnr= dna_findstruct_nr(wd->sdna, structname);
324         if(bh.SDNAnr== -1) {
325                 printf("error: can't find SDNA code %s\n", structname);
326                 return;
327         }
328         sp= wd->sdna->structs[bh.SDNAnr];
329
330         bh.len= nr*wd->sdna->typelens[sp[0]];
331
332         if(bh.len==0) return;
333
334         mywrite(wd, &bh, sizeof(BHead));
335         mywrite(wd, adr, bh.len);
336 }
337
338 static void writedata(WriteData *wd, int filecode, int len, void *adr)  /* do not use for structs */
339 {
340         BHead bh;
341
342         if(adr==0) return;
343         if(len==0) return;
344
345         len+= 3;
346         len-= ( len % 4);
347
348         /* init BHead */
349         bh.code= filecode;
350         bh.old= adr;
351         bh.nr= 1;
352         bh.SDNAnr= 0;
353         bh.len= len;
354
355         mywrite(wd, &bh, sizeof(BHead));
356         if(len) mywrite(wd, adr, len);
357 }
358
359 static void write_scriptlink(WriteData *wd, ScriptLink *slink)
360 {
361         writedata(wd, DATA, sizeof(void *)*slink->totscript, slink->scripts);
362         writedata(wd, DATA, sizeof(short)*slink->totscript, slink->flag);
363 }
364
365 static void write_renderinfo(WriteData *wd)             /* for renderdaemon */
366 {
367         Scene *sce;
368         int data[8];
369
370         sce= G.main->scene.first;
371         while(sce) {
372                 if(sce->id.lib==0  && ( sce==G.scene || (sce->r.scemode & R_BG_RENDER)) ) {
373                         data[0]= sce->r.sfra;
374                         data[1]= sce->r.efra;
375
376                         strncpy((char *)(data+2), sce->id.name+2, 23);
377
378                         writedata(wd, REND, 32, data);
379                 }
380                 sce= sce->id.next;
381         }
382 }
383
384 static void write_userdef(WriteData *wd)
385 {
386         bTheme *btheme;
387
388         writestruct(wd, USER, "UserDef", 1, &U);
389
390         btheme= U.themes.first;
391         while(btheme) {
392                 writestruct(wd, DATA, "bTheme", 1, btheme);
393                 btheme= btheme->next;
394         }
395 }
396
397 static void write_effects(WriteData *wd, ListBase *lb)
398 {
399         Effect *eff;
400
401         eff= lb->first;
402         while(eff) {
403
404                 switch(eff->type) {
405                 case EFF_BUILD:
406                         writestruct(wd, DATA, "BuildEff", 1, eff);
407                         break;
408                 case EFF_PARTICLE:
409                         writestruct(wd, DATA, "PartEff", 1, eff);
410                         break;
411                 case EFF_WAVE:
412                         writestruct(wd, DATA, "WaveEff", 1, eff);
413                         break;
414                 default:
415                         writedata(wd, DATA, MEM_allocN_len(eff), eff);
416                 }
417
418                 eff= eff->next;
419         }
420 }
421
422 static void write_properties(WriteData *wd, ListBase *lb)
423 {
424         bProperty *prop;
425
426         prop= lb->first;
427         while(prop) {
428                 writestruct(wd, DATA, "bProperty", 1, prop);
429
430                 if(prop->poin && prop->poin != &prop->data)
431                         writedata(wd, DATA, MEM_allocN_len(prop->poin), prop->poin);
432
433                 prop= prop->next;
434         }
435 }
436
437 static void write_sensors(WriteData *wd, ListBase *lb)
438 {
439         bSensor *sens;
440
441         sens= lb->first;
442         while(sens) {
443                 writestruct(wd, DATA, "bSensor", 1, sens);
444
445                 writedata(wd, DATA, sizeof(void *)*sens->totlinks, sens->links);
446
447                 switch(sens->type) {
448                 case SENS_NEAR:
449                         writestruct(wd, DATA, "bNearSensor", 1, sens->data);
450                         break;
451                 case SENS_MOUSE:
452                         writestruct(wd, DATA, "bMouseSensor", 1, sens->data);
453                         break;
454                 case SENS_TOUCH:
455                         writestruct(wd, DATA, "bTouchSensor", 1, sens->data);
456                         break;
457                 case SENS_KEYBOARD:
458                         writestruct(wd, DATA, "bKeyboardSensor", 1, sens->data);
459                         break;
460                 case SENS_PROPERTY:
461                         writestruct(wd, DATA, "bPropertySensor", 1, sens->data);
462                         break;
463                 case SENS_COLLISION:
464                         writestruct(wd, DATA, "bCollisionSensor", 1, sens->data);
465                         break;
466                 case SENS_RADAR:
467                         writestruct(wd, DATA, "bRadarSensor", 1, sens->data);
468                         break;
469                 case SENS_RANDOM:
470                         writestruct(wd, DATA, "bRandomSensor", 1, sens->data);
471                         break;
472                 case SENS_RAY:
473                         writestruct(wd, DATA, "bRaySensor", 1, sens->data);
474                         break;
475                 case SENS_MESSAGE:
476                         writestruct(wd, DATA, "bMessageSensor", 1, sens->data);
477                         break;
478                 case SENS_JOYSTICK:
479                         writestruct(wd, DATA, "bJoystickSensor", 1, sens->data);
480                         break;
481                 default:
482                         ; /* error: don't know how to write this file */
483                 }
484
485                 sens= sens->next;
486         }
487 }
488
489 static void write_controllers(WriteData *wd, ListBase *lb)
490 {
491         bController *cont;
492
493         cont= lb->first;
494         while(cont) {
495                 writestruct(wd, DATA, "bController", 1, cont);
496
497                 writedata(wd, DATA, sizeof(void *)*cont->totlinks, cont->links);
498
499                 switch(cont->type) {
500                 case CONT_EXPRESSION:
501                         writestruct(wd, DATA, "bExpressionCont", 1, cont->data);
502                         break;
503                 case CONT_PYTHON:
504                         writestruct(wd, DATA, "bPythonCont", 1, cont->data);
505                         break;
506                 default:
507                         ; /* error: don't know how to write this file */
508                 }
509
510                 cont= cont->next;
511         }
512 }
513
514 static void write_actuators(WriteData *wd, ListBase *lb)
515 {
516         bActuator *act;
517
518         act= lb->first;
519         while(act) {
520                 writestruct(wd, DATA, "bActuator", 1, act);
521
522                 switch(act->type) {
523                 case ACT_ACTION:
524                         writestruct(wd, DATA, "bActionActuator", 1, act->data);
525                         break;
526                 case ACT_SOUND:
527                         writestruct(wd, DATA, "bSoundActuator", 1, act->data);
528                         break;
529                 case ACT_CD:
530                         writestruct(wd, DATA, "bCDActuator", 1, act->data);
531                         break;
532                 case ACT_OBJECT:
533                         writestruct(wd, DATA, "bObjectActuator", 1, act->data);
534                         break;
535                 case ACT_IPO:
536                         writestruct(wd, DATA, "bIpoActuator", 1, act->data);
537                         break;
538                 case ACT_PROPERTY:
539                         writestruct(wd, DATA, "bPropertyActuator", 1, act->data);
540                         break;
541                 case ACT_CAMERA:
542                         writestruct(wd, DATA, "bCameraActuator", 1, act->data);
543                         break;
544                 case ACT_CONSTRAINT:
545                         writestruct(wd, DATA, "bConstraintActuator", 1, act->data);
546                         break;
547                 case ACT_EDIT_OBJECT:
548                         writestruct(wd, DATA, "bEditObjectActuator", 1, act->data);
549                         break;
550                 case ACT_SCENE:
551                         writestruct(wd, DATA, "bSceneActuator", 1, act->data);
552                         break;
553                 case ACT_GROUP:
554                         writestruct(wd, DATA, "bGroupActuator", 1, act->data);
555                         break;
556                 case ACT_RANDOM:
557                         writestruct(wd, DATA, "bRandomActuator", 1, act->data);
558                         break;
559                 case ACT_MESSAGE:
560                         writestruct(wd, DATA, "bMessageActuator", 1, act->data);
561                         break;
562                 case ACT_GAME:
563                         writestruct(wd, DATA, "bGameActuator", 1, act->data);
564                         break;
565                 case ACT_VISIBILITY:
566                         writestruct(wd, DATA, "bVisibilityActuator", 1, act->data);
567                         break;
568                 default:
569                         ; /* error: don't know how to write this file */
570                 }
571
572                 act= act->next;
573         }
574 }
575
576 static void write_nlastrips(WriteData *wd, ListBase *nlabase)
577 {
578         bActionStrip *strip;
579
580         for (strip=nlabase->first; strip; strip=strip->next)
581                 writestruct(wd, DATA, "bActionStrip", 1, strip);
582 }
583
584 static void write_constraints(WriteData *wd, ListBase *conlist)
585 {
586         bConstraint *con;
587
588         for (con=conlist->first; con; con=con->next) {
589                 /* Write the specific data */
590                 switch (con->type) {
591                 case CONSTRAINT_TYPE_NULL:
592                         break;
593                 case CONSTRAINT_TYPE_TRACKTO:
594                         writestruct(wd, DATA, "bTrackToConstraint", 1, con->data);
595                         break;
596                 case CONSTRAINT_TYPE_KINEMATIC:
597                         writestruct(wd, DATA, "bKinematicConstraint", 1, con->data);
598                         break;
599                 case CONSTRAINT_TYPE_ROTLIKE:
600                         writestruct(wd, DATA, "bRotateLikeConstraint", 1, con->data);
601                         break;
602                 case CONSTRAINT_TYPE_LOCLIKE:
603                         writestruct(wd, DATA, "bLocateLikeConstraint", 1, con->data);
604                         break;
605                 case CONSTRAINT_TYPE_ACTION:
606                         writestruct(wd, DATA, "bActionConstraint", 1, con->data);
607                         break;
608                 case CONSTRAINT_TYPE_LOCKTRACK:
609                         writestruct(wd, DATA, "bLockTrackConstraint", 1, con->data);
610                         break;
611                 case CONSTRAINT_TYPE_FOLLOWPATH:
612                         writestruct(wd, DATA, "bFollowPathConstraint", 1, con->data);
613                         break;
614                 case CONSTRAINT_TYPE_STRETCHTO:
615                         writestruct(wd, DATA, "bStretchToConstraint", 1, con->data);
616                         break;
617                 default:
618                         break;
619                 }
620                 /* Write the constraint */
621                 writestruct(wd, DATA, "bConstraint", 1, con);
622         }
623 }
624
625 static void write_pose(WriteData *wd, bPose *pose)
626 {
627         bPoseChannel    *chan;
628
629         /* Write each channel */
630
631         if (!pose)
632                 return;
633
634         // Write channels
635         for (chan=pose->chanbase.first; chan; chan=chan->next) {
636                 write_constraints(wd, &chan->constraints);
637                 writestruct(wd, DATA, "bPoseChannel", 1, chan);
638         }
639
640         // Write this pose
641         writestruct(wd, DATA, "bPose", 1, pose);
642 }
643
644 static void write_defgroups(WriteData *wd, ListBase *defbase)
645 {
646         bDeformGroup    *defgroup;
647
648         for (defgroup=defbase->first; defgroup; defgroup=defgroup->next)
649                 writestruct(wd, DATA, "bDeformGroup", 1, defgroup);
650 }
651
652 static void write_constraint_channels(WriteData *wd, ListBase *chanbase)
653 {
654         bConstraintChannel *chan;
655
656         for (chan = chanbase->first; chan; chan=chan->next)
657                 writestruct(wd, DATA, "bConstraintChannel", 1, chan);
658
659 }
660
661 static void write_objects(WriteData *wd, ListBase *idbase)
662 {
663         Object *ob;
664         ObHook *hook;
665         int a;
666         
667         ob= idbase->first;
668         while(ob) {
669                 if(ob->id.us>0 || wd->current) {
670                         /* write LibData */
671                         writestruct(wd, ID_OB, "Object", 1, ob);
672
673                         /* direct data */
674                         writedata(wd, DATA, sizeof(void *)*ob->totcol, ob->mat);
675                         write_effects(wd, &ob->effect);
676                         write_properties(wd, &ob->prop);
677                         write_sensors(wd, &ob->sensors);
678                         write_controllers(wd, &ob->controllers);
679                         write_actuators(wd, &ob->actuators);
680                         write_scriptlink(wd, &ob->scriptlink);
681                         write_pose(wd, ob->pose);
682                         write_defgroups(wd, &ob->defbase);
683                         write_constraints(wd, &ob->constraints);
684                         write_constraint_channels(wd, &ob->constraintChannels);
685                         write_nlastrips(wd, &ob->nlastrips);
686                         
687                         writestruct(wd, DATA, "PartDeflect", 1, ob->pd);
688                         writestruct(wd, DATA, "SoftBody", 1, ob->soft);
689                         if(ob->soft) {
690                                 SoftBody *sb= ob->soft;
691                                 if(sb->keys) {
692                                         writedata(wd, DATA, sizeof(void *)*sb->totkey, sb->keys);
693                                         for(a=0; a<sb->totkey; a++) {
694                                                 writestruct(wd, DATA, "SBVertex", sb->totpoint, sb->keys[a]);
695                                         }
696                                 }
697                         }
698                         
699                         for(hook= ob->hooks.first; hook; hook= hook->next) {
700                                 writestruct(wd, DATA, "ObHook", 1, hook);
701                                 writedata(wd, DATA, sizeof(int)*hook->totindex, hook->indexar);
702                         }
703                 }
704                 ob= ob->id.next;
705         }
706
707         /* flush helps the compression for undo-save */
708         mywrite(wd, MYWRITE_FLUSH, 0);
709 }
710
711
712 static void write_vfonts(WriteData *wd, ListBase *idbase)
713 {
714         VFont *vf;
715         PackedFile * pf;
716
717         vf= idbase->first;
718         while(vf) {
719                 if(vf->id.us>0 || wd->current) {
720                         /* write LibData */
721                         writestruct(wd, ID_VF, "VFont", 1, vf);
722
723                         /* direct data */
724
725                         if (vf->packedfile) {
726                                 pf = vf->packedfile;
727                                 writestruct(wd, DATA, "PackedFile", 1, pf);
728                                 writedata(wd, DATA, pf->size, pf->data);
729                         }
730                 }
731
732                 vf= vf->id.next;
733         }
734 }
735
736 static void write_ipos(WriteData *wd, ListBase *idbase)
737 {
738         Ipo *ipo;
739         IpoCurve *icu;
740
741         ipo= idbase->first;
742         while(ipo) {
743                 if(ipo->id.us>0 || wd->current) {
744                         /* write LibData */
745                         writestruct(wd, ID_IP, "Ipo", 1, ipo);
746
747                         /* direct data */
748                         icu= ipo->curve.first;
749                         while(icu) {
750                                 writestruct(wd, DATA, "IpoCurve", 1, icu);
751                                 icu= icu->next;
752                         }
753
754                         icu= ipo->curve.first;
755                         while(icu) {
756                                 if(icu->bezt)  writestruct(wd, DATA, "BezTriple", icu->totvert, icu->bezt);
757                                 if(icu->bp)  writestruct(wd, DATA, "BPoint", icu->totvert, icu->bp);
758                                 icu= icu->next;
759                         }
760                 }
761
762                 ipo= ipo->id.next;
763         }
764
765         /* flush helps the compression for undo-save */
766         mywrite(wd, MYWRITE_FLUSH, 0);
767 }
768
769 static void write_keys(WriteData *wd, ListBase *idbase)
770 {
771         Key *key;
772         KeyBlock *kb;
773
774         key= idbase->first;
775         while(key) {
776                 if(key->id.us>0 || wd->current) {
777                         /* write LibData */
778                         writestruct(wd, ID_KE, "Key", 1, key);
779
780                         /* direct data */
781                         kb= key->block.first;
782                         while(kb) {
783                                 writestruct(wd, DATA, "KeyBlock", 1, kb);
784                                 if(kb->data) writedata(wd, DATA, kb->totelem*key->elemsize, kb->data);
785                                 kb= kb->next;
786                         }
787                 }
788
789                 key= key->id.next;
790         }
791         /* flush helps the compression for undo-save */
792         mywrite(wd, MYWRITE_FLUSH, 0);
793 }
794
795 static void write_cameras(WriteData *wd, ListBase *idbase)
796 {
797         Camera *cam;
798
799         cam= idbase->first;
800         while(cam) {
801                 if(cam->id.us>0 || wd->current) {
802                         /* write LibData */
803                         writestruct(wd, ID_CA, "Camera", 1, cam);
804
805                         /* direct data */
806                         write_scriptlink(wd, &cam->scriptlink);
807                 }
808
809                 cam= cam->id.next;
810         }
811 }
812
813 static void write_mballs(WriteData *wd, ListBase *idbase)
814 {
815         MetaBall *mb;
816         MetaElem *ml;
817
818         mb= idbase->first;
819         while(mb) {
820                 if(mb->id.us>0 || wd->current) {
821                         /* write LibData */
822                         writestruct(wd, ID_MB, "MetaBall", 1, mb);
823
824                         /* direct data */
825                         writedata(wd, DATA, sizeof(void *)*mb->totcol, mb->mat);
826
827                         ml= mb->elems.first;
828                         while(ml) {
829                                 writestruct(wd, DATA, "MetaElem", 1, ml);
830                                 ml= ml->next;
831                         }
832                 }
833                 mb= mb->id.next;
834         }
835 }
836
837 static void write_curves(WriteData *wd, ListBase *idbase)
838 {
839         Curve *cu;
840         Nurb *nu;
841
842         cu= idbase->first;
843         while(cu) {
844                 if(cu->id.us>0 || wd->current) {
845                         /* write LibData */
846                         writestruct(wd, ID_CU, "Curve", 1, cu);
847
848                         /* direct data */
849                         writedata(wd, DATA, sizeof(void *)*cu->totcol, cu->mat);
850
851                         if(cu->vfont) {
852                                 writedata(wd, DATA, cu->len+1, cu->str);
853                         }
854                         else {
855                                 /* is also the order of reading */
856                                 nu= cu->nurb.first;
857                                 while(nu) {
858                                         writestruct(wd, DATA, "Nurb", 1, nu);
859                                         nu= nu->next;
860                                 }
861                                 nu= cu->nurb.first;
862                                 while(nu) {
863                                         if( (nu->type & 7)==CU_BEZIER)
864                                                 writestruct(wd, DATA, "BezTriple", nu->pntsu, nu->bezt);
865                                         else {
866                                                 writestruct(wd, DATA, "BPoint", nu->pntsu*nu->pntsv, nu->bp);
867                                                 if(nu->knotsu) writedata(wd, DATA, KNOTSU(nu)*sizeof(float), nu->knotsu);
868                                                 if(nu->knotsv) writedata(wd, DATA, KNOTSV(nu)*sizeof(float), nu->knotsv);
869                                         }
870                                         nu= nu->next;
871                                 }
872                         }
873                 }
874                 cu= cu->id.next;
875         }
876
877         /* flush helps the compression for undo-save */
878         mywrite(wd, MYWRITE_FLUSH, 0);
879 }
880
881 static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist)
882 {
883         int     i;
884
885         /* Write the dvert list */
886         writestruct(wd, DATA, "MDeformVert", count, dvlist);
887
888         /* Write deformation data for each dvert */
889         if (dvlist) {
890                 for (i=0; i<count; i++) {
891                         if (dvlist[i].dw)
892                                 writestruct(wd, DATA, "MDeformWeight", dvlist[i].totweight, dvlist[i].dw);
893                 }
894         }
895 }
896
897 static void write_meshs(WriteData *wd, ListBase *idbase)
898 {
899         Mesh *mesh;
900
901         mesh= idbase->first;
902         while(mesh) {
903                 if(mesh->id.us>0 || wd->current) {
904                         /* write LibData */
905                         writestruct(wd, ID_ME, "Mesh", 1, mesh);
906
907                         /* direct data */
908                         writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
909
910                         writestruct(wd, DATA, "MVert", mesh->totvert, mesh->mvert);
911                         writestruct(wd, DATA, "MEdge", mesh->totedge, mesh->medge);
912                         writestruct(wd, DATA, "MFace", mesh->totface, mesh->mface);
913                         writestruct(wd, DATA, "TFace", mesh->totface, mesh->tface);
914                         writestruct(wd, DATA, "MCol", 4*mesh->totface, mesh->mcol);
915                         writestruct(wd, DATA, "MSticky", mesh->totvert, mesh->msticky);
916
917                         write_dverts(wd, mesh->totvert, mesh->dvert);
918
919                 }
920                 mesh= mesh->id.next;
921         }
922 }
923
924 static void write_images(WriteData *wd, ListBase *idbase)
925 {
926         Image *ima;
927         PackedFile * pf;
928
929         ima= idbase->first;
930         while(ima) {
931                 if(ima->id.us>0 || wd->current) {
932                         /* write LibData */
933                         writestruct(wd, ID_IM, "Image", 1, ima);
934
935                         if (ima->packedfile) {
936                                 pf = ima->packedfile;
937                                 writestruct(wd, DATA, "PackedFile", 1, pf);
938                                 writedata(wd, DATA, pf->size, pf->data);
939                         }
940                 }
941                 ima= ima->id.next;
942         }
943         /* flush helps the compression for undo-save */
944         mywrite(wd, MYWRITE_FLUSH, 0);
945 }
946
947 static void write_textures(WriteData *wd, ListBase *idbase)
948 {
949         Tex *tex;
950
951         tex= idbase->first;
952         while(tex) {
953                 if(tex->id.us>0 || wd->current) {
954                         /* write LibData */
955                         writestruct(wd, ID_TE, "Tex", 1, tex);
956
957                         /* direct data */
958                         if(tex->plugin) writestruct(wd, DATA, "PluginTex", 1, tex->plugin);
959                         if(tex->coba) writestruct(wd, DATA, "ColorBand", 1, tex->coba);
960                         if(tex->env) writestruct(wd, DATA, "EnvMap", 1, tex->env);
961                 }
962                 tex= tex->id.next;
963         }
964
965         /* flush helps the compression for undo-save */
966         mywrite(wd, MYWRITE_FLUSH, 0);
967 }
968
969 static void write_materials(WriteData *wd, ListBase *idbase)
970 {
971         Material *ma;
972         int a;
973
974         ma= idbase->first;
975         while(ma) {
976                 if(ma->id.us>0 || wd->current) {
977                         /* write LibData */
978                         writestruct(wd, ID_MA, "Material", 1, ma);
979
980                         for(a=0; a<MAX_MTEX; a++) {
981                                 if(ma->mtex[a]) writestruct(wd, DATA, "MTex", 1, ma->mtex[a]);
982                         }
983                         
984                         if(ma->ramp_col) writestruct(wd, DATA, "ColorBand", 1, ma->ramp_col);
985                         if(ma->ramp_spec) writestruct(wd, DATA, "ColorBand", 1, ma->ramp_spec);
986                         
987                         write_scriptlink(wd, &ma->scriptlink);
988                 }
989                 ma= ma->id.next;
990         }
991 }
992
993 static void write_worlds(WriteData *wd, ListBase *idbase)
994 {
995         World *wrld;
996         int a;
997
998         wrld= idbase->first;
999         while(wrld) {
1000                 if(wrld->id.us>0 || wd->current) {
1001                         /* write LibData */
1002                         writestruct(wd, ID_WO, "World", 1, wrld);
1003
1004                         for(a=0; a<MAX_MTEX; a++) {
1005                                 if(wrld->mtex[a]) writestruct(wd, DATA, "MTex", 1, wrld->mtex[a]);
1006                         }
1007
1008                         write_scriptlink(wd, &wrld->scriptlink);
1009                 }
1010                 wrld= wrld->id.next;
1011         }
1012 }
1013
1014 static void write_lamps(WriteData *wd, ListBase *idbase)
1015 {
1016         Lamp *la;
1017         int a;
1018
1019         la= idbase->first;
1020         while(la) {
1021                 if(la->id.us>0 || wd->current) {
1022                         /* write LibData */
1023                         writestruct(wd, ID_LA, "Lamp", 1, la);
1024
1025                         /* direct data */
1026                         for(a=0; a<MAX_MTEX; a++) {
1027                                 if(la->mtex[a]) writestruct(wd, DATA, "MTex", 1, la->mtex[a]);
1028                         }
1029
1030                         write_scriptlink(wd, &la->scriptlink);
1031                 }
1032                 la= la->id.next;
1033         }
1034 }
1035
1036 static void write_lattices(WriteData *wd, ListBase *idbase)
1037 {
1038         Lattice *lt;
1039
1040         lt= idbase->first;
1041         while(lt) {
1042                 if(lt->id.us>0 || wd->current) {
1043                         /* write LibData */
1044                         writestruct(wd, ID_LT, "Lattice", 1, lt);
1045
1046                         /* direct data */
1047                         writestruct(wd, DATA, "BPoint", lt->pntsu*lt->pntsv*lt->pntsw, lt->def);
1048                 }
1049                 lt= lt->id.next;
1050         }
1051 }
1052
1053 static void write_ikas(WriteData *wd, ListBase *idbase)
1054 {
1055         Ika *ika;
1056         Limb *li;
1057
1058         ika= idbase->first;
1059         while(ika) {
1060                 if(ika->id.us>0 || wd->current) {
1061                         /* write LibData */
1062                         writestruct(wd, ID_IK, "Ika", 1, ika);
1063
1064                         /* direct data */
1065                         li= ika->limbbase.first;
1066                         while(li) {
1067                                 writestruct(wd, DATA, "Limb", 1, li);
1068                                 li= li->next;
1069                         }
1070
1071                         writestruct(wd, DATA, "Deform", ika->totdef, ika->def);
1072                 }
1073                 ika= ika->id.next;
1074         }
1075 }
1076
1077 static void write_scenes(WriteData *wd, ListBase *scebase)
1078 {
1079         Scene *sce;
1080         Base *base;
1081         Editing *ed;
1082         Sequence *seq;
1083         MetaStack *ms;
1084         Strip *strip;
1085
1086         sce= scebase->first;
1087         while(sce) {
1088                 /* write LibData */
1089                 writestruct(wd, ID_SCE, "Scene", 1, sce);
1090
1091                 /* direct data */
1092                 base= sce->base.first;
1093                 while(base) {
1094                         writestruct(wd, DATA, "Base", 1, base);
1095                         base= base->next;
1096                 }
1097
1098                 writestruct(wd, DATA, "Radio", 1, sce->radio);
1099
1100                 ed= sce->ed;
1101                 if(ed) {
1102                         writestruct(wd, DATA, "Editing", 1, ed);
1103
1104                         /* reset write flags too */
1105                         WHILE_SEQ(&ed->seqbase) {
1106                                 if(seq->strip) seq->strip->done= 0;
1107                                 writestruct(wd, DATA, "Sequence", 1, seq);
1108                         }
1109                         END_SEQ
1110
1111                         WHILE_SEQ(&ed->seqbase) {
1112                                 if(seq->strip && seq->strip->done==0) {
1113                                         /* write strip with 'done' at 0 because readfile */
1114
1115                                         if(seq->plugin) writestruct(wd, DATA, "PluginSeq", 1, seq->plugin);
1116                                         if(seq->effectdata) {
1117                                                 switch(seq->type){
1118                                                         case SEQ_WIPE:
1119                                                                 writestruct(wd, DATA, "WipeVars", 1, seq->effectdata);
1120                                                                 break;
1121                                                         case SEQ_GLOW:
1122                                                                 writestruct(wd, DATA, "GlowVars", 1, seq->effectdata);
1123                                                                 break;
1124                                                 }
1125                                         }
1126
1127                                         strip= seq->strip;
1128                                         writestruct(wd, DATA, "Strip", 1, strip);
1129
1130                                         if(seq->type==SEQ_IMAGE)
1131                                                 writestruct(wd, DATA, "StripElem", strip->len, strip->stripdata);
1132                                         else if(seq->type==SEQ_MOVIE || seq->type==SEQ_SOUND)
1133                                                 writestruct(wd, DATA, "StripElem", 1, strip->stripdata);
1134
1135                                         strip->done= 1;
1136                                 }
1137                         }
1138                         END_SEQ
1139                                 
1140                         /* new; meta stack too, even when its nasty restore code */
1141                         for(ms= ed->metastack.first; ms; ms= ms->next) {
1142                                 writestruct(wd, DATA, "MetaStack", 1, ms);
1143                         }
1144                 }
1145
1146                 write_scriptlink(wd, &sce->scriptlink);
1147
1148                 if (sce->r.avicodecdata) {
1149                         writestruct(wd, DATA, "AviCodecData", 1, sce->r.avicodecdata);
1150                         if (sce->r.avicodecdata->lpFormat) writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
1151                         if (sce->r.avicodecdata->lpParms) writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms);
1152                 }
1153
1154                 if (sce->r.qtcodecdata) {
1155                         writestruct(wd, DATA, "QuicktimeCodecData", 1, sce->r.qtcodecdata);
1156                         if (sce->r.qtcodecdata->cdParms) writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms);
1157                 }
1158
1159                 sce= sce->id.next;
1160         }
1161         /* flush helps the compression for undo-save */
1162         mywrite(wd, MYWRITE_FLUSH, 0);
1163 }
1164
1165 static void write_screens(WriteData *wd, ListBase *scrbase)
1166 {
1167         bScreen *sc;
1168         ScrArea *sa;
1169         ScrVert *sv;
1170         ScrEdge *se;
1171
1172         sc= scrbase->first;
1173         while(sc) {
1174                 /* write LibData */
1175                 writestruct(wd, ID_SCR, "Screen", 1, sc);
1176
1177                 /* direct data */
1178                 sv= sc->vertbase.first;
1179                 while(sv) {
1180                         writestruct(wd, DATA, "ScrVert", 1, sv);
1181                         sv= sv->next;
1182                 }
1183
1184                 se= sc->edgebase.first;
1185                 while(se) {
1186                         writestruct(wd, DATA, "ScrEdge", 1, se);
1187                         se= se->next;
1188                 }
1189
1190                 sa= sc->areabase.first;
1191                 while(sa) {
1192                         SpaceLink *sl;
1193                         Panel *pa;
1194
1195                         writestruct(wd, DATA, "ScrArea", 1, sa);
1196
1197                         pa= sa->panels.first;
1198                         while(pa) {
1199                                 writestruct(wd, DATA, "Panel", 1, pa);
1200                                 pa= pa->next;
1201                         }
1202
1203                         sl= sa->spacedata.first;
1204                         while(sl) {
1205                                 if(sl->spacetype==SPACE_VIEW3D) {
1206                                         View3D *v3d= (View3D*) sl;
1207                                         writestruct(wd, DATA, "View3D", 1, v3d);
1208                                         if(v3d->bgpic) writestruct(wd, DATA, "BGpic", 1, v3d->bgpic);
1209                                         if(v3d->localvd) writestruct(wd, DATA, "View3D", 1, v3d->localvd);
1210                                 }
1211                                 else if(sl->spacetype==SPACE_IPO) {
1212                                         writestruct(wd, DATA, "SpaceIpo", 1, sl);
1213                                 }
1214                                 else if(sl->spacetype==SPACE_BUTS) {
1215                                         writestruct(wd, DATA, "SpaceButs", 1, sl);
1216                                 }
1217                                 else if(sl->spacetype==SPACE_FILE) {
1218                                         writestruct(wd, DATA, "SpaceFile", 1, sl);
1219                                 }
1220                                 else if(sl->spacetype==SPACE_SEQ) {
1221                                         writestruct(wd, DATA, "SpaceSeq", 1, sl);
1222                                 }
1223                                 else if(sl->spacetype==SPACE_OOPS) {
1224                                         SpaceOops *so= (SpaceOops *)sl;
1225                                         Oops *oops;
1226
1227                                         /* cleanup */
1228                                         oops= so->oops.first;
1229                                         while(oops) {
1230                                                 Oops *oopsn= oops->next;
1231                                                 if(oops->id==0) {
1232                                                         BLI_remlink(&so->oops, oops);
1233                                                         free_oops(oops);
1234                                                 }
1235                                                 oops= oopsn;
1236                                         }
1237
1238                                         /* ater cleanup, because of listbase! */
1239                                         writestruct(wd, DATA, "SpaceOops", 1, so);
1240
1241                                         oops= so->oops.first;
1242                                         while(oops) {
1243                                                 writestruct(wd, DATA, "Oops", 1, oops);
1244                                                 oops= oops->next;
1245                                         }
1246                                         /* outliner */
1247                                         if(so->treestore) {
1248                                                 writestruct(wd, DATA, "TreeStore", 1, so->treestore);
1249                                                 if(so->treestore->data)
1250                                                         writestruct(wd, DATA, "TreeStoreElem", so->treestore->usedelem, so->treestore->data);
1251                                         }
1252                                 }
1253                                 else if(sl->spacetype==SPACE_IMAGE) {
1254                                         writestruct(wd, DATA, "SpaceImage", 1, sl);
1255                                 }
1256                                 else if(sl->spacetype==SPACE_IMASEL) {
1257                                         writestruct(wd, DATA, "SpaceImaSel", 1, sl);
1258                                 }
1259                                 else if(sl->spacetype==SPACE_TEXT) {
1260                                         writestruct(wd, DATA, "SpaceText", 1, sl);
1261                                 }
1262                                 else if(sl->spacetype==SPACE_SCRIPT) {
1263                                         writestruct(wd, DATA, "SpaceScript", 1, sl);
1264                                 }
1265                                 else if(sl->spacetype==SPACE_ACTION) {
1266                                         writestruct(wd, DATA, "SpaceAction", 1, sl);
1267                                 }
1268                                 else if(sl->spacetype==SPACE_SOUND) {
1269                                         writestruct(wd, DATA, "SpaceSound", 1, sl);
1270                                 }
1271                                 else if(sl->spacetype==SPACE_NLA){
1272                                         writestruct(wd, DATA, "SpaceNla", 1, sl);
1273                                 }
1274                                 sl= sl->next;
1275                         }
1276
1277                         sa= sa->next;
1278                 }
1279
1280                 sc= sc->id.next;
1281         }
1282 }
1283
1284 static void write_libraries(WriteData *wd, Main *main)
1285 {
1286         ListBase *lbarray[30];
1287         ID *id;
1288         int a, tot, foundone;
1289
1290         while(main) {
1291
1292                 a=tot= set_listbasepointers(main, lbarray);
1293
1294                 /* test: is lib being used */
1295                 foundone= 0;
1296                 while(tot--) {
1297                         id= lbarray[tot]->first;
1298                         while(id) {
1299                                 if(id->us>0 && (id->flag & LIB_EXTERN)) {
1300                                         foundone= 1;
1301                                         break;
1302                                 }
1303                                 id= id->next;
1304                         }
1305                         if(foundone) break;
1306                 }
1307
1308                 if(foundone) {
1309                         writestruct(wd, ID_LI, "Library", 1, main->curlib);
1310
1311                         while(a--) {
1312                                 id= lbarray[a]->first;
1313                                 while(id) {
1314                                         if(id->us>0 && (id->flag & LIB_EXTERN)) {
1315
1316                                                 writestruct(wd, ID_ID, "ID", 1, id);
1317                                         }
1318                                         id= id->next;
1319                                 }
1320                         }
1321                 }
1322
1323                 main= main->next;
1324         }
1325 }
1326
1327 static void write_bone(WriteData *wd, Bone* bone)
1328 {
1329         Bone*   cbone;
1330
1331 //      write_constraints(wd, &bone->constraints);
1332
1333         // Write this bone
1334         writestruct(wd, DATA, "Bone", 1, bone);
1335
1336         // Write Children
1337         cbone= bone->childbase.first;
1338         while(cbone) {
1339                 write_bone(wd, cbone);
1340                 cbone= cbone->next;
1341         }
1342 }
1343
1344 static void write_armatures(WriteData *wd, ListBase *idbase)
1345 {
1346         bArmature       *arm;
1347         Bone            *bone;
1348
1349         arm=idbase->first;
1350         while (arm) {
1351                 if (arm->id.us>0 || wd->current) {
1352                         writestruct(wd, ID_AR, "bArmature", 1, arm);
1353
1354                         /* Direct data */
1355                         bone= arm->bonebase.first;
1356                         while(bone) {
1357                                 write_bone(wd, bone);
1358                                 bone=bone->next;
1359                         }
1360                 }
1361                 arm=arm->id.next;
1362         }
1363
1364         /* flush helps the compression for undo-save */
1365         mywrite(wd, MYWRITE_FLUSH, 0);
1366 }
1367
1368 static void write_actions(WriteData *wd, ListBase *idbase)
1369 {
1370         bAction                 *act;
1371         bActionChannel  *chan;
1372         act=idbase->first;
1373         while (act) {
1374                 if (act->id.us>0 || wd->current) {
1375                         writestruct(wd, ID_AC, "bAction", 1, act);
1376
1377                         for (chan=act->chanbase.first; chan; chan=chan->next) {
1378                                 writestruct(wd, DATA, "bActionChannel", 1, chan);
1379                                 write_constraint_channels(wd, &chan->constraintChannels);
1380                         }
1381                 }
1382                 act=act->id.next;
1383         }
1384 }
1385
1386 static void write_texts(WriteData *wd, ListBase *idbase)
1387 {
1388         Text *text;
1389         TextLine *tmp;
1390
1391         text= idbase->first;
1392         while(text) {
1393                 if ( (text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) text->flags &= ~TXT_ISEXT;
1394
1395                 /* write LibData */
1396                 writestruct(wd, ID_TXT, "Text", 1, text);
1397                 if(text->name) writedata(wd, DATA, strlen(text->name)+1, text->name);
1398
1399                 if(!(text->flags & TXT_ISEXT)) {
1400                         /* now write the text data, in two steps for optimization in the readfunction */
1401                         tmp= text->lines.first;
1402                         while (tmp) {
1403                                 writestruct(wd, DATA, "TextLine", 1, tmp);
1404                                 tmp= tmp->next;
1405                         }
1406
1407                         tmp= text->lines.first;
1408                         while (tmp) {
1409                                 writedata(wd, DATA, tmp->len+1, tmp->line);
1410                                 tmp= tmp->next;
1411                         }
1412                 }
1413                 text= text->id.next;
1414         }
1415
1416         /* flush helps the compression for undo-save */
1417         mywrite(wd, MYWRITE_FLUSH, 0);
1418 }
1419
1420 static void write_sounds(WriteData *wd, ListBase *idbase)
1421 {
1422         bSound *sound;
1423         bSample *sample;
1424
1425         PackedFile * pf;
1426
1427         // set all samples to unsaved status
1428
1429         sample = samples->first;
1430         while (sample) {
1431                 sample->flags |= SAMPLE_NEEDS_SAVE;
1432                 sample = sample->id.next;
1433         }
1434
1435         sound= idbase->first;
1436         while(sound) {
1437                 if(sound->id.us>0 || wd->current) {
1438                         // do we need to save the packedfile as well ?
1439                         sample = sound->sample;
1440                         if (sample) {
1441                                 if (sample->flags & SAMPLE_NEEDS_SAVE) {
1442                                         sound->newpackedfile = sample->packedfile;
1443                                         sample->flags &= ~SAMPLE_NEEDS_SAVE;
1444                                 } else {
1445                                         sound->newpackedfile = NULL;
1446                                 }
1447                         }
1448
1449                         /* write LibData */
1450                         writestruct(wd, ID_SO, "bSound", 1, sound);
1451
1452                         if (sound->newpackedfile) {
1453                                 pf = sound->newpackedfile;
1454                                 writestruct(wd, DATA, "PackedFile", 1, pf);
1455                                 writedata(wd, DATA, pf->size, pf->data);
1456                         }
1457
1458                         if (sample) {
1459                                 sound->newpackedfile = sample->packedfile;
1460                         }
1461                 }
1462                 sound= sound->id.next;
1463         }
1464
1465         /* flush helps the compression for undo-save */
1466         mywrite(wd, MYWRITE_FLUSH, 0);
1467 }
1468
1469 static void write_groups(WriteData *wd, ListBase *idbase)
1470 {
1471         Group *group;
1472         GroupKey *gk;
1473         GroupObject *go;
1474         ObjectKey *ok;
1475
1476         group= idbase->first;
1477         while(group) {
1478                 if(group->id.us>0 || wd->current) {
1479                         /* write LibData */
1480                         writestruct(wd, ID_GR, "Group", 1, group);
1481
1482                         gk= group->gkey.first;
1483                         while(gk) {
1484                                 writestruct(wd, DATA, "GroupKey", 1, gk);
1485                                 gk= gk->next;
1486                         }
1487
1488                         go= group->gobject.first;
1489                         while(go) {
1490                                 writestruct(wd, DATA, "GroupObject", 1, go);
1491                                 go= go->next;
1492                         }
1493                         go= group->gobject.first;
1494                         while(go) {
1495                                 ok= go->okey.first;
1496                                 while(ok) {
1497                                         writestruct(wd, DATA, "ObjectKey", 1, ok);
1498                                         ok= ok->next;
1499                                 }
1500                                 go= go->next;
1501                         }
1502
1503                 }
1504                 group= group->id.next;
1505         }
1506 }
1507
1508 static void write_global(WriteData *wd)
1509 {
1510         FileGlobal fg;
1511
1512         fg.curscreen= G.curscreen;
1513         fg.curscene= G.scene;
1514         fg.displaymode= G.displaymode;
1515         fg.winpos= G.winpos;
1516         fg.fileflags= (G.fileflags & ~G_FILE_NO_UI);    // prevent to save this, is not good convention, and feature with concerns...
1517         fg.globalf= G.f;
1518
1519         writestruct(wd, GLOB, "FileGlobal", 1, &fg);
1520 }
1521
1522 /* if *mem there's filesave to memory */
1523 static int write_file_handle(int handle, MemFile *compare, MemFile *current, int write_user_block, int write_flags)
1524 {
1525         BHead bhead;
1526         ListBase mainlist;
1527         char buf[13];
1528         WriteData *wd;
1529 /*      int data; */ /*unused*/
1530
1531         mainlist.first= mainlist.last= G.main;
1532         G.main->next= NULL;
1533
1534         blo_split_main(&mainlist);
1535
1536         wd= bgnwrite(handle, compare, current, write_flags);
1537         
1538         sprintf(buf, "BLENDER%c%c%.3d", (sizeof(void*)==8)?'-':'_', (G.order==B_ENDIAN)?'V':'v', G.version);
1539         mywrite(wd, buf, 12);
1540
1541         write_renderinfo(wd);
1542         
1543         if(current==NULL)
1544                 write_screens  (wd, &G.main->screen);   // no UI save
1545         write_scenes   (wd, &G.main->scene);
1546         write_curves   (wd, &G.main->curve);
1547         write_mballs   (wd, &G.main->mball);
1548         write_images   (wd, &G.main->image);
1549         write_cameras  (wd, &G.main->camera);
1550         write_lamps    (wd, &G.main->lamp);
1551         write_lattices (wd, &G.main->latt);
1552         write_ikas     (wd, &G.main->ika);
1553         write_vfonts   (wd, &G.main->vfont);
1554         write_ipos     (wd, &G.main->ipo);
1555         write_keys     (wd, &G.main->key);
1556         write_worlds   (wd, &G.main->world);
1557         write_texts    (wd, &G.main->text);
1558         write_sounds   (wd, &G.main->sound);
1559         write_groups   (wd, &G.main->group);
1560         write_armatures(wd, &G.main->armature);
1561         write_actions  (wd, &G.main->action);
1562         write_objects  (wd, &G.main->object);
1563         write_materials(wd, &G.main->mat);
1564         write_textures (wd, &G.main->tex);
1565         write_meshs    (wd, &G.main->mesh);
1566         write_libraries(wd,  G.main->next);
1567
1568         write_global(wd);
1569         if (write_user_block) {
1570                 write_userdef(wd);
1571         }
1572
1573         /* dna as last, because (to be implemented) test for which structs are written */
1574         writedata(wd, DNA1, wd->sdna->datalen, wd->sdna->data);
1575
1576         /* end of file */
1577         memset(&bhead, 0, sizeof(BHead));
1578         bhead.code= ENDB;
1579         mywrite(wd, &bhead, sizeof(BHead));
1580
1581         blo_join_main(&mainlist);
1582         G.main= mainlist.first;
1583
1584         return endwrite(wd);
1585 }
1586
1587 /* return: success (1) */
1588 int BLO_write_file(char *dir, int write_flags, char **error_r)
1589 {
1590         char userfilename[FILE_MAXDIR+FILE_MAXFILE];
1591         char tempname[FILE_MAXDIR+FILE_MAXFILE];
1592         int file, fout, write_user_block;
1593
1594         sprintf(tempname, "%s@", dir);
1595
1596         file = open(tempname,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
1597         if(file == -1) {
1598                 *error_r= "Unable to open";
1599                 return 0;
1600         }
1601
1602         BLI_make_file_string(G.sce, userfilename, BLI_gethome(), ".B.blend");
1603
1604         write_user_block= BLI_streq(dir, userfilename);
1605
1606         fout= write_file_handle(file, NULL,NULL, write_user_block, write_flags);
1607         close(file);
1608
1609         if(!fout) {
1610                 if(BLI_rename(tempname, dir) < 0) {
1611                         *error_r= "Can't change old file. File saved with @";
1612                         return 0;
1613                 }
1614         } else {
1615                 remove(tempname);
1616
1617                 *error_r= "Not enough diskspace";
1618                 return 0;
1619         }
1620
1621         return 1;
1622 }
1623
1624 /* return: success (1) */
1625 int BLO_write_file_mem(MemFile *compare, MemFile *current, int write_flags, char **error_r)
1626 {
1627         int err;
1628
1629         err= write_file_handle(0, compare, current, 0, write_flags);
1630         
1631         if(err==0) return 1;
1632         return 0;
1633 }
1634
1635
1636         /* Runtime writing */
1637
1638 #ifdef WIN32
1639 #define PATHSEPERATOR           "\\"
1640 #else
1641 #define PATHSEPERATOR           "/"
1642 #endif
1643
1644 static char *get_install_dir(void) {
1645         extern char bprogname[];
1646         char *tmpname = BLI_strdup(bprogname);
1647         char *cut;
1648
1649 #ifdef __APPLE__
1650         cut = strstr(tmpname, ".app");
1651         if (cut) cut[0] = 0;
1652 #endif
1653
1654         cut = BLI_last_slash(tmpname);
1655
1656         if (cut) {
1657                 cut[0] = 0;
1658                 return tmpname;
1659         } else {
1660                 MEM_freeN(tmpname);
1661                 return NULL;
1662         }
1663 }
1664
1665 static char *get_runtime_path(char *exename) {
1666         char *installpath= get_install_dir();
1667
1668         if (!installpath) {
1669                 return NULL;
1670         } else {
1671                 char *path= MEM_mallocN(strlen(installpath)+strlen(PATHSEPERATOR)+strlen(exename)+1, "runtimepath");
1672                 strcpy(path, installpath);
1673                 strcat(path, PATHSEPERATOR);
1674                 strcat(path, exename);
1675
1676                 MEM_freeN(installpath);
1677
1678                 return path;
1679         }
1680 }
1681
1682 #ifdef __APPLE__
1683
1684 static int recursive_copy_runtime(char *outname, char *exename, char **cause_r) 
1685 {
1686         char *cause = NULL, *runtime = get_runtime_path(exename);
1687         char command[2 * (FILE_MAXDIR+FILE_MAXFILE) + 32];
1688         int progfd = -1;
1689
1690         if (!runtime) {
1691                 cause= "Unable to find runtime";
1692                 goto cleanup;
1693         }
1694         //printf("runtimepath %s\n", runtime);
1695                 
1696         progfd= open(runtime, O_BINARY|O_RDONLY, 0);
1697         if (progfd==-1) {
1698                 cause= "Unable to find runtime";
1699                 goto cleanup;
1700         }
1701
1702         sprintf(command, "/bin/cp -R \"%s\" \"%s\"", runtime, outname);
1703         //printf("command %s\n", command);
1704         if (system(command) == -1) {
1705                 cause = "Couldn't copy runtime";
1706         }
1707
1708 cleanup:
1709         if (progfd!=-1)
1710                 close(progfd);
1711         if (runtime)
1712                 MEM_freeN(runtime);
1713
1714         if (cause) {
1715                 *cause_r= cause;
1716                 return 0;
1717         } else
1718                 return 1;
1719 }
1720
1721 void BLO_write_runtime(char *file, char *exename) {
1722         char gamename[FILE_MAXDIR+FILE_MAXFILE];
1723         int outfd = -1;
1724         char *cause= NULL;
1725
1726         // remove existing file / bundle
1727         //printf("Delete file %s\n", file);
1728         BLI_delete(file, NULL, TRUE);
1729
1730         if (!recursive_copy_runtime(file, exename, &cause))
1731                 goto cleanup;
1732
1733         strcpy(gamename, file);
1734         strcat(gamename, "/Contents/Resources/game.blend");
1735         //printf("gamename %s\n", gamename);
1736         outfd= open(gamename, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0777);
1737         if (outfd != -1) {
1738
1739                 write_file_handle(outfd, NULL,NULL, 0, G.fileflags);
1740
1741                 if (write(outfd, " ", 1) != 1) {
1742                         cause= "Unable to write to output file";
1743                         goto cleanup;
1744                 }
1745         } else {
1746                 cause = "Unable to open blenderfile";
1747         }
1748
1749 cleanup:
1750         if (outfd!=-1)
1751                 close(outfd);
1752
1753         if (cause)
1754                 error("Unable to make runtime: %s", cause);
1755 }
1756
1757 #else /* !__APPLE__ */
1758
1759 static int handle_append_runtime(int handle, char *exename, char **cause_r) {
1760         char *cause= NULL, *runtime= get_runtime_path(exename);
1761         unsigned char buf[1024];
1762         int count, progfd= -1;
1763
1764         if (!runtime) {
1765                 cause= "Unable to find runtime";
1766                 goto cleanup;
1767         }
1768
1769         progfd= open(runtime, O_BINARY|O_RDONLY, 0);
1770         if (progfd==-1) {
1771                 cause= "Unable to find runtime";
1772                 goto cleanup;
1773         }
1774
1775         while ((count= read(progfd, buf, sizeof(buf)))>0) {
1776                 if (write(handle, buf, count)!=count) {
1777                         cause= "Unable to write to output file";
1778                         goto cleanup;
1779                 }
1780         }
1781
1782 cleanup:
1783         if (progfd!=-1)
1784                 close(progfd);
1785         if (runtime)
1786                 MEM_freeN(runtime);
1787
1788         if (cause) {
1789                 *cause_r= cause;
1790                 return 0;
1791         } else
1792                 return 1;
1793 }
1794
1795 static int handle_write_msb_int(int handle, int i) {
1796         unsigned char buf[4];
1797         buf[0]= (i>>24)&0xFF;
1798         buf[1]= (i>>16)&0xFF;
1799         buf[2]= (i>>8)&0xFF;
1800         buf[3]= (i>>0)&0xFF;
1801
1802         return (write(handle, buf, 4)==4);
1803 }
1804
1805 void BLO_write_runtime(char *file, char *exename) {
1806         int outfd= open(file, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0777);
1807         char *cause= NULL;
1808         int datastart;
1809
1810         if (!outfd) {
1811                 cause= "Unable to open output file";
1812                 goto cleanup;
1813         }
1814         if (!handle_append_runtime(outfd, exename, &cause))
1815                 goto cleanup;
1816
1817         datastart= lseek(outfd, 0, SEEK_CUR);
1818
1819         write_file_handle(outfd, NULL,NULL, 0, G.fileflags);
1820
1821         if (!handle_write_msb_int(outfd, datastart) || (write(outfd, "BRUNTIME", 8)!=8)) {
1822                 cause= "Unable to write to output file";
1823                 goto cleanup;
1824         }
1825
1826 cleanup:
1827         if (outfd!=-1)
1828                 close(outfd);
1829
1830         if (cause)
1831                 error("Unable to make runtime: %s", cause);
1832 }
1833
1834 #endif /* !__APPLE__ */