svn merge ^/trunk/blender -r55372:55392
[blender.git] / source / blender / blenloader / intern / writefile.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/blenloader/intern/writefile.c
28  *  \ingroup blenloader
29  */
30
31
32 /*
33  * FILEFORMAT: IFF-style structure  (but not IFF compatible!)
34  *
35  * start file:
36  *     BLENDER_V100    12 bytes  (versie 1.00)
37  *                     V = big endian, v = little endian
38  *                     _ = 4 byte pointer, - = 8 byte pointer
39  *
40  * datablocks:     also see struct BHead
41  *     <bh.code>           4 chars
42  *     <bh.len>            int,  len data after BHead
43  *     <bh.old>            void,  old pointer
44  *     <bh.SDNAnr>         int
45  *     <bh.nr>             int, in case of array: amount of structs
46  *     data
47  *     ...
48  *     ...
49  *
50  * Almost all data in Blender are structures. Each struct saved
51  * gets a BHead header.  With BHead the struct can be linked again
52  * and compared with StructDNA .
53  *
54  * WRITE
55  *
56  * Preferred writing order: (not really a must, but why would you do it random?)
57  * Any case: direct data is ALWAYS after the lib block
58  *
59  * (Local file data)
60  * - for each LibBlock
61  *     - write LibBlock
62  *     - write associated direct data
63  * (External file data)
64  * - per library
65  *     - write library block
66  *     - per LibBlock
67  *         - write the ID of LibBlock
68  * - write TEST (128x128, blend file preview, optional)
69  * - write FileGlobal (some global vars)
70  * - write SDNA
71  * - write USER if filename is ~/X.XX/config/startup.blend
72  */
73
74
75 #include <math.h>
76 #include <fcntl.h>
77 #include <limits.h>
78 #include <stdio.h>
79 #include <string.h>
80 #include <stdlib.h>
81
82 #include "zlib.h"
83
84 #ifndef WIN32
85 #  include <unistd.h>
86 #else
87 #  include "winsock2.h"
88 #  include <io.h>
89 #  include <process.h> // for getpid
90 #  include "BLI_winstuff.h"
91 #endif
92
93 #include "BLI_utildefines.h"
94
95 /* allow writefile to use deprecated functionality (for forward compatibility code) */
96 #define DNA_DEPRECATED_ALLOW
97
98 #include "DNA_anim_types.h"
99 #include "DNA_armature_types.h"
100 #include "DNA_actuator_types.h"
101 #include "DNA_brush_types.h"
102 #include "DNA_camera_types.h"
103 #include "DNA_cloth_types.h"
104 #include "DNA_constraint_types.h"
105 #include "DNA_controller_types.h"
106 #include "DNA_dynamicpaint_types.h"
107 #include "DNA_genfile.h"
108 #include "DNA_group_types.h"
109 #include "DNA_gpencil_types.h"
110 #include "DNA_fileglobal_types.h"
111 #include "DNA_key_types.h"
112 #include "DNA_lattice_types.h"
113 #include "DNA_lamp_types.h"
114 #ifdef WITH_FREESTYLE
115 #  include "DNA_linestyle_types.h"
116 #endif
117 #include "DNA_meta_types.h"
118 #include "DNA_mesh_types.h"
119 #include "DNA_meshdata_types.h"
120 #include "DNA_material_types.h"
121 #include "DNA_node_types.h"
122 #include "DNA_object_types.h"
123 #include "DNA_object_force.h"
124 #include "DNA_packedFile_types.h"
125 #include "DNA_particle_types.h"
126 #include "DNA_property_types.h"
127 #include "DNA_rigidbody_types.h"
128 #include "DNA_scene_types.h"
129 #include "DNA_sdna_types.h"
130 #include "DNA_sequence_types.h"
131 #include "DNA_sensor_types.h"
132 #include "DNA_smoke_types.h"
133 #include "DNA_space_types.h"
134 #include "DNA_screen_types.h"
135 #include "DNA_speaker_types.h"
136 #include "DNA_sound_types.h"
137 #include "DNA_text_types.h"
138 #include "DNA_view3d_types.h"
139 #include "DNA_vfont_types.h"
140 #include "DNA_world_types.h"
141 #include "DNA_windowmanager_types.h"
142 #include "DNA_movieclip_types.h"
143 #include "DNA_mask_types.h"
144
145 #include "MEM_guardedalloc.h" // MEM_freeN
146 #include "BLI_bitmap.h"
147 #include "BLI_blenlib.h"
148 #include "BLI_linklist.h"
149 #include "BKE_bpath.h"
150 #include "BLI_math.h"
151 #include "BLI_utildefines.h"
152
153 #include "BKE_action.h"
154 #include "BKE_blender.h"
155 #include "BKE_curve.h"
156 #include "BKE_constraint.h"
157 #include "BKE_global.h" // for G
158 #include "BKE_idprop.h"
159 #include "BKE_library.h" // for  set_listbasepointers
160 #include "BKE_main.h"
161 #include "BKE_node.h"
162 #include "BKE_report.h"
163 #include "BKE_sequencer.h"
164 #include "BKE_subsurf.h"
165 #include "BKE_modifier.h"
166 #include "BKE_fcurve.h"
167 #include "BKE_pointcache.h"
168 #include "BKE_mesh.h"
169
170 #ifdef USE_NODE_COMPAT_CUSTOMNODES
171 #include "NOD_common.h"
172 #include "NOD_socket.h" /* for sock->default_value data */
173 #endif
174
175 #include "RNA_access.h"
176
177 #include "BLO_writefile.h"
178 #include "BLO_readfile.h"
179 #include "BLO_undofile.h"
180 #include "BLO_blend_defs.h"
181
182 #include "readfile.h"
183
184 #include <errno.h>
185
186 /* ********* my write, buffered writing with minimum size chunks ************ */
187
188 #define MYWRITE_BUFFER_SIZE     100000
189 #define MYWRITE_MAX_CHUNK       32768
190
191 typedef struct {
192         struct SDNA *sdna;
193
194         int file;
195         unsigned char *buf;
196         MemFile *compare, *current;
197         
198         int tot, count, error, memsize;
199
200 #ifdef USE_BMESH_SAVE_AS_COMPAT
201         char use_mesh_compat; /* option to save with older mesh format */
202 #endif
203 } WriteData;
204
205 static WriteData *writedata_new(int file)
206 {
207         WriteData *wd= MEM_callocN(sizeof(*wd), "writedata");
208
209                 /* XXX, see note about this in readfile.c, remove
210                  * once we have an xp lock - zr
211                  */
212
213         if (wd == NULL) return NULL;
214
215         wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, false);
216
217         wd->file= file;
218
219         wd->buf= MEM_mallocN(MYWRITE_BUFFER_SIZE, "wd->buf");
220
221         return wd;
222 }
223
224 static void writedata_do_write(WriteData *wd, const void *mem, int memlen)
225 {
226         if ((wd == NULL) || wd->error || (mem == NULL) || memlen < 1) return;
227         if (wd->error) return;
228
229         /* memory based save */
230         if (wd->current) {
231                 add_memfilechunk(NULL, wd->current, mem, memlen);
232         }
233         else {
234                 if (write(wd->file, mem, memlen) != memlen)
235                         wd->error= 1;
236                 
237         }
238 }
239
240 static void writedata_free(WriteData *wd)
241 {
242         DNA_sdna_free(wd->sdna);
243
244         MEM_freeN(wd->buf);
245         MEM_freeN(wd);
246 }
247
248 /***/
249
250 /**
251  * Low level WRITE(2) wrapper that buffers data
252  * \param adr Pointer to new chunk of data
253  * \param len Length of new chunk of data
254  * \warning Talks to other functions with global parameters
255  */
256  
257 #define MYWRITE_FLUSH           NULL
258
259 static void mywrite(WriteData *wd, const void *adr, int len)
260 {
261         if (wd->error) return;
262
263         /* flush helps compression for undo-save */
264         if (adr==MYWRITE_FLUSH) {
265                 if (wd->count) {
266                         writedata_do_write(wd, wd->buf, wd->count);
267                         wd->count= 0;
268                 }
269                 return;
270         }
271
272         wd->tot+= len;
273         
274         /* if we have a single big chunk, write existing data in
275          * buffer and write out big chunk in smaller pieces */
276         if (len>MYWRITE_MAX_CHUNK) {
277                 if (wd->count) {
278                         writedata_do_write(wd, wd->buf, wd->count);
279                         wd->count= 0;
280                 }
281
282                 do {
283                         int writelen= MIN2(len, MYWRITE_MAX_CHUNK);
284                         writedata_do_write(wd, adr, writelen);
285                         adr = (const char *)adr + writelen;
286                         len -= writelen;
287                 } while (len > 0);
288
289                 return;
290         }
291
292         /* if data would overflow buffer, write out the buffer */
293         if (len+wd->count>MYWRITE_BUFFER_SIZE-1) {
294                 writedata_do_write(wd, wd->buf, wd->count);
295                 wd->count= 0;
296         }
297
298         /* append data at end of buffer */
299         memcpy(&wd->buf[wd->count], adr, len);
300         wd->count+= len;
301 }
302
303 /**
304  * BeGiN initializer for mywrite
305  * \param file File descriptor
306  * \param compare Previous memory file (can be NULL).
307  * \param current The current memory file (can be NULL).
308  * \warning Talks to other functions with global parameters
309  */
310 static WriteData *bgnwrite(int file, MemFile *compare, MemFile *current)
311 {
312         WriteData *wd= writedata_new(file);
313
314         if (wd == NULL) return NULL;
315
316         wd->compare= compare;
317         wd->current= current;
318         /* this inits comparing */
319         add_memfilechunk(compare, NULL, NULL, 0);
320         
321         return wd;
322 }
323
324 /**
325  * END the mywrite wrapper
326  * \return 1 if write failed
327  * \return unknown global variable otherwise
328  * \warning Talks to other functions with global parameters
329  */
330 static int endwrite(WriteData *wd)
331 {
332         int err;
333
334         if (wd->count) {
335                 writedata_do_write(wd, wd->buf, wd->count);
336                 wd->count= 0;
337         }
338         
339         err= wd->error;
340         writedata_free(wd);
341
342         return err;
343 }
344
345 /* ********** WRITE FILE ****************** */
346
347 static void writestruct(WriteData *wd, int filecode, const char *structname, int nr, void *adr)
348 {
349         BHead bh;
350         short *sp;
351
352         if (adr==NULL || nr==0) return;
353
354         /* init BHead */
355         bh.code= filecode;
356         bh.old= adr;
357         bh.nr= nr;
358
359         bh.SDNAnr= DNA_struct_find_nr(wd->sdna, structname);
360         if (bh.SDNAnr== -1) {
361                 printf("error: can't find SDNA code <%s>\n", structname);
362                 return;
363         }
364         sp= wd->sdna->structs[bh.SDNAnr];
365
366         bh.len= nr*wd->sdna->typelens[sp[0]];
367
368         if (bh.len==0) return;
369
370         mywrite(wd, &bh, sizeof(BHead));
371         mywrite(wd, adr, bh.len);
372 }
373
374 static void writedata(WriteData *wd, int filecode, int len, const void *adr)  /* do not use for structs */
375 {
376         BHead bh;
377
378         if (adr==NULL) return;
379         if (len==0) return;
380
381         len += 3;
382         len -= (len % 4);
383
384         /* init BHead */
385         bh.code   = filecode;
386         bh.old    = (void *)adr;  /* this is safe to cast from const */
387         bh.nr     = 1;
388         bh.SDNAnr = 0;
389         bh.len    = len;
390
391         mywrite(wd, &bh, sizeof(BHead));
392         if (len) mywrite(wd, adr, len);
393 }
394
395 /* use this to force writing of lists in same order as reading (using link_list) */
396 static void writelist(WriteData *wd, int filecode, const char *structname, ListBase *lb)
397 {
398         Link *link = lb->first;
399         
400         while (link) {
401                 writestruct(wd, filecode, structname, 1, link);
402                 link = link->next;
403         }
404 }
405
406 /* *************** writing some direct data structs used in more code parts **************** */
407 /*These functions are used by blender's .blend system for file saving/loading.*/
408 void IDP_WriteProperty_OnlyData(IDProperty *prop, void *wd);
409 void IDP_WriteProperty(IDProperty *prop, void *wd);
410
411 static void IDP_WriteArray(IDProperty *prop, void *wd)
412 {
413         /*REMEMBER to set totalen to len in the linking code!!*/
414         if (prop->data.pointer) {
415                 writedata(wd, DATA, MEM_allocN_len(prop->data.pointer), prop->data.pointer);
416
417                 if (prop->subtype == IDP_GROUP) {
418                         IDProperty **array= prop->data.pointer;
419                         int a;
420
421                         for (a=0; a<prop->len; a++)
422                                 IDP_WriteProperty(array[a], wd);
423                 }
424         }
425 }
426
427 static void IDP_WriteIDPArray(IDProperty *prop, void *wd)
428 {
429         /*REMEMBER to set totalen to len in the linking code!!*/
430         if (prop->data.pointer) {
431                 IDProperty *array = prop->data.pointer;
432                 int a;
433
434                 writestruct(wd, DATA, "IDProperty", prop->len, array);
435
436                 for (a=0; a<prop->len; a++)
437                         IDP_WriteProperty_OnlyData(&array[a], wd);
438         }
439 }
440
441 static void IDP_WriteString(IDProperty *prop, void *wd)
442 {
443         /*REMEMBER to set totalen to len in the linking code!!*/
444         writedata(wd, DATA, prop->len+1, prop->data.pointer);
445 }
446
447 static void IDP_WriteGroup(IDProperty *prop, void *wd)
448 {
449         IDProperty *loop;
450
451         for (loop=prop->data.group.first; loop; loop=loop->next) {
452                 IDP_WriteProperty(loop, wd);
453         }
454 }
455
456 /* Functions to read/write ID Properties */
457 void IDP_WriteProperty_OnlyData(IDProperty *prop, void *wd)
458 {
459         switch (prop->type) {
460                 case IDP_GROUP:
461                         IDP_WriteGroup(prop, wd);
462                         break;
463                 case IDP_STRING:
464                         IDP_WriteString(prop, wd);
465                         break;
466                 case IDP_ARRAY:
467                         IDP_WriteArray(prop, wd);
468                         break;
469                 case IDP_IDPARRAY:
470                         IDP_WriteIDPArray(prop, wd);
471                         break;
472         }
473 }
474
475 void IDP_WriteProperty(IDProperty *prop, void *wd)
476 {
477         writestruct(wd, DATA, "IDProperty", 1, prop);
478         IDP_WriteProperty_OnlyData(prop, wd);
479 }
480
481 static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
482 {
483         FModifier *fcm;
484         
485         /* Write all modifiers first (for faster reloading) */
486         writelist(wd, DATA, "FModifier", fmodifiers);
487         
488         /* Modifiers */
489         for (fcm= fmodifiers->first; fcm; fcm= fcm->next) {
490                 FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
491                 
492                 /* Write the specific data */
493                 if (fmi && fcm->data) {
494                         /* firstly, just write the plain fmi->data struct */
495                         writestruct(wd, DATA, fmi->structName, 1, fcm->data);
496                         
497                         /* do any modifier specific stuff */
498                         switch (fcm->type) {
499                                 case FMODIFIER_TYPE_GENERATOR:
500                                 {
501                                         FMod_Generator *data= (FMod_Generator *)fcm->data;
502                                         
503                                         /* write coefficients array */
504                                         if (data->coefficients)
505                                                 writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients);
506                                 }
507                                         break;
508                                 case FMODIFIER_TYPE_ENVELOPE:
509                                 {
510                                         FMod_Envelope *data= (FMod_Envelope *)fcm->data;
511                                         
512                                         /* write envelope data */
513                                         if (data->data)
514                                                 writestruct(wd, DATA, "FCM_EnvelopeData", data->totvert, data->data);
515                                 }
516                                         break;
517                                 case FMODIFIER_TYPE_PYTHON:
518                                 {
519                                         FMod_Python *data = (FMod_Python *)fcm->data;
520                                         
521                                         /* Write ID Properties -- and copy this comment EXACTLY for easy finding
522                                          * of library blocks that implement this.*/
523                                         IDP_WriteProperty(data->prop, wd);
524                                 }
525                                         break;
526                         }
527                 }
528         }
529 }
530
531 static void write_fcurves(WriteData *wd, ListBase *fcurves)
532 {
533         FCurve *fcu;
534         
535         writelist(wd, DATA, "FCurve", fcurves);
536         for (fcu=fcurves->first; fcu; fcu=fcu->next) {
537                 /* curve data */
538                 if (fcu->bezt)
539                         writestruct(wd, DATA, "BezTriple", fcu->totvert, fcu->bezt);
540                 if (fcu->fpt)
541                         writestruct(wd, DATA, "FPoint", fcu->totvert, fcu->fpt);
542                         
543                 if (fcu->rna_path)
544                         writedata(wd, DATA, strlen(fcu->rna_path)+1, fcu->rna_path);
545                 
546                 /* driver data */
547                 if (fcu->driver) {
548                         ChannelDriver *driver= fcu->driver;
549                         DriverVar *dvar;
550                         
551                         writestruct(wd, DATA, "ChannelDriver", 1, driver);
552                         
553                         /* variables */
554                         writelist(wd, DATA, "DriverVar", &driver->variables);
555                         for (dvar= driver->variables.first; dvar; dvar= dvar->next) {                           
556                                 DRIVER_TARGETS_USED_LOOPER(dvar)
557                                 {
558                                         if (dtar->rna_path)
559                                                 writedata(wd, DATA, strlen(dtar->rna_path)+1, dtar->rna_path);
560                                 }
561                                 DRIVER_TARGETS_LOOPER_END
562                         }
563                 }
564                 
565                 /* write F-Modifiers */
566                 write_fmodifiers(wd, &fcu->modifiers);
567         }
568 }
569
570 static void write_actions(WriteData *wd, ListBase *idbase)
571 {
572         bAction *act;
573         bActionGroup *grp;
574         TimeMarker *marker;
575         
576         for (act=idbase->first; act; act= act->id.next) {
577                 if (act->id.us>0 || wd->current) {
578                         writestruct(wd, ID_AC, "bAction", 1, act);
579                         if (act->id.properties) IDP_WriteProperty(act->id.properties, wd);
580                         
581                         write_fcurves(wd, &act->curves);
582                         
583                         for (grp=act->groups.first; grp; grp=grp->next) {
584                                 writestruct(wd, DATA, "bActionGroup", 1, grp);
585                         }
586                         
587                         for (marker=act->markers.first; marker; marker=marker->next) {
588                                 writestruct(wd, DATA, "TimeMarker", 1, marker);
589                         }
590                 }
591         }
592         
593         /* flush helps the compression for undo-save */
594         mywrite(wd, MYWRITE_FLUSH, 0);
595 }
596
597 static void write_keyingsets(WriteData *wd, ListBase *list)
598 {
599         KeyingSet *ks;
600         KS_Path *ksp;
601         
602         for (ks= list->first; ks; ks= ks->next) {
603                 /* KeyingSet */
604                 writestruct(wd, DATA, "KeyingSet", 1, ks);
605                 
606                 /* Paths */
607                 for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
608                         /* Path */
609                         writestruct(wd, DATA, "KS_Path", 1, ksp);
610                         
611                         if (ksp->rna_path)
612                                 writedata(wd, DATA, strlen(ksp->rna_path)+1, ksp->rna_path);
613                 }
614         }
615 }
616
617 static void write_nlastrips(WriteData *wd, ListBase *strips)
618 {
619         NlaStrip *strip;
620         
621         writelist(wd, DATA, "NlaStrip", strips);
622         for (strip= strips->first; strip; strip= strip->next) {
623                 /* write the strip's F-Curves and modifiers */
624                 write_fcurves(wd, &strip->fcurves);
625                 write_fmodifiers(wd, &strip->modifiers);
626                 
627                 /* write the strip's children */
628                 write_nlastrips(wd, &strip->strips);
629         }
630 }
631
632 static void write_nladata(WriteData *wd, ListBase *nlabase)
633 {
634         NlaTrack *nlt;
635         
636         /* write all the tracks */
637         for (nlt= nlabase->first; nlt; nlt= nlt->next) {
638                 /* write the track first */
639                 writestruct(wd, DATA, "NlaTrack", 1, nlt);
640                 
641                 /* write the track's strips */
642                 write_nlastrips(wd, &nlt->strips);
643         }
644 }
645
646 static void write_animdata(WriteData *wd, AnimData *adt)
647 {
648         AnimOverride *aor;
649         
650         /* firstly, just write the AnimData block */
651         writestruct(wd, DATA, "AnimData", 1, adt);
652         
653         /* write drivers */
654         write_fcurves(wd, &adt->drivers);
655         
656         /* write overrides */
657         // FIXME: are these needed?
658         for (aor= adt->overrides.first; aor; aor= aor->next) {
659                 /* overrides consist of base data + rna_path */
660                 writestruct(wd, DATA, "AnimOverride", 1, aor);
661                 writedata(wd, DATA, strlen(aor->rna_path)+1, aor->rna_path);
662         }
663         
664         // TODO write the remaps (if they are needed)
665         
666         /* write NLA data */
667         write_nladata(wd, &adt->nla_tracks);
668 }
669
670 static void write_curvemapping_curves(WriteData *wd, CurveMapping *cumap)
671 {
672         int a;
673
674         for (a = 0; a < CM_TOT; a++)
675                 writestruct(wd, DATA, "CurveMapPoint", cumap->cm[a].totpoint, cumap->cm[a].curve);
676 }
677
678 static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
679 {
680         writestruct(wd, DATA, "CurveMapping", 1, cumap);
681
682         write_curvemapping_curves(wd, cumap);
683 }
684
685 static void write_node_socket(WriteData *wd, bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock)
686 {
687 #ifdef USE_NODE_COMPAT_CUSTOMNODES
688         /* forward compatibility code, so older blenders still open */
689         sock->stack_type = 1;
690         
691         if (node->type == NODE_GROUP) {
692                 bNodeTree *ngroup = (bNodeTree *)node->id;
693                 if (ngroup) {
694                         /* for node groups: look up the deprecated groupsock pointer */
695                         sock->groupsock = ntreeFindSocketInterface(ngroup, sock->in_out, sock->identifier);
696                         BLI_assert(sock->groupsock != NULL);
697                         
698                         /* node group sockets now use the generic identifier string to verify group nodes,
699                          * old blender uses the own_index.
700                          */
701                         sock->own_index = sock->groupsock->own_index;
702                 }
703         }
704 #endif
705
706         /* actual socket writing */
707         writestruct(wd, DATA, "bNodeSocket", 1, sock);
708
709         if (sock->prop)
710                 IDP_WriteProperty(sock->prop, wd);
711         
712         if (sock->default_value)
713                 writedata(wd, DATA, MEM_allocN_len(sock->default_value), sock->default_value);
714 }
715 static void write_node_socket_interface(WriteData *wd, bNodeTree *UNUSED(ntree), bNodeSocket *sock)
716 {
717 #ifdef USE_NODE_COMPAT_CUSTOMNODES
718         /* forward compatibility code, so older blenders still open */
719         sock->stack_type = 1;
720         
721         /* Reconstruct the deprecated default_value structs in socket interface DNA. */
722         if (sock->default_value == NULL && sock->typeinfo) {
723                 node_socket_init_default_value(sock);
724         }
725 #endif
726
727         /* actual socket writing */
728         writestruct(wd, DATA, "bNodeSocket", 1, sock);
729
730         if (sock->prop)
731                 IDP_WriteProperty(sock->prop, wd);
732 }
733 /* this is only direct data, tree itself should have been written */
734 static void write_nodetree(WriteData *wd, bNodeTree *ntree)
735 {
736         bNode *node;
737         bNodeSocket *sock;
738         bNodeLink *link;
739         
740         /* for link_list() speed, we write per list */
741         
742         if (ntree->adt) write_animdata(wd, ntree->adt);
743         
744         for (node = ntree->nodes.first; node; node = node->next) {
745                 writestruct(wd, DATA, "bNode", 1, node);
746
747                 if (node->prop)
748                         IDP_WriteProperty(node->prop, wd);
749
750                 for (sock= node->inputs.first; sock; sock= sock->next)
751                         write_node_socket(wd, ntree, node, sock);
752                 for (sock= node->outputs.first; sock; sock= sock->next)
753                         write_node_socket(wd, ntree, node, sock);
754                 
755                 for (link = node->internal_links.first; link; link = link->next)
756                         writestruct(wd, DATA, "bNodeLink", 1, link);
757                 if (node->storage) {
758                         /* could be handlerized at some point, now only 1 exception still */
759                         if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
760                                 write_curvemapping(wd, node->storage);
761                         else if (ntree->type==NTREE_SHADER && node->type==SH_NODE_SCRIPT) {
762                                 NodeShaderScript *nss = (NodeShaderScript *)node->storage;
763                                 if (nss->bytecode)
764                                         writedata(wd, DATA, strlen(nss->bytecode)+1, nss->bytecode);
765                                 writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
766                         }
767                         else if (ntree->type==NTREE_COMPOSIT && ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
768                                 write_curvemapping(wd, node->storage);
769                         else if (ntree->type==NTREE_TEXTURE && (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME) )
770                                 write_curvemapping(wd, node->storage);
771                         else if (ntree->type==NTREE_COMPOSIT && node->type==CMP_NODE_MOVIEDISTORTION) {
772                                 /* pass */
773                         }
774                         else
775                                 writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
776                 }
777                 
778                 if (node->type==CMP_NODE_OUTPUT_FILE) {
779                         /* inputs have own storage data */
780                         for (sock = node->inputs.first; sock; sock = sock->next)
781                                 writestruct(wd, DATA, "NodeImageMultiFileSocket", 1, sock->storage);
782                 }
783                 if (node->type==CMP_NODE_IMAGE) {
784                         /* write extra socket info */
785                         for (sock = node->outputs.first; sock; sock = sock->next)
786                                 writestruct(wd, DATA, "NodeImageLayer", 1, sock->storage);
787                 }
788         }
789         
790         for (link= ntree->links.first; link; link= link->next)
791                 writestruct(wd, DATA, "bNodeLink", 1, link);
792         
793         for (sock = ntree->inputs.first; sock; sock = sock->next)
794                 write_node_socket_interface(wd, ntree, sock);
795         for (sock = ntree->outputs.first; sock; sock = sock->next)
796                 write_node_socket_interface(wd, ntree, sock);
797 }
798
799 static void current_screen_compat(Main *mainvar, bScreen **screen)
800 {
801         wmWindowManager *wm;
802         wmWindow *window;
803
804         /* find a global current screen in the first open window, to have
805          * a reasonable default for reading in older versions */
806         wm= mainvar->wm.first;
807         window= (wm)? wm->windows.first: NULL;
808         *screen= (window)? window->screen: NULL;
809 }
810
811 typedef struct RenderInfo {
812         int sfra;
813         int efra;
814         char scene_name[MAX_ID_NAME - 2];
815 } RenderInfo;
816
817 /* was for historic render-deamon feature,
818  * now write because it can be easily extracted without
819  * reading the whole blend file */
820 static void write_renderinfo(WriteData *wd, Main *mainvar)
821 {
822         bScreen *curscreen;
823         Scene *sce, *curscene = NULL;
824         RenderInfo data;
825
826         /* XXX in future, handle multiple windows with multiple screens? */
827         current_screen_compat(mainvar, &curscreen);
828         if (curscreen) curscene = curscreen->scene;
829         
830         for (sce= mainvar->scene.first; sce; sce= sce->id.next) {
831                 if (sce->id.lib == NULL && (sce == curscene || (sce->r.scemode & R_BG_RENDER))) {
832                         data.sfra = sce->r.sfra;
833                         data.efra = sce->r.efra;
834                         memset(data.scene_name, 0, sizeof(data.scene_name));
835
836                         BLI_strncpy(data.scene_name, sce->id.name + 2, sizeof(data.scene_name));
837
838                         writedata(wd, REND, sizeof(data), &data);
839                 }
840         }
841 }
842
843 static void write_keymapitem(WriteData *wd, wmKeyMapItem *kmi)
844 {
845         writestruct(wd, DATA, "wmKeyMapItem", 1, kmi);
846         if (kmi->properties)
847                 IDP_WriteProperty(kmi->properties, wd);
848 }
849
850 static void write_userdef(WriteData *wd)
851 {
852         bTheme *btheme;
853         wmKeyMap *keymap;
854         wmKeyMapItem *kmi;
855         wmKeyMapDiffItem *kmdi;
856         bAddon *bext;
857         uiStyle *style;
858         
859         writestruct(wd, USER, "UserDef", 1, &U);
860
861         for (btheme= U.themes.first; btheme; btheme=btheme->next)
862                 writestruct(wd, DATA, "bTheme", 1, btheme);
863
864         for (keymap= U.user_keymaps.first; keymap; keymap=keymap->next) {
865                 writestruct(wd, DATA, "wmKeyMap", 1, keymap);
866
867                 for (kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) {
868                         writestruct(wd, DATA, "wmKeyMapDiffItem", 1, kmdi);
869                         if (kmdi->remove_item)
870                                 write_keymapitem(wd, kmdi->remove_item);
871                         if (kmdi->add_item)
872                                 write_keymapitem(wd, kmdi->add_item);
873                 }
874
875                 for (kmi=keymap->items.first; kmi; kmi=kmi->next)
876                         write_keymapitem(wd, kmi);
877         }
878
879         for (bext= U.addons.first; bext; bext=bext->next) {
880                 writestruct(wd, DATA, "bAddon", 1, bext);
881                 if (bext->prop) {
882                         IDP_WriteProperty(bext->prop, wd);
883                 }
884         }
885         
886         for (style= U.uistyles.first; style; style= style->next) {
887                 writestruct(wd, DATA, "uiStyle", 1, style);
888         }
889 }
890
891 static void write_boid_state(WriteData *wd, BoidState *state)
892 {
893         BoidRule *rule = state->rules.first;
894         //BoidCondition *cond = state->conditions.first;
895
896         writestruct(wd, DATA, "BoidState", 1, state);
897
898         for (; rule; rule=rule->next) {
899                 switch (rule->type) {
900                         case eBoidRuleType_Goal:
901                         case eBoidRuleType_Avoid:
902                                 writestruct(wd, DATA, "BoidRuleGoalAvoid", 1, rule);
903                                 break;
904                         case eBoidRuleType_AvoidCollision:
905                                 writestruct(wd, DATA, "BoidRuleAvoidCollision", 1, rule);
906                                 break;
907                         case eBoidRuleType_FollowLeader:
908                                 writestruct(wd, DATA, "BoidRuleFollowLeader", 1, rule);
909                                 break;
910                         case eBoidRuleType_AverageSpeed:
911                                 writestruct(wd, DATA, "BoidRuleAverageSpeed", 1, rule);
912                                 break;
913                         case eBoidRuleType_Fight:
914                                 writestruct(wd, DATA, "BoidRuleFight", 1, rule);
915                                 break;
916                         default:
917                                 writestruct(wd, DATA, "BoidRule", 1, rule);
918                                 break;
919                 }
920         }
921         //for (; cond; cond=cond->next)
922         //      writestruct(wd, DATA, "BoidCondition", 1, cond);
923 }
924
925 /* update this also to readfile.c */
926 static const char *ptcache_data_struct[] = {
927         "", // BPHYS_DATA_INDEX
928         "", // BPHYS_DATA_LOCATION
929         "", // BPHYS_DATA_VELOCITY
930         "", // BPHYS_DATA_ROTATION
931         "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */
932         "", // BPHYS_DATA_SIZE:
933         "", // BPHYS_DATA_TIMES:
934         "BoidData" // case BPHYS_DATA_BOIDS:
935 };
936 static const char *ptcache_extra_struct[] = {
937         "",
938         "ParticleSpring"
939 };
940 static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
941 {
942         PointCache *cache = ptcaches->first;
943         int i;
944
945         for (; cache; cache=cache->next) {
946                 writestruct(wd, DATA, "PointCache", 1, cache);
947
948                 if ((cache->flag & PTCACHE_DISK_CACHE)==0) {
949                         PTCacheMem *pm = cache->mem_cache.first;
950
951                         for (; pm; pm=pm->next) {
952                                 PTCacheExtra *extra = pm->extradata.first;
953
954                                 writestruct(wd, DATA, "PTCacheMem", 1, pm);
955                                 
956                                 for (i=0; i<BPHYS_TOT_DATA; i++) {
957                                         if (pm->data[i] && pm->data_types & (1<<i)) {
958                                                 if (ptcache_data_struct[i][0]=='\0')
959                                                         writedata(wd, DATA, MEM_allocN_len(pm->data[i]), pm->data[i]);
960                                                 else
961                                                         writestruct(wd, DATA, ptcache_data_struct[i], pm->totpoint, pm->data[i]);
962                                         }
963                                 }
964
965                                 for (; extra; extra=extra->next) {
966                                         if (ptcache_extra_struct[extra->type][0]=='\0')
967                                                 continue;
968                                         writestruct(wd, DATA, "PTCacheExtra", 1, extra);
969                                         writestruct(wd, DATA, ptcache_extra_struct[extra->type], extra->totdata, extra->data);
970                                 }
971                         }
972                 }
973         }
974 }
975 static void write_particlesettings(WriteData *wd, ListBase *idbase)
976 {
977         ParticleSettings *part;
978         ParticleDupliWeight *dw;
979         GroupObject *go;
980         int a;
981
982         part= idbase->first;
983         while (part) {
984                 if (part->id.us>0 || wd->current) {
985                         /* write LibData */
986                         writestruct(wd, ID_PA, "ParticleSettings", 1, part);
987                         if (part->id.properties) IDP_WriteProperty(part->id.properties, wd);
988                         if (part->adt) write_animdata(wd, part->adt);
989                         writestruct(wd, DATA, "PartDeflect", 1, part->pd);
990                         writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
991                         writestruct(wd, DATA, "EffectorWeights", 1, part->effector_weights);
992
993                         dw = part->dupliweights.first;
994                         for (; dw; dw=dw->next) {
995                                 /* update indices */
996                                 dw->index = 0;
997                                 if (part->dup_group) { /* can be NULL if lining fails or set to None */
998                                         go = part->dup_group->gobject.first;
999                                         while (go && go->ob != dw->ob) {
1000                                                 go=go->next;
1001                                                 dw->index++;
1002                                         }
1003                                 }
1004                                 writestruct(wd, DATA, "ParticleDupliWeight", 1, dw);
1005                         }
1006
1007                         if (part->boids && part->phystype == PART_PHYS_BOIDS) {
1008                                 BoidState *state = part->boids->states.first;
1009
1010                                 writestruct(wd, DATA, "BoidSettings", 1, part->boids);
1011
1012                                 for (; state; state=state->next)
1013                                         write_boid_state(wd, state);
1014                         }
1015                         if (part->fluid && part->phystype == PART_PHYS_FLUID) {
1016                                 writestruct(wd, DATA, "SPHFluidSettings", 1, part->fluid); 
1017                         }
1018
1019                         for (a=0; a<MAX_MTEX; a++) {
1020                                 if (part->mtex[a]) writestruct(wd, DATA, "MTex", 1, part->mtex[a]);
1021                         }
1022                 }
1023                 part= part->id.next;
1024         }
1025 }
1026 static void write_particlesystems(WriteData *wd, ListBase *particles)
1027 {
1028         ParticleSystem *psys= particles->first;
1029         ParticleTarget *pt;
1030         int a;
1031
1032         for (; psys; psys=psys->next) {
1033                 writestruct(wd, DATA, "ParticleSystem", 1, psys);
1034
1035                 if (psys->particles) {
1036                         writestruct(wd, DATA, "ParticleData", psys->totpart, psys->particles);
1037
1038                         if (psys->particles->hair) {
1039                                 ParticleData *pa = psys->particles;
1040
1041                                 for (a=0; a<psys->totpart; a++, pa++)
1042                                         writestruct(wd, DATA, "HairKey", pa->totkey, pa->hair);
1043                         }
1044
1045                         if (psys->particles->boid && psys->part->phystype == PART_PHYS_BOIDS)
1046                                 writestruct(wd, DATA, "BoidParticle", psys->totpart, psys->particles->boid);
1047
1048                         if (psys->part->fluid && psys->part->phystype == PART_PHYS_FLUID && (psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS))
1049                                 writestruct(wd, DATA, "ParticleSpring", psys->tot_fluidsprings, psys->fluid_springs);
1050                 }
1051                 pt = psys->targets.first;
1052                 for (; pt; pt=pt->next)
1053                         writestruct(wd, DATA, "ParticleTarget", 1, pt);
1054
1055                 if (psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild, psys->child);
1056
1057                 if (psys->clmd) {
1058                         writestruct(wd, DATA, "ClothModifierData", 1, psys->clmd);
1059                         writestruct(wd, DATA, "ClothSimSettings", 1, psys->clmd->sim_parms);
1060                         writestruct(wd, DATA, "ClothCollSettings", 1, psys->clmd->coll_parms);
1061                 }
1062
1063                 write_pointcaches(wd, &psys->ptcaches);
1064         }
1065 }
1066
1067 static void write_properties(WriteData *wd, ListBase *lb)
1068 {
1069         bProperty *prop;
1070
1071         prop= lb->first;
1072         while (prop) {
1073                 writestruct(wd, DATA, "bProperty", 1, prop);
1074
1075                 if (prop->poin && prop->poin != &prop->data)
1076                         writedata(wd, DATA, MEM_allocN_len(prop->poin), prop->poin);
1077
1078                 prop= prop->next;
1079         }
1080 }
1081
1082 static void write_sensors(WriteData *wd, ListBase *lb)
1083 {
1084         bSensor *sens;
1085
1086         sens= lb->first;
1087         while (sens) {
1088                 writestruct(wd, DATA, "bSensor", 1, sens);
1089
1090                 writedata(wd, DATA, sizeof(void *)*sens->totlinks, sens->links);
1091
1092                 switch (sens->type) {
1093                 case SENS_NEAR:
1094                         writestruct(wd, DATA, "bNearSensor", 1, sens->data);
1095                         break;
1096                 case SENS_MOUSE:
1097                         writestruct(wd, DATA, "bMouseSensor", 1, sens->data);
1098                         break;
1099                 case SENS_TOUCH:
1100                         writestruct(wd, DATA, "bTouchSensor", 1, sens->data);
1101                         break;
1102                 case SENS_KEYBOARD:
1103                         writestruct(wd, DATA, "bKeyboardSensor", 1, sens->data);
1104                         break;
1105                 case SENS_PROPERTY:
1106                         writestruct(wd, DATA, "bPropertySensor", 1, sens->data);
1107                         break;
1108                 case SENS_ARMATURE:
1109                         writestruct(wd, DATA, "bArmatureSensor", 1, sens->data);
1110                         break;
1111                 case SENS_ACTUATOR:
1112                         writestruct(wd, DATA, "bActuatorSensor", 1, sens->data);
1113                         break;
1114                 case SENS_DELAY:
1115                         writestruct(wd, DATA, "bDelaySensor", 1, sens->data);
1116                         break;
1117                 case SENS_COLLISION:
1118                         writestruct(wd, DATA, "bCollisionSensor", 1, sens->data);
1119                         break;
1120                 case SENS_RADAR:
1121                         writestruct(wd, DATA, "bRadarSensor", 1, sens->data);
1122                         break;
1123                 case SENS_RANDOM:
1124                         writestruct(wd, DATA, "bRandomSensor", 1, sens->data);
1125                         break;
1126                 case SENS_RAY:
1127                         writestruct(wd, DATA, "bRaySensor", 1, sens->data);
1128                         break;
1129                 case SENS_MESSAGE:
1130                         writestruct(wd, DATA, "bMessageSensor", 1, sens->data);
1131                         break;
1132                 case SENS_JOYSTICK:
1133                         writestruct(wd, DATA, "bJoystickSensor", 1, sens->data);
1134                         break;
1135                 default:
1136                         ; /* error: don't know how to write this file */
1137                 }
1138
1139                 sens= sens->next;
1140         }
1141 }
1142
1143 static void write_controllers(WriteData *wd, ListBase *lb)
1144 {
1145         bController *cont;
1146
1147         cont= lb->first;
1148         while (cont) {
1149                 writestruct(wd, DATA, "bController", 1, cont);
1150
1151                 writedata(wd, DATA, sizeof(void *)*cont->totlinks, cont->links);
1152
1153                 switch (cont->type) {
1154                 case CONT_EXPRESSION:
1155                         writestruct(wd, DATA, "bExpressionCont", 1, cont->data);
1156                         break;
1157                 case CONT_PYTHON:
1158                         writestruct(wd, DATA, "bPythonCont", 1, cont->data);
1159                         break;
1160                 default:
1161                         ; /* error: don't know how to write this file */
1162                 }
1163
1164                 cont= cont->next;
1165         }
1166 }
1167
1168 static void write_actuators(WriteData *wd, ListBase *lb)
1169 {
1170         bActuator *act;
1171
1172         act= lb->first;
1173         while (act) {
1174                 writestruct(wd, DATA, "bActuator", 1, act);
1175
1176                 switch (act->type) {
1177                 case ACT_ACTION:
1178                 case ACT_SHAPEACTION:
1179                         writestruct(wd, DATA, "bActionActuator", 1, act->data);
1180                         break;
1181                 case ACT_SOUND:
1182                         writestruct(wd, DATA, "bSoundActuator", 1, act->data);
1183                         break;
1184                 case ACT_OBJECT:
1185                         writestruct(wd, DATA, "bObjectActuator", 1, act->data);
1186                         break;
1187                 case ACT_IPO:
1188                         writestruct(wd, DATA, "bIpoActuator", 1, act->data);
1189                         break;
1190                 case ACT_PROPERTY:
1191                         writestruct(wd, DATA, "bPropertyActuator", 1, act->data);
1192                         break;
1193                 case ACT_CAMERA:
1194                         writestruct(wd, DATA, "bCameraActuator", 1, act->data);
1195                         break;
1196                 case ACT_CONSTRAINT:
1197                         writestruct(wd, DATA, "bConstraintActuator", 1, act->data);
1198                         break;
1199                 case ACT_EDIT_OBJECT:
1200                         writestruct(wd, DATA, "bEditObjectActuator", 1, act->data);
1201                         break;
1202                 case ACT_SCENE:
1203                         writestruct(wd, DATA, "bSceneActuator", 1, act->data);
1204                         break;
1205                 case ACT_GROUP:
1206                         writestruct(wd, DATA, "bGroupActuator", 1, act->data);
1207                         break;
1208                 case ACT_RANDOM:
1209                         writestruct(wd, DATA, "bRandomActuator", 1, act->data);
1210                         break;
1211                 case ACT_MESSAGE:
1212                         writestruct(wd, DATA, "bMessageActuator", 1, act->data);
1213                         break;
1214                 case ACT_GAME:
1215                         writestruct(wd, DATA, "bGameActuator", 1, act->data);
1216                         break;
1217                 case ACT_VISIBILITY:
1218                         writestruct(wd, DATA, "bVisibilityActuator", 1, act->data);
1219                         break;
1220                 case ACT_2DFILTER:
1221                         writestruct(wd, DATA, "bTwoDFilterActuator", 1, act->data);
1222                         break;
1223                 case ACT_PARENT:
1224                         writestruct(wd, DATA, "bParentActuator", 1, act->data);
1225                         break;
1226                 case ACT_STATE:
1227                         writestruct(wd, DATA, "bStateActuator", 1, act->data);
1228                         break;
1229                 case ACT_ARMATURE:
1230                         writestruct(wd, DATA, "bArmatureActuator", 1, act->data);
1231                         break;
1232                 case ACT_STEERING:
1233                         writestruct(wd, DATA, "bSteeringActuator", 1, act->data);
1234                         break;
1235                 default:
1236                         ; /* error: don't know how to write this file */
1237                 }
1238
1239                 act= act->next;
1240         }
1241 }
1242
1243 static void write_motionpath(WriteData *wd, bMotionPath *mpath)
1244 {
1245         /* sanity checks */
1246         if (mpath == NULL)
1247                 return;
1248         
1249         /* firstly, just write the motionpath struct */
1250         writestruct(wd, DATA, "bMotionPath", 1, mpath);
1251         
1252         /* now write the array of data */
1253         writestruct(wd, DATA, "bMotionPathVert", mpath->length, mpath->points);
1254 }
1255
1256 static void write_constraints(WriteData *wd, ListBase *conlist)
1257 {
1258         bConstraint *con;
1259
1260         for (con=conlist->first; con; con=con->next) {
1261                 bConstraintTypeInfo *cti= BKE_constraint_get_typeinfo(con);
1262                 
1263                 /* Write the specific data */
1264                 if (cti && con->data) {
1265                         /* firstly, just write the plain con->data struct */
1266                         writestruct(wd, DATA, cti->structName, 1, con->data);
1267                         
1268                         /* do any constraint specific stuff */
1269                         switch (con->type) {
1270                                 case CONSTRAINT_TYPE_PYTHON:
1271                                 {
1272                                         bPythonConstraint *data = (bPythonConstraint *)con->data;
1273                                         bConstraintTarget *ct;
1274                                         
1275                                         /* write targets */
1276                                         for (ct= data->targets.first; ct; ct= ct->next)
1277                                                 writestruct(wd, DATA, "bConstraintTarget", 1, ct);
1278                                         
1279                                         /* Write ID Properties -- and copy this comment EXACTLY for easy finding
1280                                          * of library blocks that implement this.*/
1281                                         IDP_WriteProperty(data->prop, wd);
1282                                 }
1283                                         break;
1284                                 case CONSTRAINT_TYPE_SPLINEIK: 
1285                                 {
1286                                         bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
1287                                         
1288                                         /* write points array */
1289                                         writedata(wd, DATA, sizeof(float)*(data->numpoints), data->points);
1290                                 }
1291                                         break;
1292                         }
1293                 }
1294                 
1295                 /* Write the constraint */
1296                 writestruct(wd, DATA, "bConstraint", 1, con);
1297         }
1298 }
1299
1300 static void write_pose(WriteData *wd, bPose *pose)
1301 {
1302         bPoseChannel *chan;
1303         bActionGroup *grp;
1304
1305         /* Write each channel */
1306         if (!pose)
1307                 return;
1308
1309         /* Write channels */
1310         for (chan=pose->chanbase.first; chan; chan=chan->next) {
1311                 /* Write ID Properties -- and copy this comment EXACTLY for easy finding
1312                  * of library blocks that implement this.*/
1313                 if (chan->prop)
1314                         IDP_WriteProperty(chan->prop, wd);
1315                 
1316                 write_constraints(wd, &chan->constraints);
1317                 
1318                 write_motionpath(wd, chan->mpath);
1319                 
1320                 /* prevent crashes with autosave, when a bone duplicated in editmode has not yet been assigned to its posechannel */
1321                 if (chan->bone) 
1322                         chan->selectflag= chan->bone->flag & BONE_SELECTED; /* gets restored on read, for library armatures */
1323                 
1324                 writestruct(wd, DATA, "bPoseChannel", 1, chan);
1325         }
1326         
1327         /* Write groups */
1328         for (grp=pose->agroups.first; grp; grp=grp->next) 
1329                 writestruct(wd, DATA, "bActionGroup", 1, grp);
1330
1331         /* write IK param */
1332         if (pose->ikparam) {
1333                 char *structname = (char *)BKE_pose_ikparam_get_name(pose);
1334                 if (structname)
1335                         writestruct(wd, DATA, structname, 1, pose->ikparam);
1336         }
1337
1338         /* Write this pose */
1339         writestruct(wd, DATA, "bPose", 1, pose);
1340
1341 }
1342
1343 static void write_defgroups(WriteData *wd, ListBase *defbase)
1344 {
1345         bDeformGroup    *defgroup;
1346
1347         for (defgroup=defbase->first; defgroup; defgroup=defgroup->next)
1348                 writestruct(wd, DATA, "bDeformGroup", 1, defgroup);
1349 }
1350
1351 static void write_modifiers(WriteData *wd, ListBase *modbase)
1352 {
1353         ModifierData *md;
1354
1355         if (modbase == NULL) return;
1356         for (md=modbase->first; md; md= md->next) {
1357                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1358                 if (mti == NULL) return;
1359                 
1360                 writestruct(wd, DATA, mti->structName, 1, md);
1361                         
1362                 if (md->type==eModifierType_Hook) {
1363                         HookModifierData *hmd = (HookModifierData*) md;
1364                         
1365                         writedata(wd, DATA, sizeof(int)*hmd->totindex, hmd->indexar);
1366                 }
1367                 else if (md->type==eModifierType_Cloth) {
1368                         ClothModifierData *clmd = (ClothModifierData*) md;
1369                         
1370                         writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms);
1371                         writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
1372                         writestruct(wd, DATA, "EffectorWeights", 1, clmd->sim_parms->effector_weights);
1373                         write_pointcaches(wd, &clmd->ptcaches);
1374                 }
1375                 else if (md->type==eModifierType_Smoke) {
1376                         SmokeModifierData *smd = (SmokeModifierData*) md;
1377                         
1378                         if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
1379                                 if (smd->domain) {
1380                                         write_pointcaches(wd, &(smd->domain->ptcaches[0]));
1381
1382                                         /* create fake pointcache so that old blender versions can read it */
1383                                         smd->domain->point_cache[1] = BKE_ptcache_add(&smd->domain->ptcaches[1]);
1384                                         smd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE|PTCACHE_FAKE_SMOKE;
1385                                         smd->domain->point_cache[1]->step = 1;
1386
1387                                         write_pointcaches(wd, &(smd->domain->ptcaches[1]));
1388                                 }
1389                                 
1390                                 writestruct(wd, DATA, "SmokeDomainSettings", 1, smd->domain);
1391
1392                                 if (smd->domain) {
1393                                         /* cleanup the fake pointcache */
1394                                         BKE_ptcache_free_list(&smd->domain->ptcaches[1]);
1395                                         smd->domain->point_cache[1] = NULL;
1396                                         
1397                                         writestruct(wd, DATA, "EffectorWeights", 1, smd->domain->effector_weights);
1398                                 }
1399                         }
1400                         else if (smd->type & MOD_SMOKE_TYPE_FLOW)
1401                                 writestruct(wd, DATA, "SmokeFlowSettings", 1, smd->flow);
1402                         else if (smd->type & MOD_SMOKE_TYPE_COLL)
1403                                 writestruct(wd, DATA, "SmokeCollSettings", 1, smd->coll);
1404                 }
1405                 else if (md->type==eModifierType_Fluidsim) {
1406                         FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
1407                         
1408                         writestruct(wd, DATA, "FluidsimSettings", 1, fluidmd->fss);
1409                 }
1410                 else if (md->type==eModifierType_DynamicPaint) {
1411                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData*) md;
1412                         
1413                         if (pmd->canvas) {
1414                                 DynamicPaintSurface *surface;
1415                                 writestruct(wd, DATA, "DynamicPaintCanvasSettings", 1, pmd->canvas);
1416                                 
1417                                 /* write surfaces */
1418                                 for (surface=pmd->canvas->surfaces.first; surface; surface=surface->next)
1419                                         writestruct(wd, DATA, "DynamicPaintSurface", 1, surface);
1420                                 /* write caches and effector weights */
1421                                 for (surface=pmd->canvas->surfaces.first; surface; surface=surface->next) {
1422                                         write_pointcaches(wd, &(surface->ptcaches));
1423
1424                                         writestruct(wd, DATA, "EffectorWeights", 1, surface->effector_weights);
1425                                 }
1426                         }
1427                         if (pmd->brush) {
1428                                 writestruct(wd, DATA, "DynamicPaintBrushSettings", 1, pmd->brush);
1429                                 writestruct(wd, DATA, "ColorBand", 1, pmd->brush->paint_ramp);
1430                                 writestruct(wd, DATA, "ColorBand", 1, pmd->brush->vel_ramp);
1431                         }
1432                 }
1433                 else if (md->type==eModifierType_Collision) {
1434                         
1435 #if 0
1436                         CollisionModifierData *collmd = (CollisionModifierData*) md;
1437                         // TODO: CollisionModifier should use pointcache 
1438                         // + have proper reset events before enabling this
1439                         writestruct(wd, DATA, "MVert", collmd->numverts, collmd->x);
1440                         writestruct(wd, DATA, "MVert", collmd->numverts, collmd->xnew);
1441                         writestruct(wd, DATA, "MFace", collmd->numfaces, collmd->mfaces);
1442 #endif
1443                 }
1444                 else if (md->type==eModifierType_MeshDeform) {
1445                         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
1446                         int size = mmd->dyngridsize;
1447
1448                         writestruct(wd, DATA, "MDefInfluence", mmd->totinfluence, mmd->bindinfluences);
1449                         writedata(wd, DATA, sizeof(int) * (mmd->totvert + 1), mmd->bindoffsets);
1450                         writedata(wd, DATA, sizeof(float) * 3 * mmd->totcagevert,
1451                                 mmd->bindcagecos);
1452                         writestruct(wd, DATA, "MDefCell", size*size*size, mmd->dyngrid);
1453                         writestruct(wd, DATA, "MDefInfluence", mmd->totinfluence, mmd->dyninfluences);
1454                         writedata(wd, DATA, sizeof(int)*mmd->totvert, mmd->dynverts);
1455                 }
1456                 else if (md->type==eModifierType_Warp) {
1457                         WarpModifierData *tmd = (WarpModifierData*) md;
1458                         if (tmd->curfalloff) {
1459                                 write_curvemapping(wd, tmd->curfalloff);
1460                         }
1461                 }
1462                 else if (md->type==eModifierType_WeightVGEdit) {
1463                         WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
1464
1465                         if (wmd->cmap_curve)
1466                                 write_curvemapping(wd, wmd->cmap_curve);
1467                 }
1468         }
1469 }
1470
1471 static void write_objects(WriteData *wd, ListBase *idbase)
1472 {
1473         Object *ob;
1474         
1475         ob= idbase->first;
1476         while (ob) {
1477                 if (ob->id.us>0 || wd->current) {
1478                         /* write LibData */
1479                         writestruct(wd, ID_OB, "Object", 1, ob);
1480                         
1481                         /* Write ID Properties -- and copy this comment EXACTLY for easy finding
1482                          * of library blocks that implement this.*/
1483                         if (ob->id.properties) IDP_WriteProperty(ob->id.properties, wd);
1484                         
1485                         if (ob->adt) write_animdata(wd, ob->adt);
1486                         
1487                         /* direct data */
1488                         writedata(wd, DATA, sizeof(void *)*ob->totcol, ob->mat);
1489                         writedata(wd, DATA, sizeof(char)*ob->totcol, ob->matbits);
1490                         /* write_effects(wd, &ob->effect); */ /* not used anymore */
1491                         write_properties(wd, &ob->prop);
1492                         write_sensors(wd, &ob->sensors);
1493                         write_controllers(wd, &ob->controllers);
1494                         write_actuators(wd, &ob->actuators);
1495
1496                         if (ob->type == OB_ARMATURE) {
1497                                 bArmature *arm = ob->data;
1498                                 if (arm && ob->pose && arm->act_bone) {
1499                                         BLI_strncpy(ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone));
1500                                 }
1501                         }
1502
1503                         write_pose(wd, ob->pose);
1504                         write_defgroups(wd, &ob->defbase);
1505                         write_constraints(wd, &ob->constraints);
1506                         write_motionpath(wd, ob->mpath);
1507                         
1508                         writestruct(wd, DATA, "PartDeflect", 1, ob->pd);
1509                         writestruct(wd, DATA, "SoftBody", 1, ob->soft);
1510                         if (ob->soft) {
1511                                 write_pointcaches(wd, &ob->soft->ptcaches);
1512                                 writestruct(wd, DATA, "EffectorWeights", 1, ob->soft->effector_weights);
1513                         }
1514                         writestruct(wd, DATA, "BulletSoftBody", 1, ob->bsoft);
1515                         
1516                         if (ob->rigidbody_object) {
1517                                 // TODO: if any extra data is added to handle duplis, will need separate function then
1518                                 writestruct(wd, DATA, "RigidBodyOb", 1, ob->rigidbody_object);
1519                         }
1520                         if (ob->rigidbody_constraint) {
1521                                 writestruct(wd, DATA, "RigidBodyCon", 1, ob->rigidbody_constraint);
1522                         }
1523
1524                         write_particlesystems(wd, &ob->particlesystem);
1525                         write_modifiers(wd, &ob->modifiers);
1526                 }
1527                 ob= ob->id.next;
1528         }
1529
1530         /* flush helps the compression for undo-save */
1531         mywrite(wd, MYWRITE_FLUSH, 0);
1532 }
1533
1534
1535 static void write_vfonts(WriteData *wd, ListBase *idbase)
1536 {
1537         VFont *vf;
1538         PackedFile * pf;
1539
1540         vf= idbase->first;
1541         while (vf) {
1542                 if (vf->id.us>0 || wd->current) {
1543                         /* write LibData */
1544                         writestruct(wd, ID_VF, "VFont", 1, vf);
1545                         if (vf->id.properties) IDP_WriteProperty(vf->id.properties, wd);
1546
1547                         /* direct data */
1548
1549                         if (vf->packedfile) {
1550                                 pf = vf->packedfile;
1551                                 writestruct(wd, DATA, "PackedFile", 1, pf);
1552                                 writedata(wd, DATA, pf->size, pf->data);
1553                         }
1554                 }
1555
1556                 vf= vf->id.next;
1557         }
1558 }
1559
1560
1561 static void write_keys(WriteData *wd, ListBase *idbase)
1562 {
1563         Key *key;
1564         KeyBlock *kb;
1565
1566         key= idbase->first;
1567         while (key) {
1568                 if (key->id.us>0 || wd->current) {
1569                         /* write LibData */
1570                         writestruct(wd, ID_KE, "Key", 1, key);
1571                         if (key->id.properties) IDP_WriteProperty(key->id.properties, wd);
1572                         
1573                         if (key->adt) write_animdata(wd, key->adt);
1574                         
1575                         /* direct data */
1576                         kb= key->block.first;
1577                         while (kb) {
1578                                 writestruct(wd, DATA, "KeyBlock", 1, kb);
1579                                 if (kb->data) writedata(wd, DATA, kb->totelem*key->elemsize, kb->data);
1580                                 kb= kb->next;
1581                         }
1582                 }
1583
1584                 key= key->id.next;
1585         }
1586         /* flush helps the compression for undo-save */
1587         mywrite(wd, MYWRITE_FLUSH, 0);
1588 }
1589
1590 static void write_cameras(WriteData *wd, ListBase *idbase)
1591 {
1592         Camera *cam;
1593
1594         cam= idbase->first;
1595         while (cam) {
1596                 if (cam->id.us>0 || wd->current) {
1597                         /* write LibData */
1598                         writestruct(wd, ID_CA, "Camera", 1, cam);
1599                         if (cam->id.properties) IDP_WriteProperty(cam->id.properties, wd);
1600                         
1601                         if (cam->adt) write_animdata(wd, cam->adt);
1602                 }
1603
1604                 cam= cam->id.next;
1605         }
1606 }
1607
1608 static void write_mballs(WriteData *wd, ListBase *idbase)
1609 {
1610         MetaBall *mb;
1611         MetaElem *ml;
1612
1613         mb= idbase->first;
1614         while (mb) {
1615                 if (mb->id.us>0 || wd->current) {
1616                         /* write LibData */
1617                         writestruct(wd, ID_MB, "MetaBall", 1, mb);
1618                         if (mb->id.properties) IDP_WriteProperty(mb->id.properties, wd);
1619
1620                         /* direct data */
1621                         writedata(wd, DATA, sizeof(void *)*mb->totcol, mb->mat);
1622                         if (mb->adt) write_animdata(wd, mb->adt);
1623
1624                         ml= mb->elems.first;
1625                         while (ml) {
1626                                 writestruct(wd, DATA, "MetaElem", 1, ml);
1627                                 ml= ml->next;
1628                         }
1629                 }
1630                 mb= mb->id.next;
1631         }
1632 }
1633
1634 static int amount_of_chars(char *str)
1635 {
1636         // Since the data is saved as UTF-8 to the cu->str
1637         // The cu->len is not same as the strlen(cu->str)
1638         return strlen(str);
1639 }
1640
1641 static void write_curves(WriteData *wd, ListBase *idbase)
1642 {
1643         Curve *cu;
1644         Nurb *nu;
1645
1646         cu= idbase->first;
1647         while (cu) {
1648                 if (cu->id.us>0 || wd->current) {
1649                         /* write LibData */
1650                         writestruct(wd, ID_CU, "Curve", 1, cu);
1651                         
1652                         /* direct data */
1653                         writedata(wd, DATA, sizeof(void *)*cu->totcol, cu->mat);
1654                         if (cu->id.properties) IDP_WriteProperty(cu->id.properties, wd);
1655                         if (cu->adt) write_animdata(wd, cu->adt);
1656                         
1657                         if (cu->vfont) {
1658                                 writedata(wd, DATA, amount_of_chars(cu->str)+1, cu->str);
1659                                 writestruct(wd, DATA, "CharInfo", cu->len+1, cu->strinfo);
1660                                 writestruct(wd, DATA, "TextBox", cu->totbox, cu->tb);
1661                         }
1662                         else {
1663                                 /* is also the order of reading */
1664                                 nu= cu->nurb.first;
1665                                 while (nu) {
1666                                         writestruct(wd, DATA, "Nurb", 1, nu);
1667                                         nu= nu->next;
1668                                 }
1669                                 nu= cu->nurb.first;
1670                                 while (nu) {
1671                                         if (nu->type == CU_BEZIER)
1672                                                 writestruct(wd, DATA, "BezTriple", nu->pntsu, nu->bezt);
1673                                         else {
1674                                                 writestruct(wd, DATA, "BPoint", nu->pntsu*nu->pntsv, nu->bp);
1675                                                 if (nu->knotsu) writedata(wd, DATA, KNOTSU(nu)*sizeof(float), nu->knotsu);
1676                                                 if (nu->knotsv) writedata(wd, DATA, KNOTSV(nu)*sizeof(float), nu->knotsv);
1677                                         }
1678                                         nu= nu->next;
1679                                 }
1680                         }
1681                 }
1682                 cu= cu->id.next;
1683         }
1684
1685         /* flush helps the compression for undo-save */
1686         mywrite(wd, MYWRITE_FLUSH, 0);
1687 }
1688
1689 static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist)
1690 {
1691         if (dvlist) {
1692                 int i;
1693                 
1694                 /* Write the dvert list */
1695                 writestruct(wd, DATA, "MDeformVert", count, dvlist);
1696                 
1697                 /* Write deformation data for each dvert */
1698                 for (i=0; i<count; i++) {
1699                         if (dvlist[i].dw)
1700                                 writestruct(wd, DATA, "MDeformWeight", dvlist[i].totweight, dvlist[i].dw);
1701                 }
1702         }
1703 }
1704
1705 static void write_mdisps(WriteData *wd, int count, MDisps *mdlist, int external)
1706 {
1707         if (mdlist) {
1708                 int i;
1709                 
1710                 writestruct(wd, DATA, "MDisps", count, mdlist);
1711                 for (i = 0; i < count; ++i) {
1712                         MDisps *md = &mdlist[i];
1713                         if (md->disps) {
1714                                 if (!external)
1715                                         writedata(wd, DATA, sizeof(float) * 3 * md->totdisp, md->disps);
1716                         }
1717                         
1718                         if (md->hidden)
1719                                 writedata(wd, DATA, BLI_BITMAP_SIZE(md->totdisp), md->hidden);
1720                 }
1721         }
1722 }
1723
1724 static void write_grid_paint_mask(WriteData *wd, int count, GridPaintMask *grid_paint_mask)
1725 {
1726         if (grid_paint_mask) {
1727                 int i;
1728                 
1729                 writestruct(wd, DATA, "GridPaintMask", count, grid_paint_mask);
1730                 for (i = 0; i < count; ++i) {
1731                         GridPaintMask *gpm = &grid_paint_mask[i];
1732                         if (gpm->data) {
1733                                 const int gridsize = ccg_gridsize(gpm->level);
1734                                 writedata(wd, DATA,
1735                                           sizeof(*gpm->data) * gridsize * gridsize,
1736                                           gpm->data);
1737                         }
1738                 }
1739         }
1740 }
1741
1742 static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, int partial_type, int partial_count)
1743 {
1744         int i;
1745
1746         /* write external customdata (not for undo) */
1747         if (data->external && !wd->current)
1748                 CustomData_external_write(data, id, CD_MASK_MESH, count, 0);
1749
1750         writestruct(wd, DATA, "CustomDataLayer", data->maxlayer, data->layers);
1751
1752         for (i=0; i<data->totlayer; i++) {
1753                 CustomDataLayer *layer= &data->layers[i];
1754                 const char *structname;
1755                 int structnum, datasize;
1756
1757                 if (layer->type == CD_MDEFORMVERT) {
1758                         /* layer types that allocate own memory need special handling */
1759                         write_dverts(wd, count, layer->data);
1760                 }
1761                 else if (layer->type == CD_MDISPS) {
1762                         write_mdisps(wd, count, layer->data, layer->flag & CD_FLAG_EXTERNAL);
1763                 }
1764                 else if (layer->type == CD_PAINT_MASK) {
1765                         float *layer_data = layer->data;
1766                         writedata(wd, DATA, sizeof(*layer_data) * count, layer_data);
1767                 }
1768                 else if (layer->type == CD_GRID_PAINT_MASK) {
1769                         write_grid_paint_mask(wd, count, layer->data);
1770                 }
1771                 else {
1772                         CustomData_file_write_info(layer->type, &structname, &structnum);
1773                         if (structnum) {
1774                                 /* when using partial visibility, the MEdge and MFace layers
1775                                  * are smaller than the original, so their type and count is
1776                                  * passed to make this work */
1777                                 if (layer->type != partial_type) datasize= structnum*count;
1778                                 else datasize= structnum*partial_count;
1779
1780                                 writestruct(wd, DATA, structname, datasize, layer->data);
1781                         }
1782                         else {
1783                                 printf("%s error: layer '%s':%d - can't be written to file\n",
1784                                        __func__, structname, layer->type);
1785                         }
1786                 }
1787         }
1788
1789         if (data->external)
1790                 writestruct(wd, DATA, "CustomDataExternal", 1, data->external);
1791 }
1792
1793 static void write_meshs(WriteData *wd, ListBase *idbase)
1794 {
1795         Mesh *mesh;
1796         int save_for_old_blender= 0;
1797
1798 #ifdef USE_BMESH_SAVE_AS_COMPAT
1799         save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */
1800 #endif
1801
1802         mesh= idbase->first;
1803         while (mesh) {
1804                 if (mesh->id.us>0 || wd->current) {
1805                         /* write LibData */
1806                         if (!save_for_old_blender) {
1807
1808 #ifdef USE_BMESH_SAVE_WITHOUT_MFACE
1809                                 Mesh backup_mesh = {{0}};
1810                                 /* cache only - don't write */
1811                                 backup_mesh.mface = mesh->mface;
1812                                 mesh->mface = NULL;
1813                                 /* -- */
1814                                 backup_mesh.totface = mesh->totface;
1815                                 mesh->totface = 0;
1816                                 /* -- */
1817                                 backup_mesh.fdata = mesh->fdata;
1818                                 memset(&mesh->fdata, 0, sizeof(mesh->fdata));
1819                                 /* -- */
1820 #endif /* USE_BMESH_SAVE_WITHOUT_MFACE */
1821
1822                                 writestruct(wd, ID_ME, "Mesh", 1, mesh);
1823
1824                                 /* direct data */
1825                                 if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd);
1826                                 if (mesh->adt) write_animdata(wd, mesh->adt);
1827
1828                                 writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
1829                                 writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect);
1830
1831                                 write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0);
1832                                 write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0);
1833                                 /* fdata is really a dummy - written so slots align */
1834                                 write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0);
1835                                 write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, -1, 0);
1836                                 write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0);
1837
1838 #ifdef USE_BMESH_SAVE_WITHOUT_MFACE
1839                                 /* cache only - don't write */
1840                                 mesh->mface = backup_mesh.mface;
1841                                 /* -- */
1842                                 mesh->totface = backup_mesh.totface;
1843                                 /* -- */
1844                                 mesh->fdata = backup_mesh.fdata;
1845 #endif /* USE_BMESH_SAVE_WITHOUT_MFACE */
1846
1847                         }
1848                         else {
1849
1850 #ifdef USE_BMESH_SAVE_AS_COMPAT
1851
1852                                 Mesh backup_mesh = {{0}};
1853
1854                                 /* backup */
1855                                 backup_mesh.mpoly = mesh->mpoly;
1856                                 mesh->mpoly = NULL;
1857                                 /* -- */
1858                                 backup_mesh.mface = mesh->mface;
1859                                 mesh->mface = NULL;
1860                                 /* -- */
1861                                 backup_mesh.totface = mesh->totface;
1862                                 mesh->totface = 0;
1863                                 /* -- */
1864                                 backup_mesh.totpoly = mesh->totpoly;
1865                                 mesh->totpoly = 0;
1866                                 /* -- */
1867                                 backup_mesh.totloop = mesh->totloop;
1868                                 mesh->totloop = 0;
1869                                 /* -- */
1870                                 backup_mesh.fdata = mesh->fdata;
1871                                 CustomData_reset(&mesh->fdata);
1872                                 /* -- */
1873                                 backup_mesh.pdata = mesh->pdata;
1874                                 CustomData_reset(&mesh->pdata);
1875                                 /* -- */
1876                                 backup_mesh.ldata = mesh->ldata;
1877                                 CustomData_reset(&mesh->ldata);
1878                                 /* -- */
1879                                 backup_mesh.edit_btmesh = mesh->edit_btmesh;
1880                                 mesh->edit_btmesh = NULL;
1881                                 /* backup */
1882
1883
1884                                 /* now fill in polys to mfaces */
1885                                 mesh->totface = BKE_mesh_mpoly_to_mface(&mesh->fdata, &backup_mesh.ldata, &backup_mesh.pdata,
1886                                                                         mesh->totface, backup_mesh.totloop, backup_mesh.totpoly);
1887
1888                                 BKE_mesh_update_customdata_pointers(mesh, false);
1889
1890                                 writestruct(wd, ID_ME, "Mesh", 1, mesh);
1891
1892                                 /* direct data */
1893                                 if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd);
1894                                 if (mesh->adt) write_animdata(wd, mesh->adt);
1895
1896                                 writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
1897                                 /* writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect); */ /* pre-bmesh NULL's */
1898
1899                                 write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0);
1900                                 write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0);
1901                                 write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0);
1902                                 /* harmless for older blender versioins but _not_ writing these keeps file size down */
1903 #if 0
1904                                 write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, -1, 0);
1905                                 write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0);
1906 #endif
1907
1908                                 /* restore */
1909                                 mesh->mpoly = backup_mesh.mpoly;
1910                                 /* -- */
1911                                 mesh->mface = backup_mesh.mface;
1912                                 /* -- */
1913                                 CustomData_free(&mesh->fdata, mesh->totface);
1914                                 /* -- */
1915                                 mesh->fdata= backup_mesh.fdata;
1916                                 /* -- */
1917                                 mesh->pdata= backup_mesh.pdata;
1918                                 /* -- */
1919                                 mesh->ldata= backup_mesh.ldata;
1920                                 /* -- */
1921                                 mesh->totface = backup_mesh.totface;
1922                                 mesh->totpoly = backup_mesh.totpoly;
1923                                 mesh->totloop = backup_mesh.totloop;
1924                                 /* -- */
1925                                 BKE_mesh_update_customdata_pointers(mesh, false);
1926                                 /* --*/
1927                                 mesh->edit_btmesh = backup_mesh.edit_btmesh; /* keep this after updating custom pointers */
1928                                 /* restore */
1929
1930 #endif /* USE_BMESH_SAVE_AS_COMPAT */
1931                         }
1932                 }
1933                 mesh= mesh->id.next;
1934         }
1935 }
1936
1937 static void write_lattices(WriteData *wd, ListBase *idbase)
1938 {
1939         Lattice *lt;
1940         
1941         lt= idbase->first;
1942         while (lt) {
1943                 if (lt->id.us>0 || wd->current) {
1944                         /* write LibData */
1945                         writestruct(wd, ID_LT, "Lattice", 1, lt);
1946                         if (lt->id.properties) IDP_WriteProperty(lt->id.properties, wd);
1947                         
1948                         /* write animdata */
1949                         if (lt->adt) write_animdata(wd, lt->adt);
1950                         
1951                         /* direct data */
1952                         writestruct(wd, DATA, "BPoint", lt->pntsu*lt->pntsv*lt->pntsw, lt->def);
1953                         
1954                         write_dverts(wd, lt->pntsu*lt->pntsv*lt->pntsw, lt->dvert);
1955                         
1956                 }
1957                 lt= lt->id.next;
1958         }
1959 }
1960
1961 static void write_previews(WriteData *wd, PreviewImage *prv)
1962 {
1963         if (prv) {
1964                 short w = prv->w[1];
1965                 short h = prv->h[1];
1966                 unsigned int *rect = prv->rect[1];
1967                 /* don't write out large previews if not requested */
1968                 if (!(U.flag & USER_SAVE_PREVIEWS)) {
1969                         prv->w[1] = 0;
1970                         prv->h[1] = 0;
1971                         prv->rect[1] = NULL;
1972                 }
1973                 writestruct(wd, DATA, "PreviewImage", 1, prv);
1974                 if (prv->rect[0]) writedata(wd, DATA, prv->w[0]*prv->h[0]*sizeof(unsigned int), prv->rect[0]);
1975                 if (prv->rect[1]) writedata(wd, DATA, prv->w[1]*prv->h[1]*sizeof(unsigned int), prv->rect[1]);
1976
1977                 /* restore preview, we still want to keep it in memory even if not saved to file */
1978                 if (!(U.flag & USER_SAVE_PREVIEWS) ) {
1979                         prv->w[1] = w;
1980                         prv->h[1] = h;
1981                         prv->rect[1] = rect;
1982                 }
1983         }
1984 }
1985
1986 static void write_images(WriteData *wd, ListBase *idbase)
1987 {
1988         Image *ima;
1989         PackedFile * pf;
1990
1991
1992         ima= idbase->first;
1993         while (ima) {
1994                 if (ima->id.us>0 || wd->current) {
1995                         /* write LibData */
1996                         writestruct(wd, ID_IM, "Image", 1, ima);
1997                         if (ima->id.properties) IDP_WriteProperty(ima->id.properties, wd);
1998
1999                         if (ima->packedfile) {
2000                                 pf = ima->packedfile;
2001                                 writestruct(wd, DATA, "PackedFile", 1, pf);
2002                                 writedata(wd, DATA, pf->size, pf->data);
2003                         }
2004
2005                         write_previews(wd, ima->preview);
2006                 }
2007                 ima= ima->id.next;
2008         }
2009         /* flush helps the compression for undo-save */
2010         mywrite(wd, MYWRITE_FLUSH, 0);
2011 }
2012
2013 static void write_textures(WriteData *wd, ListBase *idbase)
2014 {
2015         Tex *tex;
2016
2017         tex= idbase->first;
2018         while (tex) {
2019                 if (tex->id.us>0 || wd->current) {
2020                         /* write LibData */
2021                         writestruct(wd, ID_TE, "Tex", 1, tex);
2022                         if (tex->id.properties) IDP_WriteProperty(tex->id.properties, wd);
2023
2024                         if (tex->adt) write_animdata(wd, tex->adt);
2025
2026                         /* direct data */
2027                         if (tex->coba) writestruct(wd, DATA, "ColorBand", 1, tex->coba);
2028                         if (tex->type == TEX_ENVMAP && tex->env) writestruct(wd, DATA, "EnvMap", 1, tex->env);
2029                         if (tex->type == TEX_POINTDENSITY && tex->pd) {
2030                                 writestruct(wd, DATA, "PointDensity", 1, tex->pd);
2031                                 if (tex->pd->coba) writestruct(wd, DATA, "ColorBand", 1, tex->pd->coba);
2032                                 if (tex->pd->falloff_curve) write_curvemapping(wd, tex->pd->falloff_curve);
2033                         }
2034                         if (tex->type == TEX_VOXELDATA) writestruct(wd, DATA, "VoxelData", 1, tex->vd);
2035                         if (tex->type == TEX_OCEAN && tex->ot) writestruct(wd, DATA, "OceanTex", 1, tex->ot);
2036                         
2037                         /* nodetree is integral part of texture, no libdata */
2038                         if (tex->nodetree) {
2039                                 writestruct(wd, DATA, "bNodeTree", 1, tex->nodetree);
2040                                 write_nodetree(wd, tex->nodetree);
2041                         }
2042                         
2043                         write_previews(wd, tex->preview);
2044                 }
2045                 tex= tex->id.next;
2046         }
2047
2048         /* flush helps the compression for undo-save */
2049         mywrite(wd, MYWRITE_FLUSH, 0);
2050 }
2051
2052 static void write_materials(WriteData *wd, ListBase *idbase)
2053 {
2054         Material *ma;
2055         int a;
2056
2057         ma= idbase->first;
2058         while (ma) {
2059                 if (ma->id.us>0 || wd->current) {
2060                         /* write LibData */
2061                         writestruct(wd, ID_MA, "Material", 1, ma);
2062                         
2063                         /* Write ID Properties -- and copy this comment EXACTLY for easy finding
2064                          * of library blocks that implement this.*/
2065                         /* manually set head group property to IDP_GROUP, just in case it hadn't been
2066                          * set yet :) */
2067                         if (ma->id.properties) IDP_WriteProperty(ma->id.properties, wd);
2068                         
2069                         if (ma->adt) write_animdata(wd, ma->adt);
2070
2071                         for (a=0; a<MAX_MTEX; a++) {
2072                                 if (ma->mtex[a]) writestruct(wd, DATA, "MTex", 1, ma->mtex[a]);
2073                         }
2074                         
2075                         if (ma->ramp_col) writestruct(wd, DATA, "ColorBand", 1, ma->ramp_col);
2076                         if (ma->ramp_spec) writestruct(wd, DATA, "ColorBand", 1, ma->ramp_spec);
2077                         
2078                         /* nodetree is integral part of material, no libdata */
2079                         if (ma->nodetree) {
2080                                 writestruct(wd, DATA, "bNodeTree", 1, ma->nodetree);
2081                                 write_nodetree(wd, ma->nodetree);
2082                         }
2083
2084                         write_previews(wd, ma->preview);
2085                 }
2086                 ma= ma->id.next;
2087         }
2088 }
2089
2090 static void write_worlds(WriteData *wd, ListBase *idbase)
2091 {
2092         World *wrld;
2093         int a;
2094
2095         wrld= idbase->first;
2096         while (wrld) {
2097                 if (wrld->id.us>0 || wd->current) {
2098                         /* write LibData */
2099                         writestruct(wd, ID_WO, "World", 1, wrld);
2100                         if (wrld->id.properties) IDP_WriteProperty(wrld->id.properties, wd);
2101                         
2102                         if (wrld->adt) write_animdata(wd, wrld->adt);
2103                         
2104                         for (a=0; a<MAX_MTEX; a++) {
2105                                 if (wrld->mtex[a]) writestruct(wd, DATA, "MTex", 1, wrld->mtex[a]);
2106                         }
2107
2108                         /* nodetree is integral part of lamps, no libdata */
2109                         if (wrld->nodetree) {
2110                                 writestruct(wd, DATA, "bNodeTree", 1, wrld->nodetree);
2111                                 write_nodetree(wd, wrld->nodetree);
2112                         }
2113                         
2114                         write_previews(wd, wrld->preview);
2115                 }
2116                 wrld= wrld->id.next;
2117         }
2118 }
2119
2120 static void write_lamps(WriteData *wd, ListBase *idbase)
2121 {
2122         Lamp *la;
2123         int a;
2124
2125         la= idbase->first;
2126         while (la) {
2127                 if (la->id.us>0 || wd->current) {
2128                         /* write LibData */
2129                         writestruct(wd, ID_LA, "Lamp", 1, la);
2130                         if (la->id.properties) IDP_WriteProperty(la->id.properties, wd);
2131                         
2132                         if (la->adt) write_animdata(wd, la->adt);
2133                         
2134                         /* direct data */
2135                         for (a=0; a<MAX_MTEX; a++) {
2136                                 if (la->mtex[a]) writestruct(wd, DATA, "MTex", 1, la->mtex[a]);
2137                         }
2138                         
2139                         if (la->curfalloff)
2140                                 write_curvemapping(wd, la->curfalloff);
2141                         
2142                         /* nodetree is integral part of lamps, no libdata */
2143                         if (la->nodetree) {
2144                                 writestruct(wd, DATA, "bNodeTree", 1, la->nodetree);
2145                                 write_nodetree(wd, la->nodetree);
2146                         }
2147
2148                         write_previews(wd, la->preview);
2149                         
2150                 }
2151                 la= la->id.next;
2152         }
2153 }
2154
2155 static void write_sequence_modifiers(WriteData *wd, ListBase *modbase)
2156 {
2157         SequenceModifierData *smd;
2158
2159         for (smd = modbase->first; smd; smd = smd->next) {
2160                 SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
2161
2162                 if (smti) {
2163                         writestruct(wd, DATA, smti->struct_name, 1, smd);
2164
2165                         if (smd->type == seqModifierType_Curves) {
2166                                 CurvesModifierData *cmd = (CurvesModifierData *) smd;
2167
2168                                 write_curvemapping(wd, &cmd->curve_mapping);
2169                         }
2170                         else if (smd->type == seqModifierType_HueCorrect) {
2171                                 HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
2172
2173                                 write_curvemapping(wd, &hcmd->curve_mapping);
2174                         }
2175                 }
2176                 else {
2177                         writestruct(wd, DATA, "SequenceModifierData", 1, smd);
2178                 }
2179         }
2180 }
2181
2182 static void write_view_settings(WriteData *wd, ColorManagedViewSettings *view_settings)
2183 {
2184         if (view_settings->curve_mapping) {
2185                 write_curvemapping(wd, view_settings->curve_mapping);
2186         }
2187 }
2188
2189 static void write_scenes(WriteData *wd, ListBase *scebase)
2190 {
2191         Scene *sce;
2192         Base *base;
2193         Editing *ed;
2194         Sequence *seq;
2195         MetaStack *ms;
2196         Strip *strip;
2197         TimeMarker *marker;
2198         TransformOrientation *ts;
2199         SceneRenderLayer *srl;
2200         ToolSettings *tos;
2201         
2202         sce= scebase->first;
2203         while (sce) {
2204                 /* write LibData */
2205                 writestruct(wd, ID_SCE, "Scene", 1, sce);
2206                 if (sce->id.properties) IDP_WriteProperty(sce->id.properties, wd);
2207                 
2208                 if (sce->adt) write_animdata(wd, sce->adt);
2209                 write_keyingsets(wd, &sce->keyingsets);
2210                 
2211                 /* direct data */
2212                 base= sce->base.first;
2213                 while (base) {
2214                         writestruct(wd, DATA, "Base", 1, base);
2215                         base= base->next;
2216                 }
2217                 
2218                 tos = sce->toolsettings;
2219                 writestruct(wd, DATA, "ToolSettings", 1, tos);
2220                 if (tos->vpaint) {
2221                         writestruct(wd, DATA, "VPaint", 1, tos->vpaint);
2222                 }
2223                 if (tos->wpaint) {
2224                         writestruct(wd, DATA, "VPaint", 1, tos->wpaint);
2225                 }
2226                 if (tos->sculpt) {
2227                         writestruct(wd, DATA, "Sculpt", 1, tos->sculpt);
2228                 }
2229                 if (tos->uvsculpt) {
2230                         writestruct(wd, DATA, "UvSculpt", 1, tos->uvsculpt);
2231                 }
2232
2233                 // write_paint(wd, &tos->imapaint.paint);
2234
2235                 ed= sce->ed;
2236                 if (ed) {
2237                         writestruct(wd, DATA, "Editing", 1, ed);
2238                         
2239                         /* reset write flags too */
2240                         
2241                         SEQ_BEGIN (ed, seq)
2242                         {
2243                                 if (seq->strip) seq->strip->done = FALSE;
2244                                 writestruct(wd, DATA, "Sequence", 1, seq);
2245                         }
2246                         SEQ_END
2247                         
2248                         SEQ_BEGIN (ed, seq)
2249                         {
2250                                 if (seq->strip && seq->strip->done==0) {
2251                                         /* write strip with 'done' at 0 because readfile */
2252                                         
2253                                         if (seq->effectdata) {
2254                                                 switch (seq->type) {
2255                                                 case SEQ_TYPE_COLOR:
2256                                                         writestruct(wd, DATA, "SolidColorVars", 1, seq->effectdata);
2257                                                         break;
2258                                                 case SEQ_TYPE_SPEED:
2259                                                         writestruct(wd, DATA, "SpeedControlVars", 1, seq->effectdata);
2260                                                         break;
2261                                                 case SEQ_TYPE_WIPE:
2262                                                         writestruct(wd, DATA, "WipeVars", 1, seq->effectdata);
2263                                                         break;
2264                                                 case SEQ_TYPE_GLOW:
2265                                                         writestruct(wd, DATA, "GlowVars", 1, seq->effectdata);
2266                                                         break;
2267                                                 case SEQ_TYPE_TRANSFORM:
2268                                                         writestruct(wd, DATA, "TransformVars", 1, seq->effectdata);
2269                                                         break;
2270                                                 }
2271                                         }
2272                                         
2273                                         strip= seq->strip;
2274                                         writestruct(wd, DATA, "Strip", 1, strip);
2275                                         if (seq->flag & SEQ_USE_CROP && strip->crop) {
2276                                                 writestruct(wd, DATA, "StripCrop", 1, strip->crop);
2277                                         }
2278                                         if (seq->flag & SEQ_USE_TRANSFORM && strip->transform) {
2279                                                 writestruct(wd, DATA, "StripTransform", 1, strip->transform);
2280                                         }
2281                                         if (seq->flag & SEQ_USE_PROXY && strip->proxy) {
2282                                                 writestruct(wd, DATA, "StripProxy", 1, strip->proxy);
2283                                         }
2284                                         if (seq->type==SEQ_TYPE_IMAGE)
2285                                                 writestruct(wd, DATA, "StripElem", MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem), strip->stripdata);
2286                                         else if (seq->type==SEQ_TYPE_MOVIE || seq->type==SEQ_TYPE_SOUND_RAM || seq->type == SEQ_TYPE_SOUND_HD)
2287                                                 writestruct(wd, DATA, "StripElem", 1, strip->stripdata);
2288                                         
2289                                         strip->done = TRUE;
2290                                 }
2291
2292                                 write_sequence_modifiers(wd, &seq->modifiers);
2293                         }
2294                         SEQ_END
2295                                 
2296                         /* new; meta stack too, even when its nasty restore code */
2297                         for (ms= ed->metastack.first; ms; ms= ms->next) {
2298                                 writestruct(wd, DATA, "MetaStack", 1, ms);
2299                         }
2300                 }
2301                 
2302                 if (sce->r.avicodecdata) {
2303                         writestruct(wd, DATA, "AviCodecData", 1, sce->r.avicodecdata);
2304                         if (sce->r.avicodecdata->lpFormat) writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
2305                         if (sce->r.avicodecdata->lpParms) writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms);
2306                 }
2307
2308                 if (sce->r.qtcodecdata) {
2309                         writestruct(wd, DATA, "QuicktimeCodecData", 1, sce->r.qtcodecdata);
2310                         if (sce->r.qtcodecdata->cdParms) writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms);
2311                 }
2312                 if (sce->r.ffcodecdata.properties) {
2313                         IDP_WriteProperty(sce->r.ffcodecdata.properties, wd);
2314                 }
2315
2316                 /* writing dynamic list of TimeMarkers to the blend file */
2317                 for (marker= sce->markers.first; marker; marker= marker->next)
2318                         writestruct(wd, DATA, "TimeMarker", 1, marker);
2319                 
2320                 /* writing dynamic list of TransformOrientations to the blend file */
2321                 for (ts = sce->transform_spaces.first; ts; ts = ts->next)
2322                         writestruct(wd, DATA, "TransformOrientation", 1, ts);
2323                 
2324                 for (srl = sce->r.layers.first; srl; srl = srl->next) {
2325                         writestruct(wd, DATA, "SceneRenderLayer", 1, srl);
2326                         
2327 #ifdef WITH_FREESTYLE
2328                         {
2329                                 FreestyleModuleConfig *fmc;
2330                                 FreestyleLineSet *fls;
2331
2332                                 for(fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
2333                                         writestruct(wd, DATA, "FreestyleModuleConfig", 1, fmc);
2334                                 }
2335                         
2336                                 for(fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
2337                                         writestruct(wd, DATA, "FreestyleLineSet", 1, fls);
2338                                 }
2339
2340                         }
2341 #endif
2342                 }
2343                 
2344                 if (sce->nodetree) {
2345                         writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree);
2346                         write_nodetree(wd, sce->nodetree);
2347                 }
2348
2349                 write_view_settings(wd, &sce->view_settings);
2350                 
2351                 /* writing RigidBodyWorld data to the blend file */
2352                 if (sce->rigidbody_world) {
2353                         writestruct(wd, DATA, "RigidBodyWorld", 1, sce->rigidbody_world);
2354                         writestruct(wd, DATA, "EffectorWeights", 1, sce->rigidbody_world->effector_weights);
2355                         write_pointcaches(wd, &(sce->rigidbody_world->ptcaches));
2356                 }
2357                 
2358                 sce= sce->id.next;
2359         }
2360         /* flush helps the compression for undo-save */
2361         mywrite(wd, MYWRITE_FLUSH, 0);
2362 }
2363
2364 static void write_gpencils(WriteData *wd, ListBase *lb)
2365 {
2366         bGPdata *gpd;
2367         bGPDlayer *gpl;
2368         bGPDframe *gpf;
2369         bGPDstroke *gps;
2370         
2371         for (gpd= lb->first; gpd; gpd= gpd->id.next) {
2372                 if (gpd->id.us>0 || wd->current) {
2373                         /* write gpd data block to file */
2374                         writestruct(wd, ID_GD, "bGPdata", 1, gpd);
2375                         
2376                         /* write grease-pencil layers to file */
2377                         writelist(wd, DATA, "bGPDlayer", &gpd->layers);
2378                         for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2379                                 
2380                                 /* write this layer's frames to file */
2381                                 writelist(wd, DATA, "bGPDframe", &gpl->frames);
2382                                 for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
2383                                         
2384                                         /* write strokes */
2385                                         writelist(wd, DATA, "bGPDstroke", &gpf->strokes);
2386                                         for (gps= gpf->strokes.first; gps; gps= gps->next) {
2387                                                 writestruct(wd, DATA, "bGPDspoint", gps->totpoints, gps->points);
2388                                         }
2389                                 }
2390                         }
2391                 }
2392         }
2393 }
2394
2395 static void write_windowmanagers(WriteData *wd, ListBase *lb)
2396 {
2397         wmWindowManager *wm;
2398         wmWindow *win;
2399         
2400         for (wm= lb->first; wm; wm= wm->id.next) {
2401                 writestruct(wd, ID_WM, "wmWindowManager", 1, wm);
2402                 
2403                 for (win= wm->windows.first; win; win= win->next)
2404                         writestruct(wd, DATA, "wmWindow", 1, win);
2405         }
2406 }
2407
2408 static void write_region(WriteData *wd, ARegion *ar, int spacetype)
2409 {       
2410         writestruct(wd, DATA, "ARegion", 1, ar);
2411         
2412         if (ar->regiondata) {
2413                 switch (spacetype) {
2414                         case SPACE_VIEW3D:
2415                                 if (ar->regiontype==RGN_TYPE_WINDOW) {
2416                                         RegionView3D *rv3d= ar->regiondata;
2417                                         writestruct(wd, DATA, "RegionView3D", 1, rv3d);
2418                                         
2419                                         if (rv3d->localvd)
2420                                                 writestruct(wd, DATA, "RegionView3D", 1, rv3d->localvd);
2421                                         if (rv3d->clipbb)
2422                                                 writestruct(wd, DATA, "BoundBox", 1, rv3d->clipbb);
2423
2424                                 }
2425                                 else
2426                                         printf("regiondata write missing!\n");
2427                                 break;
2428                         default:
2429                                 printf("regiondata write missing!\n");
2430                 }
2431         }
2432 }
2433
2434 static void write_screens(WriteData *wd, ListBase *scrbase)
2435 {
2436         bScreen *sc;
2437         ScrArea *sa;
2438         ScrVert *sv;
2439         ScrEdge *se;
2440
2441         sc= scrbase->first;
2442         while (sc) {
2443                 
2444                 /* write LibData */
2445                 /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
2446                 writestruct(wd, ID_SCRN, "Screen", 1, sc);
2447                 if (sc->id.properties) 
2448                         IDP_WriteProperty(sc->id.properties, wd);
2449                 
2450                 /* direct data */
2451                 for (sv= sc->vertbase.first; sv; sv= sv->next)
2452                         writestruct(wd, DATA, "ScrVert", 1, sv);
2453                 
2454                 for (se= sc->edgebase.first; se; se= se->next)
2455                         writestruct(wd, DATA, "ScrEdge", 1, se);
2456                 
2457                 for (sa= sc->areabase.first; sa; sa= sa->next) {
2458                         SpaceLink *sl;
2459                         Panel *pa;
2460                         uiList *ui_list;
2461                         ARegion *ar;
2462                         
2463                         writestruct(wd, DATA, "ScrArea", 1, sa);
2464                         
2465                         for (ar= sa->regionbase.first; ar; ar= ar->next) {
2466                                 write_region(wd, ar, sa->spacetype);
2467                                 
2468                                 for (pa= ar->panels.first; pa; pa= pa->next)
2469                                         writestruct(wd, DATA, "Panel", 1, pa);
2470                                 
2471                                 for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next)
2472                                         writestruct(wd, DATA, "uiList", 1, ui_list);
2473                         }
2474                         
2475                         sl= sa->spacedata.first;
2476                         while (sl) {
2477                                 for (ar= sl->regionbase.first; ar; ar= ar->next)
2478                                         write_region(wd, ar, sl->spacetype);
2479                                 
2480                                 if (sl->spacetype==SPACE_VIEW3D) {
2481                                         View3D *v3d= (View3D *) sl;
2482                                         BGpic *bgpic;
2483                                         writestruct(wd, DATA, "View3D", 1, v3d);
2484                                         for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next)
2485                                                 writestruct(wd, DATA, "BGpic", 1, bgpic);
2486                                         if (v3d->localvd) writestruct(wd, DATA, "View3D", 1, v3d->localvd);
2487                                 }
2488                                 else if (sl->spacetype==SPACE_IPO) {
2489                                         SpaceIpo *sipo= (SpaceIpo *)sl;
2490                                         ListBase tmpGhosts = sipo->ghostCurves;
2491                                         
2492                                         /* temporarily disable ghost curves when saving */
2493                                         sipo->ghostCurves.first= sipo->ghostCurves.last= NULL;
2494                                         
2495                                         writestruct(wd, DATA, "SpaceIpo", 1, sl);
2496                                         if (sipo->ads) writestruct(wd, DATA, "bDopeSheet", 1, sipo->ads);
2497                                         
2498                                         /* reenable ghost curves */
2499                                         sipo->ghostCurves= tmpGhosts;
2500                                 }
2501                                 else if (sl->spacetype==SPACE_BUTS) {
2502                                         writestruct(wd, DATA, "SpaceButs", 1, sl);
2503                                 }
2504                                 else if (sl->spacetype==SPACE_FILE) {
2505                                         SpaceFile *sfile= (SpaceFile *)sl;
2506
2507                                         writestruct(wd, DATA, "SpaceFile", 1, sl);
2508                                         if (sfile->params)
2509                                                 writestruct(wd, DATA, "FileSelectParams", 1, sfile->params);
2510                                 }
2511                                 else if (sl->spacetype==SPACE_SEQ) {
2512                                         writestruct(wd, DATA, "SpaceSeq", 1, sl);
2513                                 }
2514                                 else if (sl->spacetype==SPACE_OUTLINER) {
2515                                         SpaceOops *so= (SpaceOops *)sl;
2516                                         
2517                                         writestruct(wd, DATA, "SpaceOops", 1, so);
2518
2519                                         /* outliner */
2520                                         if (so->treestore) {
2521                                                 writestruct(wd, DATA, "TreeStore", 1, so->treestore);
2522                                                 if (so->treestore->data)
2523                                                         writestruct(wd, DATA, "TreeStoreElem", so->treestore->usedelem, so->treestore->data);
2524                                         }
2525                                 }
2526                                 else if (sl->spacetype==SPACE_IMAGE) {
2527                                         SpaceImage *sima= (SpaceImage *)sl;
2528                                         
2529                                         writestruct(wd, DATA, "SpaceImage", 1, sl);
2530                                         if (sima->cumap)
2531                                                 write_curvemapping(wd, sima->cumap);
2532                                 }
2533                                 else if (sl->spacetype==SPACE_TEXT) {
2534                                         writestruct(wd, DATA, "SpaceText", 1, sl);
2535                                 }
2536                                 else if (sl->spacetype==SPACE_SCRIPT) {
2537                                         SpaceScript *scr = (SpaceScript*)sl;
2538                                         scr->but_refs = NULL;
2539                                         writestruct(wd, DATA, "SpaceScript", 1, sl);
2540                                 }
2541                                 else if (sl->spacetype==SPACE_ACTION) {
2542                                         writestruct(wd, DATA, "SpaceAction", 1, sl);
2543                                 }
2544                                 else if (sl->spacetype==SPACE_NLA) {
2545                                         SpaceNla *snla= (SpaceNla *)sl;
2546                                         
2547                                         writestruct(wd, DATA, "SpaceNla", 1, snla);
2548                                         if (snla->ads) writestruct(wd, DATA, "bDopeSheet", 1, snla->ads);
2549                                 }
2550                                 else if (sl->spacetype==SPACE_TIME) {
2551                                         writestruct(wd, DATA, "SpaceTime", 1, sl);
2552                                 }
2553                                 else if (sl->spacetype==SPACE_NODE) {
2554                                         SpaceNode *snode = (SpaceNode *)sl;
2555                                         bNodeTreePath *path;
2556                                         writestruct(wd, DATA, "SpaceNode", 1, snode);
2557                                         
2558                                         for (path=snode->treepath.first; path; path=path->next)
2559                                                 writestruct(wd, DATA, "bNodeTreePath", 1, path);
2560                                 }
2561                                 else if (sl->spacetype==SPACE_LOGIC) {
2562                                         writestruct(wd, DATA, "SpaceLogic", 1, sl);
2563                                 }
2564                                 else if (sl->spacetype==SPACE_CONSOLE) {
2565                                         SpaceConsole *con = (SpaceConsole*)sl;
2566                                         ConsoleLine *cl;
2567
2568                                         for (cl=con->history.first; cl; cl=cl->next) {
2569                                                 /* 'len_alloc' is invalid on write, set from 'len' on read */
2570                                                 writestruct(wd, DATA, "ConsoleLine", 1, cl);
2571                                                 writedata(wd, DATA, cl->len+1, cl->line);
2572                                         }
2573                                         writestruct(wd, DATA, "SpaceConsole", 1, sl);
2574
2575                                 }
2576                                 else if (sl->spacetype==SPACE_USERPREF) {
2577                                         writestruct(wd, DATA, "SpaceUserPref", 1, sl);
2578                                 }
2579                                 else if (sl->spacetype==SPACE_CLIP) {
2580                                         writestruct(wd, DATA, "SpaceClip", 1, sl);
2581                                 }
2582
2583                                 sl= sl->next;
2584                         }
2585                 }
2586
2587                 sc= sc->id.next;
2588         }
2589         
2590         /* flush helps the compression for undo-save */
2591         mywrite(wd, MYWRITE_FLUSH, 0);
2592 }
2593
2594 static void write_libraries(WriteData *wd, Main *main)
2595 {
2596         ListBase *lbarray[MAX_LIBARRAY];
2597         ID *id;
2598         int a, tot, foundone;
2599
2600         for (; main; main= main->next) {
2601
2602                 a=tot= set_listbasepointers(main, lbarray);
2603
2604                 /* test: is lib being used */
2605                 if (main->curlib && main->curlib->packedfile)
2606                         foundone = TRUE;
2607                 else {
2608                         foundone = FALSE;
2609                         while (tot--) {
2610                                 for (id= lbarray[tot]->first; id; id= id->next) {
2611                                         if (id->us>0 && (id->flag & LIB_EXTERN)) {
2612                                                 foundone = TRUE;
2613                                                 break;
2614                                         }
2615                                 }
2616                                 if (foundone) break;
2617                         }
2618                 }
2619                 
2620                 /* to be able to restore quit.blend and temp saves, the packed blend has to be in undo buffers... */
2621                 /* XXX needs rethink, just like save UI in undo files now - would be nice to append things only for the]
2622                  * quit.blend and temp saves */
2623                 if (foundone) {
2624                         writestruct(wd, ID_LI, "Library", 1, main->curlib);
2625
2626                         if (main->curlib->packedfile) {
2627                                 PackedFile *pf = main->curlib->packedfile;
2628                                 writestruct(wd, DATA, "PackedFile", 1, pf);
2629                                 writedata(wd, DATA, pf->size, pf->data);
2630                                 if (wd->current == NULL)
2631                                         printf("write packed .blend: %s\n", main->curlib->name);
2632                         }
2633                         
2634                         while (a--) {
2635                                 for (id= lbarray[a]->first; id; id= id->next) {
2636                                         if (id->us>0 && (id->flag & LIB_EXTERN)) {
2637                                                 writestruct(wd, ID_ID, "ID", 1, id);
2638                                         }
2639                                 }
2640                         }
2641                 }
2642         }
2643 }
2644
2645 static void write_bone(WriteData *wd, Bone *bone)
2646 {
2647         Bone*   cbone;
2648
2649         // PATCH for upward compatibility after 2.37+ armature recode
2650         bone->size[0] = bone->size[1] = bone->size[2] = 1.0f;
2651                 
2652         // Write this bone
2653         writestruct(wd, DATA, "Bone", 1, bone);
2654
2655         /* Write ID Properties -- and copy this comment EXACTLY for easy finding
2656          * of library blocks that implement this.*/
2657         if (bone->prop)
2658                 IDP_WriteProperty(bone->prop, wd);
2659         
2660         // Write Children
2661         cbone= bone->childbase.first;
2662         while (cbone) {
2663                 write_bone(wd, cbone);
2664                 cbone= cbone->next;
2665         }
2666 }
2667
2668 static void write_armatures(WriteData *wd, ListBase *idbase)
2669 {
2670         bArmature       *arm;
2671         Bone            *bone;
2672
2673         arm=idbase->first;
2674         while (arm) {
2675                 if (arm->id.us>0 || wd->current) {
2676                         writestruct(wd, ID_AR, "bArmature", 1, arm);
2677                         if (arm->id.properties) IDP_WriteProperty(arm->id.properties, wd);
2678
2679                         if (arm->adt) write_animdata(wd, arm->adt);
2680
2681                         /* Direct data */
2682                         bone= arm->bonebase.first;
2683                         while (bone) {
2684                                 write_bone(wd, bone);
2685                                 bone=bone->next;
2686                         }
2687                 }
2688                 arm=arm->id.next;
2689         }
2690
2691         /* flush helps the compression for undo-save */
2692         mywrite(wd, MYWRITE_FLUSH, 0);
2693 }
2694
2695 static void write_texts(WriteData *wd, ListBase *idbase)
2696 {
2697         Text *text;
2698         TextLine *tmp;
2699
2700         text= idbase->first;
2701         while (text) {
2702                 if ( (text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) text->flags &= ~TXT_ISEXT;
2703
2704                 /* write LibData */
2705                 writestruct(wd, ID_TXT, "Text", 1, text);
2706                 if (text->name) writedata(wd, DATA, strlen(text->name)+1, text->name);
2707                 if (text->id.properties) IDP_WriteProperty(text->id.properties, wd);
2708
2709                 if (!(text->flags & TXT_ISEXT)) {
2710                         /* now write the text data, in two steps for optimization in the readfunction */
2711                         tmp= text->lines.first;
2712                         while (tmp) {
2713                                 writestruct(wd, DATA, "TextLine", 1, tmp);
2714                                 tmp= tmp->next;
2715                         }
2716
2717                         tmp= text->lines.first;
2718                         while (tmp) {
2719                                 writedata(wd, DATA, tmp->len+1, tmp->line);
2720                                 tmp= tmp->next;
2721                         }
2722                 }
2723
2724
2725                 text= text->id.next;
2726         }
2727
2728         /* flush helps the compression for undo-save */
2729         mywrite(wd, MYWRITE_FLUSH, 0);
2730 }
2731
2732 static void write_speakers(WriteData *wd, ListBase *idbase)
2733 {
2734         Speaker *spk;
2735
2736         spk= idbase->first;
2737         while (spk) {
2738                 if (spk->id.us>0 || wd->current) {
2739                         /* write LibData */
2740                         writestruct(wd, ID_SPK, "Speaker", 1, spk);
2741                         if (spk->id.properties) IDP_WriteProperty(spk->id.properties, wd);
2742
2743                         if (spk->adt) write_animdata(wd, spk->adt);
2744                 }
2745                 spk= spk->id.next;
2746         }
2747 }
2748
2749 static void write_sounds(WriteData *wd, ListBase *idbase)
2750 {
2751         bSound *sound;
2752
2753         PackedFile * pf;
2754
2755         sound= idbase->first;
2756         while (sound) {
2757                 if (sound->id.us>0 || wd->current) {
2758                         /* write LibData */
2759                         writestruct(wd, ID_SO, "bSound", 1, sound);
2760                         if (sound->id.properties) IDP_WriteProperty(sound->id.properties, wd);
2761
2762                         if (sound->packedfile) {
2763                                 pf = sound->packedfile;
2764                                 writestruct(wd, DATA, "PackedFile", 1, pf);
2765                                 writedata(wd, DATA, pf->size, pf->data);
2766                         }
2767                 }
2768                 sound= sound->id.next;
2769         }
2770
2771         /* flush helps the compression for undo-save */
2772         mywrite(wd, MYWRITE_FLUSH, 0);
2773 }
2774
2775 static void write_groups(WriteData *wd, ListBase *idbase)
2776 {
2777         Group *group;
2778         GroupObject *go;
2779
2780         for (group= idbase->first; group; group= group->id.next) {
2781                 if (group->id.us>0 || wd->current) {
2782                         /* write LibData */
2783                         writestruct(wd, ID_GR, "Group", 1, group);
2784                         if (group->id.properties) IDP_WriteProperty(group->id.properties, wd);
2785
2786                         go= group->gobject.first;
2787                         while (go) {
2788                                 writestruct(wd, DATA, "GroupObject", 1, go);
2789                                 go= go->next;
2790                         }
2791                 }
2792         }
2793 }
2794
2795 static void write_nodetrees(WriteData *wd, ListBase *idbase)
2796 {
2797         bNodeTree *ntree;
2798         
2799         for (ntree=idbase->first; ntree; ntree= ntree->id.next) {
2800                 if (ntree->id.us>0 || wd->current) {
2801                         writestruct(wd, ID_NT, "bNodeTree", 1, ntree);
2802                         write_nodetree(wd, ntree);
2803                         
2804                         if (ntree->id.properties) IDP_WriteProperty(ntree->id.properties, wd);
2805                         
2806                         if (ntree->adt) write_animdata(wd, ntree->adt);
2807                 }
2808         }
2809 }
2810
2811 #ifdef USE_NODE_COMPAT_CUSTOMNODES
2812 static void customnodes_add_deprecated_nodetree_data(bNodeTree *ntree)
2813 {
2814         bNodeLink *link, *last_link = ntree->links.last;
2815         /* Forward compatibility for group nodes: add links to node tree interface sockets.
2816          * These links are invalid by new rules (missing node pointer)!
2817          * They will be removed again in customnodes_free_deprecated_data,
2818          * cannot do this directly lest bNodeLink pointer mapping becomes ambiguous.
2819          * When loading files with such links in a new Blender version
2820          * they will be removed as well.
2821          */
2822         for (link = ntree->links.first; link; link = link->next) {
2823                 bNode *fromnode = link->fromnode, *tonode = link->tonode;
2824                 bNodeSocket *fromsock = link->fromsock, *tosock = link->tosock;
2825                 
2826                 /* check both sides of the link, to handle direct input-to-output links */
2827                 if (fromnode->type == NODE_GROUP_INPUT) {
2828                         fromnode = NULL;
2829                         fromsock = ntreeFindSocketInterface(ntree, SOCK_IN, fromsock->identifier);
2830                 }
2831                 /* only the active output node defines links */
2832                 if (tonode->type == NODE_GROUP_OUTPUT && (tonode->flag & NODE_DO_OUTPUT)) {
2833                         tonode = NULL;
2834                         tosock = ntreeFindSocketInterface(ntree, SOCK_OUT, tosock->identifier);
2835                 }
2836                 
2837                 if (!fromnode || !tonode) {
2838                         /* Note: not using nodeAddLink here, it asserts existing node pointers */
2839                         bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "group node link");
2840                         tlink->fromnode = fromnode;
2841                         tlink->fromsock = fromsock;
2842                         tlink->tonode = tonode;
2843                         tlink->tosock= tosock;
2844                         tosock->link = tlink;
2845                         tlink->flag |= NODE_LINK_VALID;
2846                         BLI_addtail(&ntree->links, tlink);
2847                 }
2848                 
2849                 /* don't check newly created compatibility links */
2850                 if (link == last_link)
2851                         break;
2852         }
2853 }
2854
2855 static void customnodes_add_deprecated_data(Main *mainvar)
2856 {
2857         bNodeTree *ntree;
2858         Scene *scene;
2859         Material *mat;
2860         World *world;
2861         Lamp *lamp;
2862         Tex *tex;
2863         
2864         for (ntree = mainvar->nodetree.first; ntree; ntree = ntree->id.next)
2865                 customnodes_add_deprecated_nodetree_data(ntree);
2866         for (scene = mainvar->scene.first; scene; scene = scene->id.next)
2867                 if (scene->nodetree)
2868                         customnodes_add_deprecated_nodetree_data(scene->nodetree);
2869         for (mat = mainvar->mat.first; mat; mat = mat->id.next)
2870                 if (mat->nodetree)
2871                         customnodes_add_deprecated_nodetree_data(mat->nodetree);
2872         for (world = mainvar->world.first; world; world = world->id.next)
2873                 if (world->nodetree)
2874                         customnodes_add_deprecated_nodetree_data(world->nodetree);
2875         for (lamp = mainvar->lamp.first; lamp; lamp = lamp->id.next)
2876                 if (lamp->nodetree)
2877                         customnodes_add_deprecated_nodetree_data(lamp->nodetree);
2878         for (tex = mainvar->tex.first; tex; tex = tex->id.next)
2879                 if (tex->nodetree)
2880                         customnodes_add_deprecated_nodetree_data(tex->nodetree);
2881 }
2882
2883 static void customnodes_free_deprecated_nodetree_data(bNodeTree *ntree)
2884 {
2885         bNodeLink *link, *next_link;
2886         
2887         for (link = ntree->links.first; link; link = next_link) {
2888                 next_link = link->next;
2889                 if (link->fromnode == NULL || link->tonode == NULL)
2890                         nodeRemLink(ntree, link);
2891         }
2892 }
2893
2894 static void customnodes_free_deprecated_data(Main *mainvar)
2895 {
2896         bNodeTree *ntree;
2897         Scene *scene;
2898         Material *mat;
2899         World *world;
2900         Lamp *lamp;
2901         Tex *tex;
2902         
2903         for (ntree = mainvar->nodetree.first; ntree; ntree = ntree->id.next)
2904                 customnodes_free_deprecated_nodetree_data(ntree);
2905         for (scene = mainvar->scene.first; scene; scene = scene->id.next)
2906                 if (scene->nodetree)
2907                         customnodes_free_deprecated_nodetree_data(scene->nodetree);
2908         for (mat = mainvar->mat.first; mat; mat = mat->id.next)
2909                 if (mat->nodetree)
2910                         customnodes_free_deprecated_nodetree_data(mat->nodetree);
2911         for (world = mainvar->world.first; world; world = world->id.next)
2912                 if (world->nodetree)
2913                         customnodes_free_deprecated_nodetree_data(world->nodetree);
2914         for (lamp = mainvar->lamp.first; lamp; lamp = lamp->id.next)
2915                 if (lamp->nodetree)
2916                         customnodes_free_deprecated_nodetree_data(lamp->nodetree);
2917         for (tex = mainvar->tex.first; tex; tex = tex->id.next)
2918                 if (tex->nodetree)
2919                         customnodes_free_deprecated_nodetree_data(tex->nodetree);
2920 }
2921 #endif
2922
2923 static void write_brushes(WriteData *wd, ListBase *idbase)
2924 {
2925         Brush *brush;
2926         
2927         for (brush=idbase->first; brush; brush= brush->id.next) {
2928                 if (brush->id.us>0 || wd->current) {
2929                         writestruct(wd, ID_BR, "Brush", 1, brush);
2930                         if (brush->id.properties) IDP_WriteProperty(brush->id.properties, wd);
2931                         
2932                         writestruct(wd, DATA, "MTex", 1, &brush->mtex);
2933                         
2934                         if (brush->curve)
2935                                 write_curvemapping(wd, brush->curve);
2936                 }
2937         }
2938 }
2939
2940 static void write_scripts(WriteData *wd, ListBase *idbase)
2941 {
2942         Script *script;
2943         
2944         for (script=idbase->first; script; script= script->id.next) {
2945                 if (script->id.us>0 || wd->current) {
2946                         writestruct(wd, ID_SCRIPT, "Script", 1, script);
2947                         if (script->id.properties) IDP_WriteProperty(script->id.properties, wd);
2948                 }
2949         }
2950 }
2951
2952 static void write_movieTracks(WriteData *wd, ListBase *tracks)
2953 {
2954         MovieTrackingTrack *track;
2955
2956         track= tracks->first;
2957         while (track) {
2958                 writestruct(wd, DATA, "MovieTrackingTrack", 1, track);
2959
2960                 if (track->markers)
2961                         writestruct(wd, DATA, "MovieTrackingMarker", track->markersnr, track->markers);
2962
2963                 track= track->next;
2964  &n