DRW: Fix couple of issues in DRW_draw_select_id
[blender.git] / source / blender / blenloader / intern / writefile.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup blenloader
22  */
23
24 /**
25  *
26  * FILE FORMAT
27  * ===========
28  *
29  * IFF-style structure  (but not IFF compatible!)
30  *
31  * start file:
32  * <pre>
33  *     BLENDER_V100    12 bytes  (version 1.00)
34  *                     V = big endian, v = little endian
35  *                     _ = 4 byte pointer, - = 8 byte pointer
36  * </pre>
37  *
38  * data-blocks: (also see struct #BHead).
39  * <pre>
40  *     <bh.code>           4 chars
41  *     <bh.len>            int,  len data after BHead
42  *     <bh.old>            void,  old pointer
43  *     <bh.SDNAnr>         int
44  *     <bh.nr>             int, in case of array: number of structs
45  *     data
46  *     ...
47  *     ...
48  * </pre>
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  * WRITE
54  * =====
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 (#RenderInfo struct. 128x128 blend file preview is optional).
69  * - write #GLOB (#FileGlobal struct) (some global vars).
70  * - write #DNA1 (#SDNA struct)
71  * - write #USER (#UserDef struct) if filename is ``~/.config/blender/X.XX/config/startup.blend``.
72  */
73
74 #include <math.h>
75 #include <fcntl.h>
76 #include <limits.h>
77 #include <stdio.h>
78 #include <string.h>
79 #include <stdlib.h>
80
81 #ifdef WIN32
82 #  include <zlib.h> /* odd include order-issue */
83 #  include "winsock2.h"
84 #  include <io.h>
85 #  include "BLI_winstuff.h"
86 #else
87 #  include <unistd.h> /* FreeBSD, for write() and close(). */
88 #endif
89
90 #include "BLI_utildefines.h"
91
92 /* allow writefile to use deprecated functionality (for forward compatibility code) */
93 #define DNA_DEPRECATED_ALLOW
94
95 #include "DNA_anim_types.h"
96 #include "DNA_armature_types.h"
97 #include "DNA_brush_types.h"
98 #include "DNA_cachefile_types.h"
99 #include "DNA_camera_types.h"
100 #include "DNA_cloth_types.h"
101 #include "DNA_collection_types.h"
102 #include "DNA_constraint_types.h"
103 #include "DNA_dynamicpaint_types.h"
104 #include "DNA_genfile.h"
105 #include "DNA_gpencil_types.h"
106 #include "DNA_gpencil_modifier_types.h"
107 #include "DNA_shader_fx_types.h"
108 #include "DNA_fileglobal_types.h"
109 #include "DNA_key_types.h"
110 #include "DNA_lattice_types.h"
111 #include "DNA_light_types.h"
112 #include "DNA_layer_types.h"
113 #include "DNA_linestyle_types.h"
114 #include "DNA_meta_types.h"
115 #include "DNA_mesh_types.h"
116 #include "DNA_meshdata_types.h"
117 #include "DNA_material_types.h"
118 #include "DNA_node_types.h"
119 #include "DNA_object_types.h"
120 #include "DNA_object_force_types.h"
121 #include "DNA_packedFile_types.h"
122 #include "DNA_particle_types.h"
123 #include "DNA_lightprobe_types.h"
124 #include "DNA_rigidbody_types.h"
125 #include "DNA_scene_types.h"
126 #include "DNA_sdna_types.h"
127 #include "DNA_sequence_types.h"
128 #include "DNA_smoke_types.h"
129 #include "DNA_space_types.h"
130 #include "DNA_screen_types.h"
131 #include "DNA_speaker_types.h"
132 #include "DNA_sound_types.h"
133 #include "DNA_text_types.h"
134 #include "DNA_view3d_types.h"
135 #include "DNA_vfont_types.h"
136 #include "DNA_world_types.h"
137 #include "DNA_windowmanager_types.h"
138 #include "DNA_workspace_types.h"
139 #include "DNA_movieclip_types.h"
140 #include "DNA_mask_types.h"
141
142 #include "MEM_guardedalloc.h"  // MEM_freeN
143 #include "BLI_bitmap.h"
144 #include "BLI_blenlib.h"
145 #include "BLI_mempool.h"
146
147 #include "BKE_action.h"
148 #include "BKE_blender_version.h"
149 #include "BKE_bpath.h"
150 #include "BKE_collection.h"
151 #include "BKE_constraint.h"
152 #include "BKE_curve.h"
153 #include "BKE_fcurve.h"
154 #include "BKE_global.h"  // for G
155 #include "BKE_gpencil_modifier.h"
156 #include "BKE_idcode.h"
157 #include "BKE_layer.h"
158 #include "BKE_library_override.h"
159 #include "BKE_main.h"
160 #include "BKE_mesh.h"
161 #include "BKE_modifier.h"
162 #include "BKE_node.h"
163 #include "BKE_pointcache.h"
164 #include "BKE_report.h"
165 #include "BKE_sequencer.h"
166 #include "BKE_shader_fx.h"
167 #include "BKE_subsurf.h"
168 #include "BKE_workspace.h"
169
170 #include "BLO_blend_defs.h"
171 #include "BLO_blend_validate.h"
172 #include "BLO_readfile.h"
173 #include "BLO_undofile.h"
174 #include "BLO_writefile.h"
175
176 #include "readfile.h"
177
178 /* for SDNA_TYPE_FROM_STRUCT() macro */
179 #include "dna_type_offsets.h"
180
181 #include <errno.h>
182
183 /* ********* my write, buffered writing with minimum size chunks ************ */
184
185 /* Use optimal allocation since blocks of this size are kept in memory for undo. */
186 #define MYWRITE_BUFFER_SIZE (MEM_SIZE_OPTIMAL(1 << 17)) /* 128kb */
187 #define MYWRITE_MAX_CHUNK (MEM_SIZE_OPTIMAL(1 << 15))   /* ~32kb */
188
189 /** Use if we want to store how many bytes have been written to the file. */
190 // #define USE_WRITE_DATA_LEN
191
192 /* -------------------------------------------------------------------- */
193 /** \name Internal Write Wrapper's (Abstracts Compression)
194  * \{ */
195
196 typedef enum {
197   WW_WRAP_NONE = 1,
198   WW_WRAP_ZLIB,
199 } eWriteWrapType;
200
201 typedef struct WriteWrap WriteWrap;
202 struct WriteWrap {
203   /* callbacks */
204   bool (*open)(WriteWrap *ww, const char *filepath);
205   bool (*close)(WriteWrap *ww);
206   size_t (*write)(WriteWrap *ww, const char *data, size_t data_len);
207
208   /* Buffer output (we only want when output isn't already buffered). */
209   bool use_buf;
210
211   /* internal */
212   union {
213     int file_handle;
214     gzFile gz_handle;
215   } _user_data;
216 };
217
218 /* none */
219 #define FILE_HANDLE(ww) (ww)->_user_data.file_handle
220
221 static bool ww_open_none(WriteWrap *ww, const char *filepath)
222 {
223   int file;
224
225   file = BLI_open(filepath, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666);
226
227   if (file != -1) {
228     FILE_HANDLE(ww) = file;
229     return true;
230   }
231   else {
232     return false;
233   }
234 }
235 static bool ww_close_none(WriteWrap *ww)
236 {
237   return (close(FILE_HANDLE(ww)) != -1);
238 }
239 static size_t ww_write_none(WriteWrap *ww, const char *buf, size_t buf_len)
240 {
241   return write(FILE_HANDLE(ww), buf, buf_len);
242 }
243 #undef FILE_HANDLE
244
245 /* zlib */
246 #define FILE_HANDLE(ww) (ww)->_user_data.gz_handle
247
248 static bool ww_open_zlib(WriteWrap *ww, const char *filepath)
249 {
250   gzFile file;
251
252   file = BLI_gzopen(filepath, "wb1");
253
254   if (file != Z_NULL) {
255     FILE_HANDLE(ww) = file;
256     return true;
257   }
258   else {
259     return false;
260   }
261 }
262 static bool ww_close_zlib(WriteWrap *ww)
263 {
264   return (gzclose(FILE_HANDLE(ww)) == Z_OK);
265 }
266 static size_t ww_write_zlib(WriteWrap *ww, const char *buf, size_t buf_len)
267 {
268   return gzwrite(FILE_HANDLE(ww), buf, buf_len);
269 }
270 #undef FILE_HANDLE
271
272 /* --- end compression types --- */
273
274 static void ww_handle_init(eWriteWrapType ww_type, WriteWrap *r_ww)
275 {
276   memset(r_ww, 0, sizeof(*r_ww));
277
278   switch (ww_type) {
279     case WW_WRAP_ZLIB: {
280       r_ww->open = ww_open_zlib;
281       r_ww->close = ww_close_zlib;
282       r_ww->write = ww_write_zlib;
283       r_ww->use_buf = false;
284       break;
285     }
286     default: {
287       r_ww->open = ww_open_none;
288       r_ww->close = ww_close_none;
289       r_ww->write = ww_write_none;
290       r_ww->use_buf = true;
291       break;
292     }
293   }
294 }
295
296 /** \} */
297
298 /* -------------------------------------------------------------------- */
299 /** \name Write Data Type & Functions
300  * \{ */
301
302 typedef struct {
303   const struct SDNA *sdna;
304
305   /** Use for file and memory writing (fixed size of #MYWRITE_BUFFER_SIZE). */
306   uchar *buf;
307   /** Number of bytes used in #WriteData.buf (flushed when exceeded). */
308   int buf_used_len;
309
310 #ifdef USE_WRITE_DATA_LEN
311   /** Total number of bytes written. */
312   size_t write_len;
313 #endif
314
315   /** Set on unlikely case of an error (ignores further file writing).  */
316   bool error;
317
318   /** #MemFile writing (used for undo). */
319   struct {
320     MemFile *current;
321     MemFile *compare;
322     /** Use to de-duplicate chunks when writing. */
323     MemFileChunk *compare_chunk;
324   } mem;
325   /** When true, write to #WriteData.current, could also call 'is_undo'. */
326   bool use_memfile;
327
328   /**
329    * Wrap writing, so we can use zlib or
330    * other compression types later, see: G_FILE_COMPRESS
331    * Will be NULL for UNDO.
332    */
333   WriteWrap *ww;
334 } WriteData;
335
336 static WriteData *writedata_new(WriteWrap *ww)
337 {
338   WriteData *wd = MEM_callocN(sizeof(*wd), "writedata");
339
340   wd->sdna = DNA_sdna_current_get();
341
342   wd->ww = ww;
343
344   if ((ww == NULL) || (ww->use_buf)) {
345     wd->buf = MEM_mallocN(MYWRITE_BUFFER_SIZE, "wd->buf");
346   }
347
348   return wd;
349 }
350
351 static void writedata_do_write(WriteData *wd, const void *mem, int memlen)
352 {
353   if ((wd == NULL) || wd->error || (mem == NULL) || memlen < 1) {
354     return;
355   }
356
357   if (UNLIKELY(wd->error)) {
358     return;
359   }
360
361   /* memory based save */
362   if (wd->use_memfile) {
363     memfile_chunk_add(wd->mem.current, mem, memlen, &wd->mem.compare_chunk);
364   }
365   else {
366     if (wd->ww->write(wd->ww, mem, memlen) != memlen) {
367       wd->error = true;
368     }
369   }
370 }
371
372 static void writedata_free(WriteData *wd)
373 {
374   if (wd->buf) {
375     MEM_freeN(wd->buf);
376   }
377   MEM_freeN(wd);
378 }
379
380 /** \} */
381
382 /* -------------------------------------------------------------------- */
383 /** \name Local Writing API 'mywrite'
384  * \{ */
385
386 /**
387  * Flush helps the de-duplicating memory for undo-save by logically segmenting data,
388  * so differences in one part of memory won't cause unrelated data to be duplicated.
389  */
390 static void mywrite_flush(WriteData *wd)
391 {
392   if (wd->buf_used_len) {
393     writedata_do_write(wd, wd->buf, wd->buf_used_len);
394     wd->buf_used_len = 0;
395   }
396 }
397
398 /**
399  * Low level WRITE(2) wrapper that buffers data
400  * \param adr: Pointer to new chunk of data
401  * \param len: Length of new chunk of data
402  */
403 static void mywrite(WriteData *wd, const void *adr, int len)
404 {
405   if (UNLIKELY(wd->error)) {
406     return;
407   }
408
409   if (UNLIKELY(adr == NULL)) {
410     BLI_assert(0);
411     return;
412   }
413
414 #ifdef USE_WRITE_DATA_LEN
415   wd->write_len += len;
416 #endif
417
418   if (wd->buf == NULL) {
419     writedata_do_write(wd, adr, len);
420   }
421   else {
422     /* if we have a single big chunk, write existing data in
423      * buffer and write out big chunk in smaller pieces */
424     if (len > MYWRITE_MAX_CHUNK) {
425       if (wd->buf_used_len) {
426         writedata_do_write(wd, wd->buf, wd->buf_used_len);
427         wd->buf_used_len = 0;
428       }
429
430       do {
431         int writelen = MIN2(len, MYWRITE_MAX_CHUNK);
432         writedata_do_write(wd, adr, writelen);
433         adr = (const char *)adr + writelen;
434         len -= writelen;
435       } while (len > 0);
436
437       return;
438     }
439
440     /* if data would overflow buffer, write out the buffer */
441     if (len + wd->buf_used_len > MYWRITE_BUFFER_SIZE - 1) {
442       writedata_do_write(wd, wd->buf, wd->buf_used_len);
443       wd->buf_used_len = 0;
444     }
445
446     /* append data at end of buffer */
447     memcpy(&wd->buf[wd->buf_used_len], adr, len);
448     wd->buf_used_len += len;
449   }
450 }
451
452 /**
453  * BeGiN initializer for mywrite
454  * \param ww: File write wrapper.
455  * \param compare: Previous memory file (can be NULL).
456  * \param current: The current memory file (can be NULL).
457  * \warning Talks to other functions with global parameters
458  */
459 static WriteData *mywrite_begin(WriteWrap *ww, MemFile *compare, MemFile *current)
460 {
461   WriteData *wd = writedata_new(ww);
462
463   if (current != NULL) {
464     wd->mem.current = current;
465     wd->mem.compare = compare;
466     wd->mem.compare_chunk = compare ? compare->chunks.first : NULL;
467     wd->use_memfile = true;
468   }
469
470   return wd;
471 }
472
473 /**
474  * END the mywrite wrapper
475  * \return 1 if write failed
476  * \return unknown global variable otherwise
477  * \warning Talks to other functions with global parameters
478  */
479 static bool mywrite_end(WriteData *wd)
480 {
481   if (wd->buf_used_len) {
482     writedata_do_write(wd, wd->buf, wd->buf_used_len);
483     wd->buf_used_len = 0;
484   }
485
486   const bool err = wd->error;
487   writedata_free(wd);
488
489   return err;
490 }
491
492 /** \} */
493
494 /* -------------------------------------------------------------------- */
495 /** \name Generic DNA File Writing
496  * \{ */
497
498 static void writestruct_at_address_nr(
499     WriteData *wd, int filecode, const int struct_nr, int nr, const void *adr, const void *data)
500 {
501   BHead bh;
502   const short *sp;
503
504   BLI_assert(struct_nr > 0 && struct_nr < SDNA_TYPE_MAX);
505
506   if (adr == NULL || data == NULL || nr == 0) {
507     return;
508   }
509
510   /* init BHead */
511   bh.code = filecode;
512   bh.old = adr;
513   bh.nr = nr;
514
515   bh.SDNAnr = struct_nr;
516   sp = wd->sdna->structs[bh.SDNAnr];
517
518   bh.len = nr * wd->sdna->types_size[sp[0]];
519
520   if (bh.len == 0) {
521     return;
522   }
523
524   mywrite(wd, &bh, sizeof(BHead));
525   mywrite(wd, data, bh.len);
526 }
527
528 static void writestruct_at_address_id(
529     WriteData *wd, int filecode, const char *structname, int nr, const void *adr, const void *data)
530 {
531   if (adr == NULL || data == NULL || nr == 0) {
532     return;
533   }
534
535   const int SDNAnr = DNA_struct_find_nr(wd->sdna, structname);
536   if (UNLIKELY(SDNAnr == -1)) {
537     printf("error: can't find SDNA code <%s>\n", structname);
538     return;
539   }
540
541   writestruct_at_address_nr(wd, filecode, SDNAnr, nr, adr, data);
542 }
543
544 static void writestruct_nr(
545     WriteData *wd, int filecode, const int struct_nr, int nr, const void *adr)
546 {
547   writestruct_at_address_nr(wd, filecode, struct_nr, nr, adr, adr);
548 }
549
550 static void writestruct_id(
551     WriteData *wd, int filecode, const char *structname, int nr, const void *adr)
552 {
553   writestruct_at_address_id(wd, filecode, structname, nr, adr, adr);
554 }
555
556 /* do not use for structs */
557 static void writedata(WriteData *wd, int filecode, int len, const void *adr)
558 {
559   BHead bh;
560
561   if (adr == NULL || len == 0) {
562     return;
563   }
564
565   /* align to 4 (writes uninitialized bytes in some cases) */
566   len = (len + 3) & ~3;
567
568   /* init BHead */
569   bh.code = filecode;
570   bh.old = adr;
571   bh.nr = 1;
572   bh.SDNAnr = 0;
573   bh.len = len;
574
575   mywrite(wd, &bh, sizeof(BHead));
576   mywrite(wd, adr, len);
577 }
578
579 /* use this to force writing of lists in same order as reading (using link_list) */
580 static void writelist_nr(WriteData *wd, int filecode, const int struct_nr, const ListBase *lb)
581 {
582   const Link *link = lb->first;
583
584   while (link) {
585     writestruct_nr(wd, filecode, struct_nr, 1, link);
586     link = link->next;
587   }
588 }
589
590 #if 0
591 static void writelist_id(WriteData *wd, int filecode, const char *structname, const ListBase *lb)
592 {
593   const Link *link = lb->first;
594   if (link) {
595
596     const int struct_nr = DNA_struct_find_nr(wd->sdna, structname);
597     if (struct_nr == -1) {
598       printf("error: can't find SDNA code <%s>\n", structname);
599       return;
600     }
601
602     while (link) {
603       writestruct_nr(wd, filecode, struct_nr, 1, link);
604       link = link->next;
605     }
606   }
607 }
608 #endif
609
610 #define writestruct_at_address(wd, filecode, struct_id, nr, adr, data) \
611   writestruct_at_address_nr(wd, filecode, SDNA_TYPE_FROM_STRUCT(struct_id), nr, adr, data)
612
613 #define writestruct(wd, filecode, struct_id, nr, adr) \
614   writestruct_nr(wd, filecode, SDNA_TYPE_FROM_STRUCT(struct_id), nr, adr)
615
616 #define writelist(wd, filecode, struct_id, lb) \
617   writelist_nr(wd, filecode, SDNA_TYPE_FROM_STRUCT(struct_id), lb)
618
619 /** \} */
620
621 /* -------------------------------------------------------------------- */
622 /** \name Typed DNA File Writing
623  *
624  * These functions are used by blender's .blend system for file saving/loading.
625  * \{ */
626
627 void IDP_WriteProperty_OnlyData(const IDProperty *prop, void *wd);
628 void IDP_WriteProperty(const IDProperty *prop, void *wd);
629
630 static void IDP_WriteArray(const IDProperty *prop, void *wd)
631 {
632   /*REMEMBER to set totalen to len in the linking code!!*/
633   if (prop->data.pointer) {
634     writedata(wd, DATA, MEM_allocN_len(prop->data.pointer), prop->data.pointer);
635
636     if (prop->subtype == IDP_GROUP) {
637       IDProperty **array = prop->data.pointer;
638       int a;
639
640       for (a = 0; a < prop->len; a++) {
641         IDP_WriteProperty(array[a], wd);
642       }
643     }
644   }
645 }
646
647 static void IDP_WriteIDPArray(const IDProperty *prop, void *wd)
648 {
649   /*REMEMBER to set totalen to len in the linking code!!*/
650   if (prop->data.pointer) {
651     const IDProperty *array = prop->data.pointer;
652     int a;
653
654     writestruct(wd, DATA, IDProperty, prop->len, array);
655
656     for (a = 0; a < prop->len; a++) {
657       IDP_WriteProperty_OnlyData(&array[a], wd);
658     }
659   }
660 }
661
662 static void IDP_WriteString(const IDProperty *prop, void *wd)
663 {
664   /*REMEMBER to set totalen to len in the linking code!!*/
665   writedata(wd, DATA, prop->len, prop->data.pointer);
666 }
667
668 static void IDP_WriteGroup(const IDProperty *prop, void *wd)
669 {
670   IDProperty *loop;
671
672   for (loop = prop->data.group.first; loop; loop = loop->next) {
673     IDP_WriteProperty(loop, wd);
674   }
675 }
676
677 /* Functions to read/write ID Properties */
678 void IDP_WriteProperty_OnlyData(const IDProperty *prop, void *wd)
679 {
680   switch (prop->type) {
681     case IDP_GROUP:
682       IDP_WriteGroup(prop, wd);
683       break;
684     case IDP_STRING:
685       IDP_WriteString(prop, wd);
686       break;
687     case IDP_ARRAY:
688       IDP_WriteArray(prop, wd);
689       break;
690     case IDP_IDPARRAY:
691       IDP_WriteIDPArray(prop, wd);
692       break;
693   }
694 }
695
696 void IDP_WriteProperty(const IDProperty *prop, void *wd)
697 {
698   writestruct(wd, DATA, IDProperty, 1, prop);
699   IDP_WriteProperty_OnlyData(prop, wd);
700 }
701
702 static void write_iddata(void *wd, const ID *id)
703 {
704   /* ID_WM's id->properties are considered runtime only, and never written in .blend file. */
705   if (id->properties && !ELEM(GS(id->name), ID_WM)) {
706     IDP_WriteProperty(id->properties, wd);
707   }
708
709   if (id->override_library) {
710     writestruct(wd, DATA, IDOverrideLibrary, 1, id->override_library);
711
712     writelist(wd, DATA, IDOverrideLibraryProperty, &id->override_library->properties);
713     for (IDOverrideLibraryProperty *op = id->override_library->properties.first; op;
714          op = op->next) {
715       writedata(wd, DATA, strlen(op->rna_path) + 1, op->rna_path);
716
717       writelist(wd, DATA, IDOverrideLibraryPropertyOperation, &op->operations);
718       for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop;
719            opop = opop->next) {
720         if (opop->subitem_reference_name) {
721           writedata(
722               wd, DATA, strlen(opop->subitem_reference_name) + 1, opop->subitem_reference_name);
723         }
724         if (opop->subitem_local_name) {
725           writedata(wd, DATA, strlen(opop->subitem_local_name) + 1, opop->subitem_local_name);
726         }
727       }
728     }
729   }
730 }
731
732 static void write_previews(WriteData *wd, const PreviewImage *prv_orig)
733 {
734   /* Note we write previews also for undo steps. It takes up some memory,
735    * but not doing so would causes all previews to be re-rendered after
736    * undo which is too expensive. */
737   if (prv_orig) {
738     PreviewImage prv = *prv_orig;
739
740     /* don't write out large previews if not requested */
741     if (!(U.flag & USER_SAVE_PREVIEWS)) {
742       prv.w[1] = 0;
743       prv.h[1] = 0;
744       prv.rect[1] = NULL;
745     }
746     writestruct_at_address(wd, DATA, PreviewImage, 1, prv_orig, &prv);
747     if (prv.rect[0]) {
748       writedata(wd, DATA, prv.w[0] * prv.h[0] * sizeof(uint), prv.rect[0]);
749     }
750     if (prv.rect[1]) {
751       writedata(wd, DATA, prv.w[1] * prv.h[1] * sizeof(uint), prv.rect[1]);
752     }
753   }
754 }
755
756 static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
757 {
758   FModifier *fcm;
759
760   /* Write all modifiers first (for faster reloading) */
761   writelist(wd, DATA, FModifier, fmodifiers);
762
763   /* Modifiers */
764   for (fcm = fmodifiers->first; fcm; fcm = fcm->next) {
765     const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);
766
767     /* Write the specific data */
768     if (fmi && fcm->data) {
769       /* firstly, just write the plain fmi->data struct */
770       writestruct_id(wd, DATA, fmi->structName, 1, fcm->data);
771
772       /* do any modifier specific stuff */
773       switch (fcm->type) {
774         case FMODIFIER_TYPE_GENERATOR: {
775           FMod_Generator *data = fcm->data;
776
777           /* write coefficients array */
778           if (data->coefficients) {
779             writedata(wd, DATA, sizeof(float) * (data->arraysize), data->coefficients);
780           }
781
782           break;
783         }
784         case FMODIFIER_TYPE_ENVELOPE: {
785           FMod_Envelope *data = fcm->data;
786
787           /* write envelope data */
788           if (data->data) {
789             writestruct(wd, DATA, FCM_EnvelopeData, data->totvert, data->data);
790           }
791
792           break;
793         }
794         case FMODIFIER_TYPE_PYTHON: {
795           FMod_Python *data = fcm->data;
796
797           /* Write ID Properties -- and copy this comment EXACTLY for easy finding
798            * of library blocks that implement this.*/
799           IDP_WriteProperty(data->prop, wd);
800
801           break;
802         }
803       }
804     }
805   }
806 }
807
808 static void write_fcurves(WriteData *wd, ListBase *fcurves)
809 {
810   FCurve *fcu;
811
812   writelist(wd, DATA, FCurve, fcurves);
813   for (fcu = fcurves->first; fcu; fcu = fcu->next) {
814     /* curve data */
815     if (fcu->bezt) {
816       writestruct(wd, DATA, BezTriple, fcu->totvert, fcu->bezt);
817     }
818     if (fcu->fpt) {
819       writestruct(wd, DATA, FPoint, fcu->totvert, fcu->fpt);
820     }
821
822     if (fcu->rna_path) {
823       writedata(wd, DATA, strlen(fcu->rna_path) + 1, fcu->rna_path);
824     }
825
826     /* driver data */
827     if (fcu->driver) {
828       ChannelDriver *driver = fcu->driver;
829       DriverVar *dvar;
830
831       writestruct(wd, DATA, ChannelDriver, 1, driver);
832
833       /* variables */
834       writelist(wd, DATA, DriverVar, &driver->variables);
835       for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
836         DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
837           if (dtar->rna_path) {
838             writedata(wd, DATA, strlen(dtar->rna_path) + 1, dtar->rna_path);
839           }
840         }
841         DRIVER_TARGETS_LOOPER_END;
842       }
843     }
844
845     /* write F-Modifiers */
846     write_fmodifiers(wd, &fcu->modifiers);
847   }
848 }
849
850 static void write_action(WriteData *wd, bAction *act)
851 {
852   if (act->id.us > 0 || wd->use_memfile) {
853     writestruct(wd, ID_AC, bAction, 1, act);
854     write_iddata(wd, &act->id);
855
856     write_fcurves(wd, &act->curves);
857
858     for (bActionGroup *grp = act->groups.first; grp; grp = grp->next) {
859       writestruct(wd, DATA, bActionGroup, 1, grp);
860     }
861
862     for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
863       writestruct(wd, DATA, TimeMarker, 1, marker);
864     }
865   }
866 }
867
868 static void write_keyingsets(WriteData *wd, ListBase *list)
869 {
870   KeyingSet *ks;
871   KS_Path *ksp;
872
873   for (ks = list->first; ks; ks = ks->next) {
874     /* KeyingSet */
875     writestruct(wd, DATA, KeyingSet, 1, ks);
876
877     /* Paths */
878     for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
879       /* Path */
880       writestruct(wd, DATA, KS_Path, 1, ksp);
881
882       if (ksp->rna_path) {
883         writedata(wd, DATA, strlen(ksp->rna_path) + 1, ksp->rna_path);
884       }
885     }
886   }
887 }
888
889 static void write_nlastrips(WriteData *wd, ListBase *strips)
890 {
891   NlaStrip *strip;
892
893   writelist(wd, DATA, NlaStrip, strips);
894   for (strip = strips->first; strip; strip = strip->next) {
895     /* write the strip's F-Curves and modifiers */
896     write_fcurves(wd, &strip->fcurves);
897     write_fmodifiers(wd, &strip->modifiers);
898
899     /* write the strip's children */
900     write_nlastrips(wd, &strip->strips);
901   }
902 }
903
904 static void write_nladata(WriteData *wd, ListBase *nlabase)
905 {
906   NlaTrack *nlt;
907
908   /* write all the tracks */
909   for (nlt = nlabase->first; nlt; nlt = nlt->next) {
910     /* write the track first */
911     writestruct(wd, DATA, NlaTrack, 1, nlt);
912
913     /* write the track's strips */
914     write_nlastrips(wd, &nlt->strips);
915   }
916 }
917
918 static void write_animdata(WriteData *wd, AnimData *adt)
919 {
920   AnimOverride *aor;
921
922   /* firstly, just write the AnimData block */
923   writestruct(wd, DATA, AnimData, 1, adt);
924
925   /* write drivers */
926   write_fcurves(wd, &adt->drivers);
927
928   /* write overrides */
929   // FIXME: are these needed?
930   for (aor = adt->overrides.first; aor; aor = aor->next) {
931     /* overrides consist of base data + rna_path */
932     writestruct(wd, DATA, AnimOverride, 1, aor);
933     writedata(wd, DATA, strlen(aor->rna_path) + 1, aor->rna_path);
934   }
935
936   // TODO write the remaps (if they are needed)
937
938   /* write NLA data */
939   write_nladata(wd, &adt->nla_tracks);
940 }
941
942 static void write_curvemapping_curves(WriteData *wd, CurveMapping *cumap)
943 {
944   for (int a = 0; a < CM_TOT; a++) {
945     writestruct(wd, DATA, CurveMapPoint, cumap->cm[a].totpoint, cumap->cm[a].curve);
946   }
947 }
948
949 static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
950 {
951   writestruct(wd, DATA, CurveMapping, 1, cumap);
952
953   write_curvemapping_curves(wd, cumap);
954 }
955
956 static void write_node_socket(WriteData *wd, bNodeSocket *sock)
957 {
958   /* actual socket writing */
959   writestruct(wd, DATA, bNodeSocket, 1, sock);
960
961   if (sock->prop) {
962     IDP_WriteProperty(sock->prop, wd);
963   }
964
965   if (sock->default_value) {
966     writedata(wd, DATA, MEM_allocN_len(sock->default_value), sock->default_value);
967   }
968 }
969 static void write_node_socket_interface(WriteData *wd, bNodeSocket *sock)
970 {
971   /* actual socket writing */
972   writestruct(wd, DATA, bNodeSocket, 1, sock);
973
974   if (sock->prop) {
975     IDP_WriteProperty(sock->prop, wd);
976   }
977
978   if (sock->default_value) {
979     writedata(wd, DATA, MEM_allocN_len(sock->default_value), sock->default_value);
980   }
981 }
982 /* this is only direct data, tree itself should have been written */
983 static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
984 {
985   bNode *node;
986   bNodeSocket *sock;
987   bNodeLink *link;
988
989   /* for link_list() speed, we write per list */
990
991   if (ntree->adt) {
992     write_animdata(wd, ntree->adt);
993   }
994
995   for (node = ntree->nodes.first; node; node = node->next) {
996     writestruct(wd, DATA, bNode, 1, node);
997
998     if (node->prop) {
999       IDP_WriteProperty(node->prop, wd);
1000     }
1001
1002     for (sock = node->inputs.first; sock; sock = sock->next) {
1003       write_node_socket(wd, sock);
1004     }
1005     for (sock = node->outputs.first; sock; sock = sock->next) {
1006       write_node_socket(wd, sock);
1007     }
1008
1009     for (link = node->internal_links.first; link; link = link->next) {
1010       writestruct(wd, DATA, bNodeLink, 1, link);
1011     }
1012
1013     if (node->storage) {
1014       /* could be handlerized at some point, now only 1 exception still */
1015       if ((ntree->type == NTREE_SHADER) &&
1016           ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB)) {
1017         write_curvemapping(wd, node->storage);
1018       }
1019       else if (ntree->type == NTREE_SHADER && (node->type == SH_NODE_SCRIPT)) {
1020         NodeShaderScript *nss = (NodeShaderScript *)node->storage;
1021         if (nss->bytecode) {
1022           writedata(wd, DATA, strlen(nss->bytecode) + 1, nss->bytecode);
1023         }
1024         writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
1025       }
1026       else if ((ntree->type == NTREE_COMPOSIT) && ELEM(node->type,
1027                                                        CMP_NODE_TIME,
1028                                                        CMP_NODE_CURVE_VEC,
1029                                                        CMP_NODE_CURVE_RGB,
1030                                                        CMP_NODE_HUECORRECT)) {
1031         write_curvemapping(wd, node->storage);
1032       }
1033       else if ((ntree->type == NTREE_TEXTURE) &&
1034                (node->type == TEX_NODE_CURVE_RGB || node->type == TEX_NODE_CURVE_TIME)) {
1035         write_curvemapping(wd, node->storage);
1036       }
1037       else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_MOVIEDISTORTION)) {
1038         /* pass */
1039       }
1040       else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_GLARE)) {
1041         /* Simple forward compatibility for fix for T50736.
1042          * Not ideal (there is no ideal solution here), but should do for now. */
1043         NodeGlare *ndg = node->storage;
1044         /* Not in undo case. */
1045         if (wd->use_memfile == false) {
1046           switch (ndg->type) {
1047             case 2: /* Grrrr! magic numbers :( */
1048               ndg->angle = ndg->streaks;
1049               break;
1050             case 0:
1051               ndg->angle = ndg->star_45;
1052               break;
1053             default:
1054               break;
1055           }
1056         }
1057         writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
1058       }
1059       else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_CRYPTOMATTE)) {
1060         NodeCryptomatte *nc = (NodeCryptomatte *)node->storage;
1061         if (nc->matte_id) {
1062           writedata(wd, DATA, strlen(nc->matte_id) + 1, nc->matte_id);
1063         }
1064         writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
1065       }
1066       else {
1067         writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
1068       }
1069     }
1070
1071     if (node->type == CMP_NODE_OUTPUT_FILE) {
1072       /* inputs have own storage data */
1073       for (sock = node->inputs.first; sock; sock = sock->next) {
1074         writestruct(wd, DATA, NodeImageMultiFileSocket, 1, sock->storage);
1075       }
1076     }
1077     if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) {
1078       /* write extra socket info */
1079       for (sock = node->outputs.first; sock; sock = sock->next) {
1080         writestruct(wd, DATA, NodeImageLayer, 1, sock->storage);
1081       }
1082     }
1083   }
1084
1085   for (link = ntree->links.first; link; link = link->next) {
1086     writestruct(wd, DATA, bNodeLink, 1, link);
1087   }
1088
1089   for (sock = ntree->inputs.first; sock; sock = sock->next) {
1090     write_node_socket_interface(wd, sock);
1091   }
1092   for (sock = ntree->outputs.first; sock; sock = sock->next) {
1093     write_node_socket_interface(wd, sock);
1094   }
1095 }
1096
1097 /**
1098  * Take care using 'use_active_win', since we wont want the currently active window
1099  * to change which scene renders (currently only used for undo).
1100  */
1101 static void current_screen_compat(Main *mainvar,
1102                                   bool use_active_win,
1103                                   bScreen **r_screen,
1104                                   Scene **r_scene,
1105                                   ViewLayer **r_view_layer)
1106 {
1107   wmWindowManager *wm;
1108   wmWindow *window = NULL;
1109
1110   /* find a global current screen in the first open window, to have
1111    * a reasonable default for reading in older versions */
1112   wm = mainvar->wm.first;
1113
1114   if (wm) {
1115     if (use_active_win) {
1116       /* write the active window into the file, needed for multi-window undo T43424 */
1117       for (window = wm->windows.first; window; window = window->next) {
1118         if (window->active) {
1119           break;
1120         }
1121       }
1122
1123       /* fallback */
1124       if (window == NULL) {
1125         window = wm->windows.first;
1126       }
1127     }
1128     else {
1129       window = wm->windows.first;
1130     }
1131   }
1132
1133   *r_screen = (window) ? BKE_workspace_active_screen_get(window->workspace_hook) : NULL;
1134   *r_scene = (window) ? window->scene : NULL;
1135   *r_view_layer = (window && *r_scene) ? BKE_view_layer_find(*r_scene, window->view_layer_name) :
1136                                          NULL;
1137 }
1138
1139 typedef struct RenderInfo {
1140   int sfra;
1141   int efra;
1142   char scene_name[MAX_ID_NAME - 2];
1143 } RenderInfo;
1144
1145 /**
1146  * This was originally added for the historic render-daemon feature,
1147  * now write because it can be easily extracted without reading the whole blend file.
1148  *
1149  * See: `release/scripts/modules/blend_render_info.py`
1150  */
1151 static void write_renderinfo(WriteData *wd, Main *mainvar)
1152 {
1153   bScreen *curscreen;
1154   Scene *sce, *curscene = NULL;
1155   ViewLayer *view_layer;
1156   RenderInfo data;
1157
1158   /* XXX in future, handle multiple windows with multiple screens? */
1159   current_screen_compat(mainvar, false, &curscreen, &curscene, &view_layer);
1160
1161   for (sce = mainvar->scenes.first; sce; sce = sce->id.next) {
1162     if (sce->id.lib == NULL && (sce == curscene || (sce->r.scemode & R_BG_RENDER))) {
1163       data.sfra = sce->r.sfra;
1164       data.efra = sce->r.efra;
1165       memset(data.scene_name, 0, sizeof(data.scene_name));
1166
1167       BLI_strncpy(data.scene_name, sce->id.name + 2, sizeof(data.scene_name));
1168
1169       writedata(wd, REND, sizeof(data), &data);
1170     }
1171   }
1172 }
1173
1174 static void write_keymapitem(WriteData *wd, const wmKeyMapItem *kmi)
1175 {
1176   writestruct(wd, DATA, wmKeyMapItem, 1, kmi);
1177   if (kmi->properties) {
1178     IDP_WriteProperty(kmi->properties, wd);
1179   }
1180 }
1181
1182 static void write_userdef(WriteData *wd, const UserDef *userdef)
1183 {
1184   writestruct(wd, USER, UserDef, 1, userdef);
1185
1186   for (const bTheme *btheme = userdef->themes.first; btheme; btheme = btheme->next) {
1187     writestruct(wd, DATA, bTheme, 1, btheme);
1188   }
1189
1190   for (const wmKeyMap *keymap = userdef->user_keymaps.first; keymap; keymap = keymap->next) {
1191     writestruct(wd, DATA, wmKeyMap, 1, keymap);
1192
1193     for (const wmKeyMapDiffItem *kmdi = keymap->diff_items.first; kmdi; kmdi = kmdi->next) {
1194       writestruct(wd, DATA, wmKeyMapDiffItem, 1, kmdi);
1195       if (kmdi->remove_item) {
1196         write_keymapitem(wd, kmdi->remove_item);
1197       }
1198       if (kmdi->add_item) {
1199         write_keymapitem(wd, kmdi->add_item);
1200       }
1201     }
1202
1203     for (const wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
1204       write_keymapitem(wd, kmi);
1205     }
1206   }
1207
1208   for (const wmKeyConfigPref *kpt = userdef->user_keyconfig_prefs.first; kpt; kpt = kpt->next) {
1209     writestruct(wd, DATA, wmKeyConfigPref, 1, kpt);
1210     if (kpt->prop) {
1211       IDP_WriteProperty(kpt->prop, wd);
1212     }
1213   }
1214
1215   for (const bUserMenu *um = userdef->user_menus.first; um; um = um->next) {
1216     writestruct(wd, DATA, bUserMenu, 1, um);
1217     for (const bUserMenuItem *umi = um->items.first; umi; umi = umi->next) {
1218       if (umi->type == USER_MENU_TYPE_OPERATOR) {
1219         const bUserMenuItem_Op *umi_op = (const bUserMenuItem_Op *)umi;
1220         writestruct(wd, DATA, bUserMenuItem_Op, 1, umi_op);
1221         if (umi_op->prop) {
1222           IDP_WriteProperty(umi_op->prop, wd);
1223         }
1224       }
1225       else if (umi->type == USER_MENU_TYPE_MENU) {
1226         const bUserMenuItem_Menu *umi_mt = (const bUserMenuItem_Menu *)umi;
1227         writestruct(wd, DATA, bUserMenuItem_Menu, 1, umi_mt);
1228       }
1229       else if (umi->type == USER_MENU_TYPE_PROP) {
1230         const bUserMenuItem_Prop *umi_pr = (const bUserMenuItem_Prop *)umi;
1231         writestruct(wd, DATA, bUserMenuItem_Prop, 1, umi_pr);
1232       }
1233       else {
1234         writestruct(wd, DATA, bUserMenuItem, 1, umi);
1235       }
1236     }
1237   }
1238
1239   for (const bAddon *bext = userdef->addons.first; bext; bext = bext->next) {
1240     writestruct(wd, DATA, bAddon, 1, bext);
1241     if (bext->prop) {
1242       IDP_WriteProperty(bext->prop, wd);
1243     }
1244   }
1245
1246   for (const bPathCompare *path_cmp = userdef->autoexec_paths.first; path_cmp;
1247        path_cmp = path_cmp->next) {
1248     writestruct(wd, DATA, bPathCompare, 1, path_cmp);
1249   }
1250
1251   for (const uiStyle *style = userdef->uistyles.first; style; style = style->next) {
1252     writestruct(wd, DATA, uiStyle, 1, style);
1253   }
1254 }
1255
1256 static void write_boid_state(WriteData *wd, BoidState *state)
1257 {
1258   BoidRule *rule = state->rules.first;
1259
1260   writestruct(wd, DATA, BoidState, 1, state);
1261
1262   for (; rule; rule = rule->next) {
1263     switch (rule->type) {
1264       case eBoidRuleType_Goal:
1265       case eBoidRuleType_Avoid:
1266         writestruct(wd, DATA, BoidRuleGoalAvoid, 1, rule);
1267         break;
1268       case eBoidRuleType_AvoidCollision:
1269         writestruct(wd, DATA, BoidRuleAvoidCollision, 1, rule);
1270         break;
1271       case eBoidRuleType_FollowLeader:
1272         writestruct(wd, DATA, BoidRuleFollowLeader, 1, rule);
1273         break;
1274       case eBoidRuleType_AverageSpeed:
1275         writestruct(wd, DATA, BoidRuleAverageSpeed, 1, rule);
1276         break;
1277       case eBoidRuleType_Fight:
1278         writestruct(wd, DATA, BoidRuleFight, 1, rule);
1279         break;
1280       default:
1281         writestruct(wd, DATA, BoidRule, 1, rule);
1282         break;
1283     }
1284   }
1285 #if 0
1286   BoidCondition *cond = state->conditions.first;
1287   for (; cond; cond = cond->next) {
1288     writestruct(wd, DATA, BoidCondition, 1, cond);
1289   }
1290 #endif
1291 }
1292
1293 /* update this also to readfile.c */
1294 static const char *ptcache_data_struct[] = {
1295     "",          // BPHYS_DATA_INDEX
1296     "",          // BPHYS_DATA_LOCATION
1297     "",          // BPHYS_DATA_VELOCITY
1298     "",          // BPHYS_DATA_ROTATION
1299     "",          // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */
1300     "",          // BPHYS_DATA_SIZE:
1301     "",          // BPHYS_DATA_TIMES:
1302     "BoidData",  // case BPHYS_DATA_BOIDS:
1303 };
1304 static const char *ptcache_extra_struct[] = {
1305     "",
1306     "ParticleSpring",
1307 };
1308 static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
1309 {
1310   PointCache *cache = ptcaches->first;
1311   int i;
1312
1313   for (; cache; cache = cache->next) {
1314     writestruct(wd, DATA, PointCache, 1, cache);
1315
1316     if ((cache->flag & PTCACHE_DISK_CACHE) == 0) {
1317       PTCacheMem *pm = cache->mem_cache.first;
1318
1319       for (; pm; pm = pm->next) {
1320         PTCacheExtra *extra = pm->extradata.first;
1321
1322         writestruct(wd, DATA, PTCacheMem, 1, pm);
1323
1324         for (i = 0; i < BPHYS_TOT_DATA; i++) {
1325           if (pm->data[i] && pm->data_types & (1 << i)) {
1326             if (ptcache_data_struct[i][0] == '\0') {
1327               writedata(wd, DATA, MEM_allocN_len(pm->data[i]), pm->data[i]);
1328             }
1329             else {
1330               writestruct_id(wd, DATA, ptcache_data_struct[i], pm->totpoint, pm->data[i]);
1331             }
1332           }
1333         }
1334
1335         for (; extra; extra = extra->next) {
1336           if (ptcache_extra_struct[extra->type][0] == '\0') {
1337             continue;
1338           }
1339           writestruct(wd, DATA, PTCacheExtra, 1, extra);
1340           writestruct_id(wd, DATA, ptcache_extra_struct[extra->type], extra->totdata, extra->data);
1341         }
1342       }
1343     }
1344   }
1345 }
1346
1347 static void write_particlesettings(WriteData *wd, ParticleSettings *part)
1348 {
1349   if (part->id.us > 0 || wd->use_memfile) {
1350     /* write LibData */
1351     writestruct(wd, ID_PA, ParticleSettings, 1, part);
1352     write_iddata(wd, &part->id);
1353
1354     if (part->adt) {
1355       write_animdata(wd, part->adt);
1356     }
1357     writestruct(wd, DATA, PartDeflect, 1, part->pd);
1358     writestruct(wd, DATA, PartDeflect, 1, part->pd2);
1359     writestruct(wd, DATA, EffectorWeights, 1, part->effector_weights);
1360
1361     if (part->clumpcurve) {
1362       write_curvemapping(wd, part->clumpcurve);
1363     }
1364     if (part->roughcurve) {
1365       write_curvemapping(wd, part->roughcurve);
1366     }
1367     if (part->twistcurve) {
1368       write_curvemapping(wd, part->twistcurve);
1369     }
1370
1371     for (ParticleDupliWeight *dw = part->instance_weights.first; dw; dw = dw->next) {
1372       /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
1373       if (dw->ob != NULL) {
1374         dw->index = 0;
1375         if (part->instance_collection) { /* can be NULL if lining fails or set to None */
1376           FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) {
1377             if (object == dw->ob) {
1378               break;
1379             }
1380             dw->index++;
1381           }
1382           FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
1383         }
1384       }
1385       writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
1386     }
1387
1388     if (part->boids && part->phystype == PART_PHYS_BOIDS) {
1389       writestruct(wd, DATA, BoidSettings, 1, part->boids);
1390
1391       for (BoidState *state = part->boids->states.first; state; state = state->next) {
1392         write_boid_state(wd, state);
1393       }
1394     }
1395     if (part->fluid && part->phystype == PART_PHYS_FLUID) {
1396       writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid);
1397     }
1398
1399     for (int a = 0; a < MAX_MTEX; a++) {
1400       if (part->mtex[a]) {
1401         writestruct(wd, DATA, MTex, 1, part->mtex[a]);
1402       }
1403     }
1404   }
1405 }
1406
1407 static void write_particlesystems(WriteData *wd, ListBase *particles)
1408 {
1409   ParticleSystem *psys = particles->first;
1410   ParticleTarget *pt;
1411   int a;
1412
1413   for (; psys; psys = psys->next) {
1414     writestruct(wd, DATA, ParticleSystem, 1, psys);
1415
1416     if (psys->particles) {
1417       writestruct(wd, DATA, ParticleData, psys->totpart, psys->particles);
1418
1419       if (psys->particles->hair) {
1420         ParticleData *pa = psys->particles;
1421
1422         for (a = 0; a < psys->totpart; a++, pa++) {
1423           writestruct(wd, DATA, HairKey, pa->totkey, pa->hair);
1424         }
1425       }
1426
1427       if (psys->particles->boid && (psys->part->phystype == PART_PHYS_BOIDS)) {
1428         writestruct(wd, DATA, BoidParticle, psys->totpart, psys->particles->boid);
1429       }
1430
1431       if (psys->part->fluid && (psys->part->phystype == PART_PHYS_FLUID) &&
1432           (psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS)) {
1433         writestruct(wd, DATA, ParticleSpring, psys->tot_fluidsprings, psys->fluid_springs);
1434       }
1435     }
1436     pt = psys->targets.first;
1437     for (; pt; pt = pt->next) {
1438       writestruct(wd, DATA, ParticleTarget, 1, pt);
1439     }
1440
1441     if (psys->child) {
1442       writestruct(wd, DATA, ChildParticle, psys->totchild, psys->child);
1443     }
1444
1445     if (psys->clmd) {
1446       writestruct(wd, DATA, ClothModifierData, 1, psys->clmd);
1447       writestruct(wd, DATA, ClothSimSettings, 1, psys->clmd->sim_parms);
1448       writestruct(wd, DATA, ClothCollSettings, 1, psys->clmd->coll_parms);
1449     }
1450
1451     write_pointcaches(wd, &psys->ptcaches);
1452   }
1453 }
1454
1455 static void write_motionpath(WriteData *wd, bMotionPath *mpath)
1456 {
1457   /* sanity checks */
1458   if (mpath == NULL) {
1459     return;
1460   }
1461
1462   /* firstly, just write the motionpath struct */
1463   writestruct(wd, DATA, bMotionPath, 1, mpath);
1464
1465   /* now write the array of data */
1466   writestruct(wd, DATA, bMotionPathVert, mpath->length, mpath->points);
1467 }
1468
1469 static void write_constraints(WriteData *wd, ListBase *conlist)
1470 {
1471   bConstraint *con;
1472
1473   for (con = conlist->first; con; con = con->next) {
1474     const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1475
1476     /* Write the specific data */
1477     if (cti && con->data) {
1478       /* firstly, just write the plain con->data struct */
1479       writestruct_id(wd, DATA, cti->structName, 1, con->data);
1480
1481       /* do any constraint specific stuff */
1482       switch (con->type) {
1483         case CONSTRAINT_TYPE_PYTHON: {
1484           bPythonConstraint *data = con->data;
1485           bConstraintTarget *ct;
1486
1487           /* write targets */
1488           for (ct = data->targets.first; ct; ct = ct->next) {
1489             writestruct(wd, DATA, bConstraintTarget, 1, ct);
1490           }
1491
1492           /* Write ID Properties -- and copy this comment EXACTLY for easy finding
1493            * of library blocks that implement this.*/
1494           IDP_WriteProperty(data->prop, wd);
1495
1496           break;
1497         }
1498         case CONSTRAINT_TYPE_ARMATURE: {
1499           bArmatureConstraint *data = con->data;
1500           bConstraintTarget *ct;
1501
1502           /* write targets */
1503           for (ct = data->targets.first; ct; ct = ct->next) {
1504             writestruct(wd, DATA, bConstraintTarget, 1, ct);
1505           }
1506
1507           break;
1508         }
1509         case CONSTRAINT_TYPE_SPLINEIK: {
1510           bSplineIKConstraint *data = con->data;
1511
1512           /* write points array */
1513           writedata(wd, DATA, sizeof(float) * (data->numpoints), data->points);
1514
1515           break;
1516         }
1517       }
1518     }
1519
1520     /* Write the constraint */
1521     writestruct(wd, DATA, bConstraint, 1, con);
1522   }
1523 }
1524
1525 static void write_pose(WriteData *wd, bPose *pose)
1526 {
1527   bPoseChannel *chan;
1528   bActionGroup *grp;
1529
1530   /* Write each channel */
1531   if (pose == NULL) {
1532     return;
1533   }
1534
1535   /* Write channels */
1536   for (chan = pose->chanbase.first; chan; chan = chan->next) {
1537     /* Write ID Properties -- and copy this comment EXACTLY for easy finding
1538      * of library blocks that implement this.*/
1539     if (chan->prop) {
1540       IDP_WriteProperty(chan->prop, wd);
1541     }
1542
1543     write_constraints(wd, &chan->constraints);
1544
1545     write_motionpath(wd, chan->mpath);
1546
1547     /* prevent crashes with autosave,
1548      * when a bone duplicated in editmode has not yet been assigned to its posechannel */
1549     if (chan->bone) {
1550       /* gets restored on read, for library armatures */
1551       chan->selectflag = chan->bone->flag & BONE_SELECTED;
1552     }
1553
1554     writestruct(wd, DATA, bPoseChannel, 1, chan);
1555   }
1556
1557   /* Write groups */
1558   for (grp = pose->agroups.first; grp; grp = grp->next) {
1559     writestruct(wd, DATA, bActionGroup, 1, grp);
1560   }
1561
1562   /* write IK param */
1563   if (pose->ikparam) {
1564     const char *structname = BKE_pose_ikparam_get_name(pose);
1565     if (structname) {
1566       writestruct_id(wd, DATA, structname, 1, pose->ikparam);
1567     }
1568   }
1569
1570   /* Write this pose */
1571   writestruct(wd, DATA, bPose, 1, pose);
1572 }
1573
1574 static void write_defgroups(WriteData *wd, ListBase *defbase)
1575 {
1576   for (bDeformGroup *defgroup = defbase->first; defgroup; defgroup = defgroup->next) {
1577     writestruct(wd, DATA, bDeformGroup, 1, defgroup);
1578   }
1579 }
1580
1581 static void write_fmaps(WriteData *wd, ListBase *fbase)
1582 {
1583   for (bFaceMap *fmap = fbase->first; fmap; fmap = fmap->next) {
1584     writestruct(wd, DATA, bFaceMap, 1, fmap);
1585   }
1586 }
1587
1588 static void write_modifiers(WriteData *wd, ListBase *modbase)
1589 {
1590   ModifierData *md;
1591
1592   if (modbase == NULL) {
1593     return;
1594   }
1595
1596   for (md = modbase->first; md; md = md->next) {
1597     const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1598     if (mti == NULL) {
1599       return;
1600     }
1601
1602     writestruct_id(wd, DATA, mti->structName, 1, md);
1603
1604     if (md->type == eModifierType_Hook) {
1605       HookModifierData *hmd = (HookModifierData *)md;
1606
1607       if (hmd->curfalloff) {
1608         write_curvemapping(wd, hmd->curfalloff);
1609       }
1610
1611       writedata(wd, DATA, sizeof(int) * hmd->totindex, hmd->indexar);
1612     }
1613     else if (md->type == eModifierType_Cloth) {
1614       ClothModifierData *clmd = (ClothModifierData *)md;
1615
1616       writestruct(wd, DATA, ClothSimSettings, 1, clmd->sim_parms);
1617       writestruct(wd, DATA, ClothCollSettings, 1, clmd->coll_parms);
1618       writestruct(wd, DATA, EffectorWeights, 1, clmd->sim_parms->effector_weights);
1619       write_pointcaches(wd, &clmd->ptcaches);
1620     }
1621     else if (md->type == eModifierType_Smoke) {
1622       SmokeModifierData *smd = (SmokeModifierData *)md;
1623
1624       if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
1625         writestruct(wd, DATA, SmokeDomainSettings, 1, smd->domain);
1626
1627         if (smd->domain) {
1628           write_pointcaches(wd, &(smd->domain->ptcaches[0]));
1629
1630           /* create fake pointcache so that old blender versions can read it */
1631           smd->domain->point_cache[1] = BKE_ptcache_add(&smd->domain->ptcaches[1]);
1632           smd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE | PTCACHE_FAKE_SMOKE;
1633           smd->domain->point_cache[1]->step = 1;
1634
1635           write_pointcaches(wd, &(smd->domain->ptcaches[1]));
1636
1637           if (smd->domain->coba) {
1638             writestruct(wd, DATA, ColorBand, 1, smd->domain->coba);
1639           }
1640
1641           /* cleanup the fake pointcache */
1642           BKE_ptcache_free_list(&smd->domain->ptcaches[1]);
1643           smd->domain->point_cache[1] = NULL;
1644
1645           writestruct(wd, DATA, EffectorWeights, 1, smd->domain->effector_weights);
1646         }
1647       }
1648       else if (smd->type & MOD_SMOKE_TYPE_FLOW) {
1649         writestruct(wd, DATA, SmokeFlowSettings, 1, smd->flow);
1650       }
1651       else if (smd->type & MOD_SMOKE_TYPE_COLL) {
1652         writestruct(wd, DATA, SmokeCollSettings, 1, smd->coll);
1653       }
1654     }
1655     else if (md->type == eModifierType_Fluidsim) {
1656       FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
1657
1658       writestruct(wd, DATA, FluidsimSettings, 1, fluidmd->fss);
1659     }
1660     else if (md->type == eModifierType_DynamicPaint) {
1661       DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
1662
1663       if (pmd->canvas) {
1664         DynamicPaintSurface *surface;
1665         writestruct(wd, DATA, DynamicPaintCanvasSettings, 1, pmd->canvas);
1666
1667         /* write surfaces */
1668         for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
1669           writestruct(wd, DATA, DynamicPaintSurface, 1, surface);
1670         }
1671         /* write caches and effector weights */
1672         for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
1673           write_pointcaches(wd, &(surface->ptcaches));
1674
1675           writestruct(wd, DATA, EffectorWeights, 1, surface->effector_weights);
1676         }
1677       }
1678       if (pmd->brush) {
1679         writestruct(wd, DATA, DynamicPaintBrushSettings, 1, pmd->brush);
1680         writestruct(wd, DATA, ColorBand, 1, pmd->brush->paint_ramp);
1681         writestruct(wd, DATA, ColorBand, 1, pmd->brush->vel_ramp);
1682       }
1683     }
1684     else if (md->type == eModifierType_Collision) {
1685
1686 #if 0
1687       CollisionModifierData *collmd = (CollisionModifierData *)md;
1688       // TODO: CollisionModifier should use pointcache
1689       // + have proper reset events before enabling this
1690       writestruct(wd, DATA, MVert, collmd->numverts, collmd->x);
1691       writestruct(wd, DATA, MVert, collmd->numverts, collmd->xnew);
1692       writestruct(wd, DATA, MFace, collmd->numfaces, collmd->mfaces);
1693 #endif
1694     }
1695     else if (md->type == eModifierType_MeshDeform) {
1696       MeshDeformModifierData *mmd = (MeshDeformModifierData *)md;
1697       int size = mmd->dyngridsize;
1698
1699       writestruct(wd, DATA, MDefInfluence, mmd->totinfluence, mmd->bindinfluences);
1700       writedata(wd, DATA, sizeof(int) * (mmd->totvert + 1), mmd->bindoffsets);
1701       writedata(wd, DATA, sizeof(float) * 3 * mmd->totcagevert, mmd->bindcagecos);
1702       writestruct(wd, DATA, MDefCell, size * size * size, mmd->dyngrid);
1703       writestruct(wd, DATA, MDefInfluence, mmd->totinfluence, mmd->dyninfluences);
1704       writedata(wd, DATA, sizeof(int) * mmd->totvert, mmd->dynverts);
1705     }
1706     else if (md->type == eModifierType_Warp) {
1707       WarpModifierData *tmd = (WarpModifierData *)md;
1708       if (tmd->curfalloff) {
1709         write_curvemapping(wd, tmd->curfalloff);
1710       }
1711     }
1712     else if (md->type == eModifierType_WeightVGEdit) {
1713       WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md;
1714
1715       if (wmd->cmap_curve) {
1716         write_curvemapping(wd, wmd->cmap_curve);
1717       }
1718     }
1719     else if (md->type == eModifierType_LaplacianDeform) {
1720       LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md;
1721
1722       writedata(wd, DATA, sizeof(float) * lmd->total_verts * 3, lmd->vertexco);
1723     }
1724     else if (md->type == eModifierType_CorrectiveSmooth) {
1725       CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
1726
1727       if (csmd->bind_coords) {
1728         writedata(wd, DATA, sizeof(float[3]) * csmd->bind_coords_num, csmd->bind_coords);
1729       }
1730     }
1731     else if (md->type == eModifierType_SurfaceDeform) {
1732       SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
1733
1734       writestruct(wd, DATA, SDefVert, smd->numverts, smd->verts);
1735
1736       if (smd->verts) {
1737         for (int i = 0; i < smd->numverts; i++) {
1738           writestruct(wd, DATA, SDefBind, smd->verts[i].numbinds, smd->verts[i].binds);
1739
1740           if (smd->verts[i].binds) {
1741             for (int j = 0; j < smd->verts[i].numbinds; j++) {
1742               writedata(wd,
1743                         DATA,
1744                         sizeof(int) * smd->verts[i].binds[j].numverts,
1745                         smd->verts[i].binds[j].vert_inds);
1746
1747               if (smd->verts[i].binds[j].mode == MOD_SDEF_MODE_CENTROID ||
1748                   smd->verts[i].binds[j].mode == MOD_SDEF_MODE_LOOPTRI) {
1749                 writedata(wd, DATA, sizeof(float) * 3, smd->verts[i].binds[j].vert_weights);
1750               }
1751               else {
1752                 writedata(wd,
1753                           DATA,
1754                           sizeof(float) * smd->verts[i].binds[j].numverts,
1755                           smd->verts[i].binds[j].vert_weights);
1756               }
1757             }
1758           }
1759         }
1760       }
1761     }
1762   }
1763 }
1764
1765 static void write_gpencil_modifiers(WriteData *wd, ListBase *modbase)
1766 {
1767   GpencilModifierData *md;
1768
1769   if (modbase == NULL) {
1770     return;
1771   }
1772
1773   for (md = modbase->first; md; md = md->next) {
1774     const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
1775     if (mti == NULL) {
1776       return;
1777     }
1778
1779     writestruct_id(wd, DATA, mti->struct_name, 1, md);
1780
1781     if (md->type == eGpencilModifierType_Thick) {
1782       ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
1783
1784       if (gpmd->curve_thickness) {
1785         write_curvemapping(wd, gpmd->curve_thickness);
1786       }
1787     }
1788     else if (md->type == eGpencilModifierType_Hook) {
1789       HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md;
1790
1791       if (gpmd->curfalloff) {
1792         write_curvemapping(wd, gpmd->curfalloff);
1793       }
1794     }
1795   }
1796 }
1797
1798 static void write_shaderfxs(WriteData *wd, ListBase *fxbase)
1799 {
1800   ShaderFxData *fx;
1801
1802   if (fxbase == NULL) {
1803     return;
1804   }
1805
1806   for (fx = fxbase->first; fx; fx = fx->next) {
1807     const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type);
1808     if (fxi == NULL) {
1809       return;
1810     }
1811
1812     writestruct_id(wd, DATA, fxi->struct_name, 1, fx);
1813   }
1814 }
1815
1816 static void write_object(WriteData *wd, Object *ob)
1817 {
1818   if (ob->id.us > 0 || wd->use_memfile) {
1819     /* write LibData */
1820     writestruct(wd, ID_OB, Object, 1, ob);
1821     write_iddata(wd, &ob->id);
1822
1823     if (ob->adt) {
1824       write_animdata(wd, ob->adt);
1825     }
1826
1827     /* direct data */
1828     writedata(wd, DATA, sizeof(void *) * ob->totcol, ob->mat);
1829     writedata(wd, DATA, sizeof(char) * ob->totcol, ob->matbits);
1830     /* write_effects(wd, &ob->effect); */ /* not used anymore */
1831
1832     if (ob->type == OB_ARMATURE) {
1833       bArmature *arm = ob->data;
1834       if (arm && ob->pose && arm->act_bone) {
1835         BLI_strncpy(
1836             ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone));
1837       }
1838     }
1839
1840     write_pose(wd, ob->pose);
1841     write_defgroups(wd, &ob->defbase);
1842     write_fmaps(wd, &ob->fmaps);
1843     write_constraints(wd, &ob->constraints);
1844     write_motionpath(wd, ob->mpath);
1845
1846     writestruct(wd, DATA, PartDeflect, 1, ob->pd);
1847     if (ob->soft) {
1848       /* Set deprecated pointers to prevent crashes of older Blenders */
1849       ob->soft->pointcache = ob->soft->shared->pointcache;
1850       ob->soft->ptcaches = ob->soft->shared->ptcaches;
1851       writestruct(wd, DATA, SoftBody, 1, ob->soft);
1852       writestruct(wd, DATA, SoftBody_Shared, 1, ob->soft->shared);
1853       write_pointcaches(wd, &(ob->soft->shared->ptcaches));
1854       writestruct(wd, DATA, EffectorWeights, 1, ob->soft->effector_weights);
1855     }
1856
1857     if (ob->rigidbody_object) {
1858       /* TODO: if any extra data is added to handle duplis, will need separate function then */
1859       writestruct(wd, DATA, RigidBodyOb, 1, ob->rigidbody_object);
1860     }
1861     if (ob->rigidbody_constraint) {
1862       writestruct(wd, DATA, RigidBodyCon, 1, ob->rigidbody_constraint);
1863     }
1864
1865     if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
1866       writestruct(wd, DATA, ImageUser, 1, ob->iuser);
1867     }
1868
1869     write_particlesystems(wd, &ob->particlesystem);
1870     write_modifiers(wd, &ob->modifiers);
1871     write_gpencil_modifiers(wd, &ob->greasepencil_modifiers);
1872     write_shaderfxs(wd, &ob->shader_fx);
1873
1874     writelist(wd, DATA, LinkData, &ob->pc_ids);
1875     writelist(wd, DATA, LodLevel, &ob->lodlevels);
1876
1877     write_previews(wd, ob->preview);
1878   }
1879 }
1880
1881 static void write_vfont(WriteData *wd, VFont *vf)
1882 {
1883   if (vf->id.us > 0 || wd->use_memfile) {
1884     /* write LibData */
1885     writestruct(wd, ID_VF, VFont, 1, vf);
1886     write_iddata(wd, &vf->id);
1887
1888     /* direct data */
1889     if (vf->packedfile) {
1890       PackedFile *pf = vf->packedfile;
1891       writestruct(wd, DATA, PackedFile, 1, pf);
1892       writedata(wd, DATA, pf->size, pf->data);
1893     }
1894   }
1895 }
1896
1897 static void write_key(WriteData *wd, Key *key)
1898 {
1899   if (key->id.us > 0 || wd->use_memfile) {
1900     /* write LibData */
1901     writestruct(wd, ID_KE, Key, 1, key);
1902     write_iddata(wd, &key->id);
1903
1904     if (key->adt) {
1905       write_animdata(wd, key->adt);
1906     }
1907
1908     /* direct data */
1909     for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
1910       writestruct(wd, DATA, KeyBlock, 1, kb);
1911       if (kb->data) {
1912         writedata(wd, DATA, kb->totelem * key->elemsize, kb->data);
1913       }
1914     }
1915   }
1916 }
1917
1918 static void write_camera(WriteData *wd, Camera *cam)
1919 {
1920   if (cam->id.us > 0 || wd->use_memfile) {
1921     /* write LibData */
1922     writestruct(wd, ID_CA, Camera, 1, cam);
1923     write_iddata(wd, &cam->id);
1924
1925     if (cam->adt) {
1926       write_animdata(wd, cam->adt);
1927     }
1928
1929     for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
1930       writestruct(wd, DATA, CameraBGImage, 1, bgpic);
1931     }
1932   }
1933 }
1934
1935 static void write_mball(WriteData *wd, MetaBall *mb)
1936 {
1937   if (mb->id.us > 0 || wd->use_memfile) {
1938     /* write LibData */
1939     writestruct(wd, ID_MB, MetaBall, 1, mb);
1940     write_iddata(wd, &mb->id);
1941
1942     /* direct data */
1943     writedata(wd, DATA, sizeof(void *) * mb->totcol, mb->mat);
1944     if (mb->adt) {
1945       write_animdata(wd, mb->adt);
1946     }
1947
1948     for (MetaElem *ml = mb->elems.first; ml; ml = ml->next) {
1949       writestruct(wd, DATA, MetaElem, 1, ml);
1950     }
1951   }
1952 }
1953
1954 static void write_curve(WriteData *wd, Curve *cu)
1955 {
1956   if (cu->id.us > 0 || wd->use_memfile) {
1957     /* write LibData */
1958     writestruct(wd, ID_CU, Curve, 1, cu);
1959     write_iddata(wd, &cu->id);
1960
1961     /* direct data */
1962     writedata(wd, DATA, sizeof(void *) * cu->totcol, cu->mat);
1963     if (cu->adt) {
1964       write_animdata(wd, cu->adt);
1965     }
1966
1967     if (cu->vfont) {
1968       writedata(wd, DATA, cu->len + 1, cu->str);
1969       writestruct(wd, DATA, CharInfo, cu->len_wchar + 1, cu->strinfo);
1970       writestruct(wd, DATA, TextBox, cu->totbox, cu->tb);
1971     }
1972     else {
1973       /* is also the order of reading */
1974       for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
1975         writestruct(wd, DATA, Nurb, 1, nu);
1976       }
1977       for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
1978         if (nu->type == CU_BEZIER) {
1979           writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt);
1980         }
1981         else {
1982           writestruct(wd, DATA, BPoint, nu->pntsu * nu->pntsv, nu->bp);
1983           if (nu->knotsu) {
1984             writedata(wd, DATA, KNOTSU(nu) * sizeof(float), nu->knotsu);
1985           }
1986           if (nu->knotsv) {
1987             writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv);
1988           }
1989         }
1990       }
1991     }
1992   }
1993 }
1994
1995 static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist)
1996 {
1997   if (dvlist) {
1998
1999     /* Write the dvert list */
2000     writestruct(wd, DATA, MDeformVert, count, dvlist);
2001
2002     /* Write deformation data for each dvert */
2003     for (int i = 0; i < count; i++) {
2004       if (dvlist[i].dw) {
2005         writestruct(wd, DATA, MDeformWeight, dvlist[i].totweight, dvlist[i].dw);
2006       }
2007     }
2008   }
2009 }
2010
2011 static void write_mdisps(WriteData *wd, int count, MDisps *mdlist, int external)
2012 {
2013   if (mdlist) {
2014     int i;
2015
2016     writestruct(wd, DATA, MDisps, count, mdlist);
2017     for (i = 0; i < count; ++i) {
2018       MDisps *md = &mdlist[i];
2019       if (md->disps) {
2020         if (!external) {
2021           writedata(wd, DATA, sizeof(float) * 3 * md->totdisp, md->disps);
2022         }
2023       }
2024
2025       if (md->hidden) {
2026         writedata(wd, DATA, BLI_BITMAP_SIZE(md->totdisp), md->hidden);
2027       }
2028     }
2029   }
2030 }
2031
2032 static void write_grid_paint_mask(WriteData *wd, int count, GridPaintMask *grid_paint_mask)
2033 {
2034   if (grid_paint_mask) {
2035     int i;
2036
2037     writestruct(wd, DATA, GridPaintMask, count, grid_paint_mask);
2038     for (i = 0; i < count; ++i) {
2039       GridPaintMask *gpm = &grid_paint_mask[i];
2040       if (gpm->data) {
2041         const int gridsize = BKE_ccg_gridsize(gpm->level);
2042         writedata(wd, DATA, sizeof(*gpm->data) * gridsize * gridsize, gpm->data);
2043       }
2044     }
2045   }
2046 }
2047
2048 static void write_customdata(WriteData *wd,
2049                              ID *id,
2050                              int count,
2051                              CustomData *data,
2052                              CustomDataLayer *layers,
2053                              CustomDataMask cddata_mask,
2054                              int partial_type,
2055                              int partial_count)
2056 {
2057   int i;
2058
2059   /* write external customdata (not for undo) */
2060   if (data->external && (wd->use_memfile == false)) {
2061     CustomData_external_write(data, id, cddata_mask, count, 0);
2062   }
2063
2064   writestruct_at_address(wd, DATA, CustomDataLayer, data->totlayer, data->layers, layers);
2065
2066   for (i = 0; i < data->totlayer; i++) {
2067     CustomDataLayer *layer = &layers[i];
2068     const char *structname;
2069     int structnum, datasize;
2070
2071     if (layer->type == CD_MDEFORMVERT) {
2072       /* layer types that allocate own memory need special handling */
2073       write_dverts(wd, count, layer->data);
2074     }
2075     else if (layer->type == CD_MDISPS) {
2076       write_mdisps(wd, count, layer->data, layer->flag & CD_FLAG_EXTERNAL);
2077     }
2078     else if (layer->type == CD_PAINT_MASK) {
2079       const float *layer_data = layer->data;
2080       writedata(wd, DATA, sizeof(*layer_data) * count, layer_data);
2081     }
2082     else if (layer->type == CD_GRID_PAINT_MASK) {
2083       write_grid_paint_mask(wd, count, layer->data);
2084     }
2085     else if (layer->type == CD_FACEMAP) {
2086       const int *layer_data = layer->data;
2087       writedata(wd, DATA, sizeof(*layer_data) * count, layer_data);
2088     }
2089     else {
2090       CustomData_file_write_info(layer->type, &structname, &structnum);
2091       if (structnum) {
2092         /* when using partial visibility, the MEdge and MFace layers
2093          * are smaller than the original, so their type and count is
2094          * passed to make this work */
2095         if (layer->type != partial_type) {
2096           datasize = structnum * count;
2097         }
2098         else {
2099           datasize = structnum * partial_count;
2100         }
2101
2102         writestruct_id(wd, DATA, structname, datasize, layer->data);
2103       }
2104       else {
2105         printf("%s error: layer '%s':%d - can't be written to file\n",
2106                __func__,
2107                structname,
2108                layer->type);
2109       }
2110     }
2111   }
2112
2113   if (data->external) {
2114     writestruct(wd, DATA, CustomDataExternal, 1, data->external);
2115   }
2116 }
2117
2118 static void write_mesh(WriteData *wd, Mesh *mesh)
2119 {
2120   CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
2121   CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
2122   CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
2123   CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE];
2124   CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
2125
2126   if (mesh->id.us > 0 || wd->use_memfile) {
2127     /* write LibData */
2128     {
2129       /* write a copy of the mesh, don't modify in place because it is
2130        * not thread safe for threaded renders that are reading this */
2131       Mesh *old_mesh = mesh;
2132       Mesh copy_mesh = *mesh;
2133       mesh = &copy_mesh;
2134
2135       /* cache only - don't write */
2136       mesh->mface = NULL;
2137       mesh->totface = 0;
2138       memset(&mesh->fdata, 0, sizeof(mesh->fdata));
2139
2140       /**
2141        * Those calls:
2142        * - Reduce mesh->xdata.totlayer to number of layers to write.
2143        * - Fill xlayers with those layers to be written.
2144        * Note that mesh->xdata is from now on invalid for Blender,
2145        * but this is why the whole mesh is a temp local copy!
2146        */
2147       CustomData_file_write_prepare(
2148           &mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
2149       CustomData_file_write_prepare(
2150           &mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
2151       flayers = flayers_buff;
2152       CustomData_file_write_prepare(
2153           &mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
2154       CustomData_file_write_prepare(
2155           &mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
2156
2157       writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh);
2158       write_iddata(wd, &mesh->id);
2159
2160       /* direct data */
2161       if (mesh->adt) {
2162         write_animdata(wd, mesh->adt);
2163       }
2164
2165       writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat);
2166       writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect);
2167
2168       write_customdata(
2169           wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, CD_MASK_MESH.vmask, -1, 0);
2170       write_customdata(
2171           wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, CD_MASK_MESH.emask, -1, 0);
2172       /* fdata is really a dummy - written so slots align */
2173       write_customdata(
2174           wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, CD_MASK_MESH.fmask, -1, 0);
2175       write_customdata(
2176           wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, CD_MASK_MESH.lmask, -1, 0);
2177       write_customdata(
2178           wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, CD_MASK_MESH.pmask, -1, 0);
2179
2180       /* restore pointer */
2181       mesh = old_mesh;
2182     }
2183   }
2184
2185   if (vlayers && vlayers != vlayers_buff) {
2186     MEM_freeN(vlayers);
2187   }
2188   if (elayers && elayers != elayers_buff) {
2189     MEM_freeN(elayers);
2190   }
2191   if (flayers && flayers != flayers_buff) {
2192     MEM_freeN(flayers);
2193   }
2194   if (llayers && llayers != llayers_buff) {
2195     MEM_freeN(llayers);
2196   }
2197   if (players && players != players_buff) {
2198     MEM_freeN(players);
2199   }
2200 }
2201
2202 static void write_lattice(WriteData *wd, Lattice *lt)
2203 {
2204   if (lt->id.us > 0 || wd->use_memfile) {
2205     /* write LibData */
2206     writestruct(wd, ID_LT, Lattice, 1, lt);
2207     write_iddata(wd, &lt->id);
2208
2209     /* write animdata */
2210     if (lt->adt) {
2211       write_animdata(wd, lt->adt);
2212     }
2213
2214     /* direct data */
2215     writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
2216
2217     write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
2218   }
2219 }
2220
2221 static void write_image(WriteData *wd, Image *ima)
2222 {
2223   if (ima->id.us > 0 || wd->use_memfile) {
2224     ImagePackedFile *imapf;
2225
2226     /* Some trickery to keep forward compatibility of packed images. */
2227     BLI_assert(ima->packedfile == NULL);
2228     if (ima->packedfiles.first != NULL) {
2229       imapf = ima->packedfiles.first;
2230       ima->packedfile = imapf->packedfile;
2231     }
2232
2233     /* write LibData */
2234     writestruct(wd, ID_IM, Image, 1, ima);
2235     write_iddata(wd, &ima->id);
2236
2237     for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
2238       writestruct(wd, DATA, ImagePackedFile, 1, imapf);
2239       if (imapf->packedfile) {
2240         PackedFile *pf = imapf->packedfile;
2241         writestruct(wd, DATA, PackedFile, 1, pf);
2242         writedata(wd, DATA, pf->size, pf->data);
2243       }
2244     }
2245
2246     write_previews(wd, ima->preview);
2247
2248     for (ImageView *iv = ima->views.first; iv; iv = iv->next) {
2249       writestruct(wd, DATA, ImageView, 1, iv);
2250     }
2251     writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format);
2252
2253     ima->packedfile = NULL;
2254
2255     writelist(wd, DATA, RenderSlot, &ima->renderslots);
2256   }
2257 }
2258
2259 static void write_texture(WriteData *wd, Tex *tex)
2260 {
2261   if (tex->id.us > 0 || wd->use_memfile) {
2262     /* write LibData */
2263     writestruct(wd, ID_TE, Tex, 1, tex);
2264     write_iddata(wd, &tex->id);
2265
2266     if (tex->adt) {
2267       write_animdata(wd, tex->adt);
2268     }
2269
2270     /* direct data */
2271     if (tex->coba) {
2272       writestruct(wd, DATA, ColorBand, 1, tex->coba);
2273     }
2274
2275     /* nodetree is integral part of texture, no libdata */
2276     if (tex->nodetree) {
2277       writestruct(wd, DATA, bNodeTree, 1, tex->nodetree);
2278       write_nodetree_nolib(wd, tex->nodetree);
2279     }
2280
2281     write_previews(wd, tex->preview);
2282   }
2283 }
2284
2285 static void write_material(WriteData *wd, Material *ma)
2286 {
2287   if (ma->id.us > 0 || wd->use_memfile) {
2288     /* write LibData */
2289     writestruct(wd, ID_MA, Material, 1, ma);
2290     write_iddata(wd, &ma->id);
2291
2292     if (ma->adt) {
2293       write_animdata(wd, ma->adt);
2294     }
2295
2296     /* nodetree is integral part of material, no libdata */
2297     if (ma->nodetree) {
2298       writestruct(wd, DATA, bNodeTree, 1, ma->nodetree);
2299       write_nodetree_nolib(wd, ma->nodetree);
2300     }
2301
2302     write_previews(wd, ma->preview);
2303
2304     /* grease pencil settings */
2305     if (ma->gp_style) {
2306       writestruct(wd, DATA, MaterialGPencilStyle, 1, ma->gp_style);
2307     }
2308   }
2309 }
2310
2311 static void write_world(WriteData *wd, World *wrld)
2312 {
2313   if (wrld->id.us > 0 || wd->use_memfile) {
2314     /* write LibData */
2315     writestruct(wd, ID_WO, World, 1, wrld);
2316     write_iddata(wd, &wrld->id);
2317
2318     if (wrld->adt) {
2319       write_animdata(wd, wrld->adt);
2320     }
2321
2322     /* nodetree is integral part of world, no libdata */
2323     if (wrld->nodetree) {
2324       writestruct(wd, DATA, bNodeTree, 1, wrld->nodetree);
2325       write_nodetree_nolib(wd, wrld->nodetree);
2326     }
2327
2328     write_previews(wd, wrld->preview);
2329   }
2330 }
2331
2332 static void write_light(WriteData *wd, Light *la)
2333 {
2334   if (la->id.us > 0 || wd->use_memfile) {
2335     /* write LibData */
2336     writestruct(wd, ID_LA, Light, 1, la);
2337     write_iddata(wd, &la->id);
2338
2339     if (la->adt) {
2340       write_animdata(wd, la->adt);
2341     }
2342
2343     if (la->curfalloff) {
2344       write_curvemapping(wd, la->curfalloff);
2345     }
2346
2347     /* Node-tree is integral part of lights, no libdata. */
2348     if (la->nodetree) {
2349       writestruct(wd, DATA, bNodeTree, 1, la->nodetree);
2350       write_nodetree_nolib(wd, la->nodetree);
2351     }
2352
2353     write_previews(wd, la->preview);
2354   }
2355 }
2356
2357 static void write_collection_nolib(WriteData *wd, Collection *collection)
2358 {
2359   /* Shared function for collection data-blocks and scene master collection. */
2360   write_previews(wd, collection->preview);
2361
2362   for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
2363     writestruct(wd, DATA, CollectionObject, 1, cob);
2364   }
2365
2366   for (CollectionChild *child = collection->children.first; child; child = child->next) {
2367     writestruct(wd, DATA, CollectionChild, 1, child);
2368   }
2369 }
2370
2371 static void write_collection(WriteData *wd, Collection *collection)
2372 {
2373   if (collection->id.us > 0 || wd->use_memfile) {
2374     /* write LibData */
2375     writestruct(wd, ID_GR, Collection, 1, collection);
2376     write_iddata(wd, &collection->id);
2377
2378     write_collection_nolib(wd, collection);
2379   }
2380 }
2381
2382 static void write_sequence_modifiers(WriteData *wd, ListBase *modbase)
2383 {
2384   SequenceModifierData *smd;
2385
2386   for (smd = modbase->first; smd; smd = smd->next) {
2387     const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
2388
2389     if (smti) {
2390       writestruct_id(wd, DATA, smti->struct_name, 1, smd);
2391
2392       if (smd->type == seqModifierType_Curves) {
2393         CurvesModifierData *cmd = (CurvesModifierData *)smd;
2394
2395         write_curvemapping(wd, &cmd->curve_mapping);
2396       }
2397       else if (smd->type == seqModifierType_HueCorrect) {
2398         HueCorrectModifierData *hcmd = (HueCorrectModifierData *)smd;
2399
2400         write_curvemapping(wd, &hcmd->curve_mapping);
2401       }
2402     }
2403     else {
2404       writestruct(wd, DATA, SequenceModifierData, 1, smd);
2405     }
2406   }
2407 }
2408
2409 static void write_view_settings(WriteData *wd, ColorManagedViewSettings *view_settings)
2410 {
2411   if (view_settings->curve_mapping) {
2412     write_curvemapping(wd, view_settings->curve_mapping);
2413   }
2414 }
2415
2416 static void write_paint(WriteData *wd, Paint *p)
2417 {
2418   if (p->cavity_curve) {
2419     write_curvemapping(wd, p->cavity_curve);
2420   }
2421   writestruct(wd, DATA, PaintToolSlot, p->tool_slots_len, p->tool_slots);
2422 }
2423
2424 static void write_layer_collections(WriteData *wd, ListBase *lb)
2425 {
2426   for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
2427     writestruct(wd, DATA, LayerCollection, 1, lc);
2428
2429     write_layer_collections(wd, &lc->layer_collections);
2430   }
2431 }
2432
2433 static void write_view_layer(WriteData *wd, ViewLayer *view_layer)
2434 {
2435   writestruct(wd, DATA, ViewLayer, 1, view_layer);
2436   writelist(wd, DATA, Base, &view_layer->object_bases);
2437
2438   if (view_layer->id_properties) {
2439     IDP_WriteProperty(view_layer->id_properties, wd);
2440   }
2441
2442   for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc;
2443        fmc = fmc->next) {
2444     writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
2445   }
2446
2447   for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) {
2448     writestruct(wd, DATA, FreestyleLineSet, 1, fls);
2449   }
2450   write_layer_collections(wd, &view_layer->layer_collections);
2451 }
2452
2453 static void write_lightcache_texture(WriteData *wd, LightCacheTexture *tex)
2454 {
2455   if (tex->data) {
2456     size_t data_size = tex->components * tex->tex_size[0] * tex->tex_size[1] * tex->tex_size[2];
2457     if (tex->data_type == LIGHTCACHETEX_FLOAT) {
2458       data_size *= sizeof(float);
2459     }
2460     else if (tex->data_type == LIGHTCACHETEX_UINT) {
2461       data_size *= sizeof(uint);
2462     }
2463     writedata(wd, DATA, data_size, tex->data);
2464   }
2465 }
2466
2467 static void write_lightcache(WriteData *wd, LightCache *cache)
2468 {
2469   write_lightcache_texture(wd, &cache->grid_tx);
2470   write_lightcache_texture(wd, &cache->cube_tx);
2471
2472   if (cache->cube_mips) {
2473     writestruct(wd, DATA, LightCacheTexture, cache->mips_len, cache->cube_mips);
2474     for (int i = 0; i < cache->mips_len; ++i) {
2475       write_lightcache_texture(wd, &cache->cube_mips[i]);
2476     }
2477   }
2478
2479   writestruct(wd, DATA, LightGridCache, cache->grid_len, cache->grid_data);
2480   writestruct(wd, DATA, LightProbeCache, cache->cube_len, cache->cube_data);
2481 }
2482
2483 static void write_scene(WriteData *wd, Scene *sce)
2484 {
2485   /* write LibData */
2486   writestruct(wd, ID_SCE, Scene, 1, sce);
2487   write_iddata(wd, &sce->id);
2488
2489   if (sce->adt) {
2490     write_animdata(wd, sce->adt);
2491   }
2492   write_keyingsets(wd, &sce->keyingsets);
2493
2494   /* direct data */
2495   ToolSettings *tos = sce->toolsettings;
2496   writestruct(wd, DATA, ToolSettings, 1, tos);
2497   if (tos->vpaint) {
2498     writestruct(wd, DATA, VPaint, 1, tos->vpaint);
2499     write_paint(wd, &tos->vpaint->paint);
2500   }
2501   if (tos->wpaint) {
2502     writestruct(wd, DATA, VPaint, 1, tos->wpaint);
2503     write_paint(wd, &tos->wpaint->paint);
2504   }
2505   if (tos->sculpt) {
2506     writestruct(wd, DATA, Sculpt, 1, tos->sculpt);
2507     write_paint(wd, &tos->sculpt->paint);
2508   }
2509   if (tos->uvsculpt) {
2510     writestruct(wd, DATA, UvSculpt, 1, tos->uvsculpt);
2511     write_paint(wd, &tos->uvsculpt->paint);
2512   }
2513   if (tos->gp_paint) {
2514     writestruct(wd, DATA, GpPaint, 1, tos->gp_paint);
2515     write_paint(wd, &tos->gp_paint->paint);
2516   }
2517   /* write grease-pencil custom ipo curve to file */
2518   if (tos->gp_interpolate.custom_ipo) {
2519     write_curvemapping(wd, tos->gp_interpolate.custom_ipo);
2520   }
2521   /* write grease-pencil multiframe falloff curve to file */
2522   if (tos->gp_sculpt.cur_falloff) {
2523     write_curvemapping(wd, tos->gp_sculpt.cur_falloff);
2524   }
2525   /* write grease-pencil primitive curve to file */
2526   if (tos->gp_sculpt.cur_primitive) {
2527     write_curvemapping(wd, tos->gp_sculpt.cur_primitive);
2528   }
2529
2530   write_paint(wd, &tos->imapaint.paint);
2531
2532   Editing *ed = sce->ed;
2533   if (ed) {
2534     Sequence *seq;
2535
2536     writestruct(wd, DATA, Editing, 1, ed);
2537
2538     /* reset write flags too */
2539
2540     SEQ_BEGIN (ed, seq) {
2541       if (seq->strip) {
2542         seq->strip->done = false;
2543       }
2544       writestruct(wd, DATA, Sequence, 1, seq);
2545     }
2546     SEQ_END;
2547
2548     SEQ_BEGIN (ed, seq) {
2549       if (seq->strip && seq->strip->done == 0) {
2550         /* write strip with 'done' at 0 because readfile */
2551
2552         if (seq->effectdata) {
2553           switch (seq->type) {
2554             case SEQ_TYPE_COLOR:
2555               writestruct(wd, DATA, SolidColorVars, 1, seq->effectdata);
2556               break;
2557             case SEQ_TYPE_SPEED:
2558               writestruct(wd, DATA, SpeedControlVars, 1, seq->effectdata);
2559               break;
2560             case SEQ_TYPE_WIPE:
2561               writestruct(wd, DATA, WipeVars, 1, seq->effectdata);
2562               break;
2563             case SEQ_TYPE_GLOW:
2564               writestruct(wd, DATA, GlowVars, 1, seq->effectdata);
2565               break;
2566             case SEQ_TYPE_TRANSFORM:
2567               writestruct(wd, DATA, TransformVars, 1, seq->effectdata);
2568               break;
2569             case SEQ_TYPE_GAUSSIAN_BLUR:
2570               writestruct(wd, DATA, GaussianBlurVars, 1, seq->effectdata);
2571               break;
2572             case SEQ_TYPE_TEXT:
2573               writestruct(wd, DATA, TextVars, 1, seq->effectdata);
2574               break;
2575             case SEQ_TYPE_COLORMIX:
2576               writestruct(wd, DATA, ColorMixVars, 1, seq->effectdata);
2577               break;
2578           }
2579         }
2580
2581         writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format);
2582
2583         Strip *strip = seq->strip;
2584         writestruct(wd, DATA, Strip, 1, strip);
2585         if (strip->crop) {
2586           writestruct(wd, DATA, StripCrop, 1, strip->crop);
2587         }
2588         if (strip->transform) {
2589           writestruct(wd, DATA, StripTransform, 1, strip->transform);
2590         }
2591         if (strip->proxy) {
2592           writestruct(wd, DATA, StripProxy, 1, strip->proxy);
2593         }
2594         if (seq->type == SEQ_TYPE_IMAGE) {
2595           writestruct(wd,
2596                       DATA,
2597                       StripElem,
2598                       MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem),
2599                       strip->stripdata);
2600         }
2601         else if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
2602           writestruct(wd, DATA, StripElem, 1, strip->stripdata);
2603         }
2604
2605         strip->done = true;
2606       }
2607
2608       if (seq->prop) {
2609         IDP_WriteProperty(seq->prop, wd);
2610       }
2611
2612       write_sequence_modifiers(wd, &seq->modifiers);
2613     }
2614     SEQ_END;
2615
2616     /* new; meta stack too, even when its nasty restore code */
2617     for (MetaStack *ms = ed->metastack.first; ms; ms = ms->next) {
2618       writestruct(wd, DATA, MetaStack, 1, ms);
2619     }
2620   }
2621
2622   if (sce->r.avicodecdata) {
2623     writestruct(wd, DATA, AviCodecData, 1, sce->r.avicodecdata);
2624     if (sce->r.avicodecdata->lpFormat) {
2625       writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
2626     }
2627     if (sce->r.avicodecdata->lpParms) {
2628       writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms);
2629     }
2630   }
2631   if (sce->r.ffcodecdata.properties) {
2632     IDP_WriteProperty(sce->r.ffcodecdata.properties, wd);
2633   }
2634
2635   /* writing dynamic list of TimeMarkers to the blend file */
2636   for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) {
2637     writestruct(wd, DATA, TimeMarker, 1, marker);
2638   }
2639
2640   /* writing dynamic list of TransformOrientations to the blend file */
2641   for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) {
2642     writestruct(wd, DATA, TransformOrientation, 1, ts);
2643   }
2644
2645   /* writing MultiView to the blend file */
2646   for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) {
2647     writestruct(wd, DATA, SceneRenderView, 1, srv);
2648   }
2649
2650   if (sce->nodetree) {
2651     writestruct(wd, DATA, bNodeTree, 1, sce->nodetree);
2652     write_nodetree_nolib(wd, sce->nodetree);
2653   }
2654
2655   write_view_settings(wd, &sce->view_settings);
2656
2657   /* writing RigidBodyWorld data to the blend file */
2658   if (sce->rigidbody_world) {
2659     /* Set deprecated pointers to prevent crashes of older Blenders */
2660     sce->rigidbody_world->pointcache = sce->rigidbody_world->shared->pointcache;
2661     sce->rigidbody_world->ptcaches = sce->rigidbody_world->shared->ptcaches;
2662     writestruct(wd, DATA, RigidBodyWorld, 1, sce->rigidbody_world);
2663
2664     writestruct(wd, DATA, RigidBodyWorld_Shared, 1, sce->rigidbody_world->shared);
2665     writestruct(wd, DATA, EffectorWeights, 1, sce->rigidbody_world->effector_weights);
2666     write_pointcaches(wd, &(sce->rigidbody_world->shared->ptcaches));
2667   }
2668
2669   write_previews(wd, sce->preview);
2670   write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
2671
2672   for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
2673     write_view_layer(wd, view_layer);
2674   }
2675
2676   if (sce->master_collection) {
2677     writestruct(wd, DATA, Collection, 1, sce->master_collection);
2678     write_collection_nolib(wd, sce->master_collection);
2679   }
2680
2681   /* Eevee Lightcache */
2682   if (sce->eevee.light_cache && !wd->use_memfile) {
2683     writestruct(wd, DATA, LightCache, 1, sce->eevee.light_cache);
2684     write_lightcache(wd, sce->eevee.light_cache);
2685   }
2686
2687   /* Freed on doversion. */
2688   BLI_assert(sce->layer_properties == NULL);
2689 }
2690
2691 static void write_gpencil(WriteData *wd, bGPdata *gpd)
2692 {
2693   if (gpd->id.us > 0 || wd->use_memfile) {
2694     /* write gpd data block to file */
2695     writestruct(wd, ID_GD, bGPdata, 1, gpd);
2696     write_iddata(wd, &gpd->id);
2697
2698     if (gpd->adt) {
2699       write_animdata(wd, gpd->adt);
2700     }
2701
2702     writedata(wd, DATA, sizeof(void *) * gpd->totcol, gpd->mat);
2703
2704     /* write grease-pencil layers to file */
2705     writelist(wd, DATA, bGPDlayer, &gpd->layers);
2706     for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
2707       /* write this layer's frames to file */
2708       writelist(wd, DATA, bGPDframe, &gpl->frames);
2709       for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
2710         /* write strokes */
2711         writelist(wd, DATA, bGPDstroke, &gpf->strokes);
2712         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
2713           writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points);
2714           write_dverts(wd, gps->totpoints, gps->dvert);
2715         }
2716       }
2717     }
2718   }
2719 }
2720
2721 static void write_region(WriteData *wd, ARegion *ar, int spacetype)
2722 {
2723   writestruct(wd, DATA, ARegion, 1, ar);
2724
2725   if (ar->regiondata) {
2726     if (ar->flag & RGN_FLAG_TEMP_REGIONDATA) {
2727       return;
2728     }
2729
2730     switch (spacetype) {
2731       case SPACE_VIEW3D:
2732         if (ar->regiontype == RGN_TYPE_WINDOW) {
2733           RegionView3D *rv3d = ar->regiondata;
2734           writestruct(wd, DATA, RegionView3D, 1, rv3d);
2735
2736           if (rv3d->localvd) {
2737             writestruct(wd, DATA, RegionView3D, 1, rv3d->localvd);
2738           }
2739           if (rv3d->clipbb) {
2740             writestruct(wd, DATA, BoundBox, 1, rv3d->clipbb);
2741           }
2742         }
2743         else {
2744           printf("regiondata write missing!\n");
2745         }
2746         break;
2747       default:
2748         printf("regiondata write missing!\n");
2749     }
2750   }
2751 }
2752
2753 static void write_uilist(WriteData *wd, uiList *ui_list)
2754 {
2755   writestruct(wd, DATA, uiList, 1, ui_list);
2756
2757   if (ui_list->properties) {
2758     IDP_WriteProperty(ui_list->properties, wd);
2759   }
2760 }
2761
2762 static void write_soops(WriteData *wd, SpaceOutliner *so)
2763 {
2764   BLI_mempool *ts = so->treestore;
2765
2766   if (ts) {
2767     SpaceOutliner so_flat = *so;
2768
2769     int elems = BLI_mempool_len(ts);
2770     /* linearize mempool to array */
2771     TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL;
2772
2773     if (data) {
2774       /* In this block we use the memory location of the treestore
2775        * but _not_ its data, the addresses in this case are UUID's,
2776        * since we can't rely on malloc giving us different values each time.
2777        */
2778       TreeStore ts_flat = {0};
2779
2780       /* we know the treestore is at least as big as a pointer,
2781        * so offsetting works to give us a UUID. */
2782       void *data_addr = (void *)POINTER_OFFSET(ts, sizeof(void *));
2783
2784       ts_flat.usedelem = elems;
2785       ts_flat.totelem = elems;
2786       ts_flat.data = data_addr;
2787
2788       writestruct(wd, DATA, SpaceOutliner, 1, so);
2789
2790       writestruct_at_address(wd, DATA, TreeStore, 1, ts, &ts_flat);
2791       writestruct_at_address(wd, DATA, TreeStoreElem, elems, data_addr, data);
2792
2793       MEM_freeN(data);
2794     }
2795     else {
2796       so_flat.treestore = NULL;
2797       writestruct_at_address(wd, DATA, SpaceOutliner, 1, so, &so_flat);
2798     }
2799   }
2800   else {
2801     writestruct(wd, DATA, SpaceOutliner, 1, so);
2802   }
2803 }
2804
2805 static void write_panel_list(WriteData *wd, ListBase *lb)
2806 {
2807   for (Panel *pa = lb->first; pa; pa = pa->next) {
2808     writestruct(wd, DATA, Panel, 1, pa);
2809     write_panel_list(wd, &pa->children);
2810   }
2811 }
2812
2813 static void write_area_regions(WriteData *wd, ScrArea *area)
2814 {
2815   for (ARegion *region = area->regionbase.first; region; region = region->next) {
2816     write_region(wd, region, area->spacetype);
2817     write_panel_list(wd, &region->panels);
2818
2819     for (PanelCategoryStack *pc_act = region->panels_category_active.first; pc_act;
2820          pc_act = pc_act->next) {
2821       writestruct(wd, DATA, PanelCategoryStack, 1, pc_act);
2822     }
2823
2824     for (uiList *ui_list = region->ui_lists.first; ui_list; ui_list = ui_list->next) {
2825       write_uilist(wd, ui_list);
2826     }
2827
2828     for (uiPreview *ui_preview = region->ui_previews.first; ui_preview;
2829          ui_preview = ui_preview->next) {
2830       writestruct(wd, DATA, uiPreview, 1, ui_preview);
2831     }
2832   }
2833
2834   for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
2835     for (ARegion *region = sl->regionbase.first; region; region = region->next) {
2836       write_region(wd, region, sl->spacetype);
2837     }
2838
2839     if (sl->spacetype == SPACE_VIEW3D) {
2840       View3D *v3d = (View3D *)sl;
2841       writestruct(wd, DATA, View3D, 1, v3d);
2842
2843       if (v3d->localvd) {
2844         writestruct(wd, DATA, View3D, 1, v3d->localvd);
2845       }
2846
2847       if (v3d->fx_settings.ssao) {
2848         writestruct(wd, DATA, GPUSSAOSettings, 1, v3d->fx_settings.ssao);
2849       }
2850       if (v3d->fx_settings.dof) {
2851         writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof);
2852       }
2853     }
2854     else if (sl->spacetype == SPACE_GRAPH) {
2855       SpaceGraph *sipo = (SpaceGraph *)sl;
2856       ListBase tmpGhosts = sipo->runtime.ghost_curves;
2857
2858       /* temporarily disable ghost curves when saving */
2859       BLI_listbase_clear(&sipo->runtime.ghost_curves);
2860
2861       writestruct(wd, DATA, SpaceGraph, 1, sl);
2862       if (sipo->ads) {
2863         writestruct(wd, DATA, bDopeSheet, 1, sipo->ads);
2864       }
2865
2866       /* reenable ghost curves */
2867       sipo->runtime.ghost_curves = tmpGhosts;
2868     }
2869     else if (sl->spacetype == SPACE_PROPERTIES) {
2870       writestruct(wd, DATA, SpaceProperties, 1, sl);
2871     }
2872     else if (sl->spacetype == SPACE_FILE) {
2873       SpaceFile *sfile = (SpaceFile *)sl;
2874
2875       writestruct(wd, DATA, SpaceFile, 1, sl);
2876       if (sfile->params) {
2877         writestruct(wd, DATA, FileSelectParams, 1, sfile->params);
2878       }
2879     }
2880     else if (sl->spacetype == SPACE_SEQ) {
2881       writestruct(wd, DATA, SpaceSeq, 1, sl);
2882     }
2883     else if (sl->spacetype == SPACE_OUTLINER) {
2884       SpaceOutliner *so = (SpaceOutliner *)sl;
2885       write_soops(wd, so);
2886     }
2887     else if (sl->spacetype == SPACE_IMAGE) {
2888       writestruct(wd, DATA, SpaceImage, 1, sl);
2889     }
2890     else if (sl->spacetype == SPACE_TEXT) {
2891       writestruct(wd, DATA, SpaceText, 1, sl);
2892     }
2893     else if (sl->spacetype == SPACE_SCRIPT) {
2894       SpaceScript *scr = (SpaceScript *)sl;
2895       scr->but_refs = NULL;
2896       writestruct(wd, DATA, SpaceScript, 1, sl);
2897     }
2898     else if (sl->spacetype == SPACE_ACTION) {
2899       writestruct(wd, DATA, SpaceAction, 1, sl);
2900     }
2901     else if (sl->spacetype == SPACE_NLA) {
2902       SpaceNla *snla = (SpaceNla *)sl;
2903
2904       writestruct(wd, DATA, SpaceNla, 1, snla);
2905       if (snla->ads) {
2906         writestruct(wd, DATA, bDopeSheet, 1, snla->ads);
2907       }
2908     }
2909     else if (sl->spacetype == SPACE_NODE) {
2910       SpaceNode *snode = (SpaceNode *)sl;
2911       bNodeTreePath *path;
2912       writestruct(wd, DATA, SpaceNode, 1, snode);
2913
2914       for (path = snode->treepath.first; path; path = path->next) {
2915         writestruct(wd, DATA, bNodeTreePath, 1, path);
2916       }
2917     }
2918     else if (sl->spacetype == SPACE_CONSOLE) {
2919       SpaceConsole *con = (SpaceConsole *)sl;
2920       ConsoleLine *cl;
2921
2922       for (cl = con->history.first; cl; cl = cl->next) {
2923         /* 'len_alloc' is invalid on write, set from 'len' on read */
2924         writestruct(wd, DATA, ConsoleLine, 1, cl);
2925         writedata(wd, DATA, cl->len + 1, cl->line);
2926       }
2927       writestruct(wd, DATA, SpaceConsole, 1, sl);
2928     }
2929 #ifdef WITH_GLOBAL_AREA_WRITING
2930     else if (sl->spacetype == SPACE_TOPBAR) {
2931       writestruct(wd, DATA, SpaceTopBar, 1, sl);
2932     }
2933     else if (sl->spacetype == SPACE_STATUSBAR) {
2934       writestruct(wd, DATA, SpaceStatusBar, 1, sl);
2935     }
2936 #endif
2937     else if (sl->spacetype == SPACE_USERPREF) {
2938       writestruct(wd, DATA, SpaceUserPref, 1, sl);
2939     }
2940     else if (sl->spacetype == SPACE_CLIP) {
2941       writestruct(wd, DATA, SpaceClip, 1, sl);
2942     }
2943     else if (sl->spacetype == SPACE_INFO) {
2944       writestruct(wd, DATA, SpaceInfo, 1, sl);
2945     }
2946   }
2947 }
2948
2949 static void write_area_map(WriteData *wd, ScrAreaMap *area_map)
2950 {
2951   writelist(wd, DATA, ScrVert, &area_map->vertbase);
2952   writelist(wd, DATA, ScrEdge, &area_map->edgebase);
2953   for (ScrArea *area = area_map->areabase.first; area; area = area->next) {
2954     area->butspacetype = area->spacetype; /* Just for compatibility, will be reset below. */
2955
2956     writestruct(wd, DATA, ScrArea, 1, area);
2957
2958 #ifdef WITH_GLOBAL_AREA_WRITING
2959     writestruct(wd, DATA, ScrGlobalAreaData, 1, area->global);
2960 #endif
2961
2962     write_area_regions(wd, area);
2963
2964     area->butspacetype = SPACE_EMPTY; /* Unset again, was changed above. */
2965   }
2966 }
2967
2968 static void write_windowmanager(WriteData *wd, wmWindowManager *wm)
2969 {
2970   writestruct(wd, ID_WM, wmWindowManager, 1, wm);
2971   write_iddata(wd, &wm->id);
2972
2973   for (wmWindow *win = wm->windows.first; win; win = win->next) {
2974 #ifndef WITH_GLOBAL_AREA_WRITING
2975     /* Don't write global areas yet, while we make changes to them. */
2976     ScrAreaMap global_areas = win->global_areas;
2977     memset(&win->global_areas, 0, sizeof(win->global_areas));
2978 #endif
2979
2980     /* update deprecated screen member (for so loading in 2.7x uses the correct screen) */
2981     win->screen = BKE_workspace_active_screen_get(win->workspace_hook);
2982
2983     writestruct(wd, DATA, wmWindow, 1, win);
2984     writestruct(wd, DATA, WorkSpaceInstanceHook, 1, win->workspace_hook);
2985     writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
2986
2987 #ifdef WITH_GLOBAL_AREA_WRITING
2988     write_area_map(wd, &win->global_areas);
2989 #else
2990     win->global_areas = global_areas;
2991 #endif
2992
2993     /* data is written, clear deprecated data again */
2994     win->screen = NULL;
2995   }
2996 }
2997
2998 static void write_screen(WriteData *wd, bScreen *sc)
2999 {
3000   /* Screens are reference counted, only saved if used by a workspace. */
3001   if (sc->id.us > 0 || wd->use_memfile) {
3002     /* write LibData */
3003     /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
3004     writestruct(wd, ID_SCRN, bScreen, 1, sc);
3005     write_iddata(wd, &sc->id);
3006
3007     write_previews(wd, sc->preview);
3008
3009     /* direct data */
3010     write_area_map(wd, AREAMAP_FROM_SCREEN(sc));
3011   }
3012 }
3013
3014 static void write_bone(WriteData *wd, Bone *bone)
3015 {
3016   /* PATCH for upward compatibility after 2.37+ armature recode */
3017   bone->size[0] = bone->size[1] = bone->size[2] = 1.0f;
3018
3019   /* Write this bone */
3020   writestruct(wd, DATA, Bone, 1, bone);
3021
3022   /* Write ID Properties -- and copy this comment EXACTLY for easy finding
3023    * of library blocks that implement this.*/
3024   if (bone->prop) {
3025     IDP_WriteProperty(bone->prop, wd);
3026   }
3027
3028   /* Write Children */
3029   for (Bone *cbone = bone->childbase.first; cbone; cbone = cbone->next) {
3030     write_bone(wd, cbone);
3031   }
3032 }
3033
3034 static void write_armature(WriteData *wd, bArmature *arm)
3035 {
3036   if (arm->id.us > 0 || wd->use_memfile) {
3037     writestruct(wd, ID_AR, bArmature, 1, arm);
3038     write_iddata(wd, &arm->id);
3039
3040     if (arm->adt) {
3041       write_animdata(wd, arm->adt);
3042     }
3043
3044     /* Direct data */
3045     for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) {
3046       write_bone(wd, bone);
3047     }
3048   }
3049 }
3050
3051 static void write_text(WriteData *wd, Text *text)
3052 {
3053   if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) {
3054     text->flags &= ~TXT_ISEXT;
3055   }
3056
3057   /* write LibData */
3058   writestruct(wd, ID_TXT, Text, 1, text);
3059   write_iddata(wd, &text->id);
3060
3061   if (text->name) {
3062     writedata(wd, DATA, strlen(text->name) + 1, text->name);
3063   }
3064
3065   if (!(text->flags & TXT_ISEXT)) {
3066     /* now write the text data, in two steps for optimization in the readfunction */
3067     for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
3068       writestruct(wd, DATA, TextLine, 1, tmp);
3069     }
3070
3071     for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
3072       writedata(wd, DATA, tmp->len + 1, tmp->line);
3073     }
3074   }
3075 }
3076
3077 static void write_speaker(WriteData *wd, Speaker *spk)
3078 {
3079   if (spk->id.us > 0 || wd->use_memfile) {
3080     /* write LibData */
3081     writestruct(wd, ID_SPK, Speaker, 1, spk);
3082     write_iddata(wd, &spk->id);
3083
3084     if (spk->adt) {
3085       write_animdata(wd, spk->adt);
3086     }
3087   }
3088 }
3089
3090 static void write_sound(WriteData *wd, bSound *sound)
3091 {
3092   if (sound->id.us > 0 || wd->use_memfile) {
3093     /* write LibData */
3094     writestruct(wd, ID_SO, bSound, 1, sound);
3095     write_iddata(wd, &sound->id);
3096
3097     if (sound->packedfile) {
3098       PackedFile *pf = sound->packedfile;
3099       writestruct(wd, DATA, PackedFile, 1, pf);
3100       writedata(wd, DATA, pf->size, pf->data);
3101     }
3102   }
3103 }
3104
3105 static void write_probe(WriteData *wd, LightProbe *prb)
3106 {
3107   if (prb->id.us > 0 || wd->use_memfile) {
3108     /* write LibData */
3109     writestruct(wd, ID_LP, LightProbe, 1, prb);
3110     write_iddata(wd, &prb->id);
3111
3112     if (prb->adt) {
3113       write_animdata(wd, prb->adt);
3114     }
3115   }
3116 }
3117
3118 static void write_nodetree(WriteData *wd, bNodeTree *ntree)
3119 {
3120   if (ntree->id.us > 0 || wd->use_memfile) {
3121     writestruct(wd, ID_NT, bNodeTree, 1, ntree);
3122     /* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot
3123      * be linked, etc., so we write actual id data here only, for 'real' ID trees. */
3124     write_iddata(wd, &ntree->id);
3125
3126     write_nodetree_nolib(wd, ntree);
3127   }
3128 }
3129
3130 static void write_brush(WriteData *wd, Brush *brush)
3131 {
3132   if (brush->id.us > 0 || wd->use_memfile) {
3133     writestruct(wd, ID_BR, Brush, 1, brush);
3134     write_iddata(wd, &brush->id);
3135
3136     if (brush->curve) {
3137       write_curvemapping(wd, brush->curve);
3138     }
3139
3140     if (brush->gpencil_settings) {
3141       writestruct(wd, DATA, BrushGpencilSettings, 1, brush->gpencil_settings);
3142
3143       if (brush->gpencil_settings->curve_sensitivity) {
3144         write_curvemapping(wd, brush->gpencil_settings->curve_sensitivity);
3145       }
3146       if (brush->gpencil_settings->curve_strength) {
3147         write_curvemapping(wd, brush->gpencil_settings->curve_strength);
3148       }
3149       if (brush->gpencil_settings->curve_jitter) {
3150         write_curvemapping(wd, brush->gpencil_settings->curve_jitter);
3151       }
3152     }
3153     if (brush->gradient) {
3154       writestruct(wd, DATA, ColorBand, 1, brush->gradient);
3155     }
3156   }
3157 }
3158
3159 static void write_palette(WriteData *wd, Palette *palette)
3160 {
3161   if (palette->id.us > 0 || wd->use_memfile) {
3162     PaletteColor *color;
3163     writestruct(wd, ID_PAL, Palette, 1, palette);
3164     write_iddata(wd, &palette->id);
3165
3166     for (color = palette->colors.first; color; color = color->next) {
3167       writestruct(wd, DATA, PaletteColor, 1, color);
3168     }
3169   }
3170 }
3171
3172 static void write_paintcurve(WriteData *wd, PaintCurve *pc)
3173 {
3174   if (pc->id.us > 0 || wd->use_memfile) {
3175     writestruct(wd, ID_PC, PaintCurve, 1, pc);
3176     write_iddata(wd, &pc->id);
3177
3178     writestruct(wd, DATA, PaintCurvePoint, pc->tot_points, pc->points);
3179   }
3180 }
3181
3182 static void write_movieTracks(WriteData *wd, ListBase *tracks)
3183 {
3184   MovieTrackingTrack *track;
3185
3186   track = tracks->first;
3187   while (track) {
3188     writestruct(wd, DATA, MovieTrackingTrack, 1, track);
3189
3190     if (track->markers) {
3191       writestruct(wd, DATA, MovieTrackingMarker, track->markersnr, track->markers);
3192     }
3193
3194     track = track->next;
3195   }
3196 }
3197
3198 static void write_moviePlaneTracks(WriteData *wd, ListBase *plane_tracks_base)
3199 {
3200   MovieTrackingPlaneTrack *plane_track;
3201
3202   for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
3203     writestruct(wd, DATA, MovieTrackingPlaneTrack, 1, plane_track);
3204
3205     writedata(wd,
3206               DATA,
3207               sizeof(MovieTrackingTrack *) * plane_track->point_tracksnr,
3208               plane_track->point_tracks);
3209     writestruct(wd, DATA, MovieTrackingPlaneMarker, plane_track->markersnr, plane_track->markers);
3210   }
3211 }
3212
3213 static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction *reconstruction)
3214 {
3215   if (reconstruction->camnr) {
3216     writestruct(
3217         wd, DATA, MovieReconstructedCamera, reconstruction->camnr, reconstruction->cameras);
3218   }
3219 }
3220
3221 static void write_movieclip(WriteData *wd, MovieClip *clip)
3222 {
3223   if (clip->id.us > 0 || wd->use_memfile) {
3224     MovieTracking *tracking = &clip->tracking;
3225     MovieTrackingObject *object;
3226
3227     writestruct(wd, ID_MC, MovieClip, 1, clip);
3228     write_iddata(wd, &clip->id);
3229
3230     if (clip->adt) {
3231       write_animdata(wd, clip->adt);
3232     }
3233
3234     write_movieTracks(wd, &tracking->tracks);
3235     write_moviePlaneTracks(wd, &tracking->plane_tracks);
3236     write_movieReconstruction(wd, &tracking->reconstruction);
3237
3238     object = tracking->objects.first;
3239     while (object) {
3240       writestruct(wd, DATA, MovieTrackingObject, 1, object);
3241
3242       write_movieTracks(wd, &object->tracks);
3243       write_moviePlaneTracks(wd, &object->plane_tracks);
3244       write_movieReconstruction(wd, &object->reconstruction);
3245
3246       object = object->next;
3247     }
3248   }
3249 }
3250
3251 static void write_mask(WriteData *wd, Mask *mask)
3252 {
3253   if (mask->id.us > 0 || wd->use_memfile) {
3254     MaskLayer *masklay;
3255
3256     writestruct(wd, ID_MSK, Mask, 1, mask);
3257     write_iddata(wd, &mask->id);
3258
3259     if (mask->adt) {
3260       write_animdata(wd, mask->adt);
3261     }
3262
3263     for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
3264       MaskSpline *spline;
3265       MaskLayerShape *masklay_shape;
3266
3267       writestruct(wd, DATA, MaskLayer, 1, masklay);
3268
3269       for (spline = masklay->splines.first; spline; spline = spline->next) {
3270         int i;
3271
3272         void *points_deform = spline->points_deform;
3273         spline->points_deform = NULL;
3274
3275         writestruct(wd, DATA, MaskSpline, 1, spline);
3276         writestruct(wd, DATA, MaskSplinePoint, spline->tot_point, spline->points);
3277
3278         spline->points_deform = points_deform;
3279
3280         for (i = 0; i < spline->tot_point; i++) {
3281           MaskSplinePoint *point = &spline->points[i];
3282
3283           if (point->tot_uw) {
3284             writestruct(wd, DATA, MaskSplinePointUW, point->tot_uw, point->uw);
3285           }
3286         }
3287       }
3288
3289       for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
3290            masklay_shape = masklay_shape->next) {
3291         writestruct(wd, DATA, MaskLayerShape, 1, masklay_shape);
3292         writedata(wd,
3293                   DATA,
3294                   masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE,
3295                   masklay_shape->data);
3296       }
3297     }
3298   }
3299 }
3300
3301 static void write_linestyle_color_modifiers(WriteData *wd, ListBase *modifiers)
3302 {
3303   LineStyleModifier *m;
3304
3305   for (m = modifiers->first; m; m = m->next) {
3306     int struct_nr;
3307     switch (m->type) {
3308       case LS_MODIFIER_ALONG_STROKE:
3309         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleColorModifier_AlongStroke);
3310         break;
3311       case LS_MODIFIER_DISTANCE_FROM_CAMERA:
3312         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleColorModifier_DistanceFromCamera);
3313         break;
3314       case LS_MODIFIER_DISTANCE_FROM_OBJECT:
3315         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleColorModifier_DistanceFromObject);
3316         break;
3317       case LS_MODIFIER_MATERIAL:
3318         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleColorModifier_Material);
3319         break;
3320       case LS_MODIFIER_TANGENT:
3321         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleColorModifier_Tangent);
3322         break;
3323       case LS_MODIFIER_NOISE:
3324         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleColorModifier_Noise);
3325         break;
3326       case LS_MODIFIER_CREASE_ANGLE:
3327         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleColorModifier_CreaseAngle);
3328         break;
3329       case LS_MODIFIER_CURVATURE_3D:
3330         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleColorModifier_Curvature_3D);
3331         break;
3332       default:
3333         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleModifier); /* this should not happen */
3334     }
3335     writestruct_nr(wd, DATA, struct_nr, 1, m);
3336   }
3337   for (m = modifiers->first; m; m = m->next) {
3338     switch (m->type) {
3339       case LS_MODIFIER_ALONG_STROKE:
3340         writestruct(wd, DATA, ColorBand, 1, ((LineStyleColorModifier_AlongStroke *)m)->color_ramp);
3341         break;
3342       case LS_MODIFIER_DISTANCE_FROM_CAMERA:
3343         writestruct(
3344             wd, DATA, ColorBand, 1, ((LineStyleColorModifier_DistanceFromCamera *)m)->color_ramp);
3345         break;
3346       case LS_MODIFIER_DISTANCE_FROM_OBJECT:
3347         writestruct(
3348             wd, DATA, ColorBand, 1, ((LineStyleColorModifier_DistanceFromObject *)m)->color_ramp);
3349         break;
3350       case LS_MODIFIER_MATERIAL:
3351         writestruct(wd, DATA, ColorBand, 1, ((LineStyleColorModifier_Material *)m)->color_ramp);
3352         break;
3353       case LS_MODIFIER_TANGENT:
3354         writestruct(wd, DATA, ColorBand, 1, ((LineStyleColorModifier_Tangent *)m)->color_ramp);
3355         break;
3356       case LS_MODIFIER_NOISE:
3357         writestruct(wd, DATA, ColorBand, 1, ((LineStyleColorModifier_Noise *)m)->color_ramp);
3358         break;
3359       case LS_MODIFIER_CREASE_ANGLE:
3360         writestruct(wd, DATA, ColorBand, 1, ((LineStyleColorModifier_CreaseAngle *)m)->color_ramp);
3361         break;
3362       case LS_MODIFIER_CURVATURE_3D:
3363         writestruct(
3364             wd, DATA, ColorBand, 1, ((LineStyleColorModifier_Curvature_3D *)m)->color_ramp);
3365         break;
3366     }
3367   }
3368 }
3369
3370 static void write_linestyle_alpha_modifiers(WriteData *wd, ListBase *modifiers)
3371 {
3372   LineStyleModifier *m;
3373
3374   for (m = modifiers->first; m; m = m->next) {
3375     int struct_nr;
3376     switch (m->type) {
3377       case LS_MODIFIER_ALONG_STROKE:
3378         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleAlphaModifier_AlongStroke);
3379         break;
3380       case LS_MODIFIER_DISTANCE_FROM_CAMERA:
3381         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleAlphaModifier_DistanceFromCamera);
3382         break;
3383       case LS_MODIFIER_DISTANCE_FROM_OBJECT:
3384         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleAlphaModifier_DistanceFromObject);
3385         break;
3386       case LS_MODIFIER_MATERIAL:
3387         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleAlphaModifier_Material);
3388         break;
3389       case LS_MODIFIER_TANGENT:
3390         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleAlphaModifier_Tangent);
3391         break;
3392       case LS_MODIFIER_NOISE:
3393         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleAlphaModifier_Noise);
3394         break;
3395       case LS_MODIFIER_CREASE_ANGLE:
3396         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleAlphaModifier_CreaseAngle);
3397         break;
3398       case LS_MODIFIER_CURVATURE_3D:
3399         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleAlphaModifier_Curvature_3D);
3400         break;
3401       default:
3402         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleModifier); /* this should not happen */
3403     }
3404     writestruct_nr(wd, DATA, struct_nr, 1, m);
3405   }
3406   for (m = modifiers->first; m; m = m->next) {
3407     switch (m->type) {
3408       case LS_MODIFIER_ALONG_STROKE:
3409         write_curvemapping(wd, ((LineStyleAlphaModifier_AlongStroke *)m)->curve);
3410         break;
3411       case LS_MODIFIER_DISTANCE_FROM_CAMERA:
3412         write_curvemapping(wd, ((LineStyleAlphaModifier_DistanceFromCamera *)m)->curve);
3413         break;
3414       case LS_MODIFIER_DISTANCE_FROM_OBJECT:
3415         write_curvemapping(wd, ((LineStyleAlphaModifier_DistanceFromObject *)m)->curve);
3416         break;
3417       case LS_MODIFIER_MATERIAL:
3418         write_curvemapping(wd, ((LineStyleAlphaModifier_Material *)m)->curve);
3419         break;
3420       case LS_MODIFIER_TANGENT:
3421         write_curvemapping(wd, ((LineStyleAlphaModifier_Tangent *)m)->curve);
3422         break;
3423       case LS_MODIFIER_NOISE:
3424         write_curvemapping(wd, ((LineStyleAlphaModifier_Noise *)m)->curve);
3425         break;
3426       case LS_MODIFIER_CREASE_ANGLE:
3427         write_curvemapping(wd, ((LineStyleAlphaModifier_CreaseAngle *)m)->curve);
3428         break;
3429       case LS_MODIFIER_CURVATURE_3D:
3430         write_curvemapping(wd, ((LineStyleAlphaModifier_Curvature_3D *)m)->curve);
3431         break;
3432     }
3433   }
3434 }
3435
3436 static void write_linestyle_thickness_modifiers(WriteData *wd, ListBase *modifiers)
3437 {
3438   LineStyleModifier *m;
3439
3440   for (m = modifiers->first; m; m = m->next) {
3441     int struct_nr;
3442     switch (m->type) {
3443       case LS_MODIFIER_ALONG_STROKE:
3444         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleThicknessModifier_AlongStroke);
3445         break;
3446       case LS_MODIFIER_DISTANCE_FROM_CAMERA:
3447         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleThicknessModifier_DistanceFromCamera);
3448         break;
3449       case LS_MODIFIER_DISTANCE_FROM_OBJECT:
3450         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleThicknessModifier_DistanceFromObject);
3451         break;
3452       case LS_MODIFIER_MATERIAL:
3453         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleThicknessModifier_Material);
3454         break;
3455       case LS_MODIFIER_CALLIGRAPHY:
3456         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleThicknessModifier_Calligraphy);
3457         break;
3458       case LS_MODIFIER_TANGENT:
3459         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleThicknessModifier_Tangent);
3460         break;
3461       case LS_MODIFIER_NOISE:
3462         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleThicknessModifier_Noise);
3463         break;
3464       case LS_MODIFIER_CREASE_ANGLE:
3465         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleThicknessModifier_CreaseAngle);
3466         break;
3467       case LS_MODIFIER_CURVATURE_3D:
3468         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleThicknessModifier_Curvature_3D);
3469         break;
3470       default:
3471         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleModifier); /* this should not happen */
3472     }
3473     writestruct_nr(wd, DATA, struct_nr, 1, m);
3474   }
3475   for (m = modifiers->first; m; m = m->next) {
3476     switch (m->type) {
3477       case LS_MODIFIER_ALONG_STROKE:
3478         write_curvemapping(wd, ((LineStyleThicknessModifier_AlongStroke *)m)->curve);
3479         break;
3480       case LS_MODIFIER_DISTANCE_FROM_CAMERA:
3481         write_curvemapping(wd, ((LineStyleThicknessModifier_DistanceFromCamera *)m)->curve);
3482         break;
3483       case LS_MODIFIER_DISTANCE_FROM_OBJECT:
3484         write_curvemapping(wd, ((LineStyleThicknessModifier_DistanceFromObject *)m)->curve);
3485         break;
3486       case LS_MODIFIER_MATERIAL:
3487         write_curvemapping(wd, ((LineStyleThicknessModifier_Material *)m)->curve);
3488         break;
3489       case LS_MODIFIER_TANGENT:
3490         write_curvemapping(wd, ((LineStyleThicknessModifier_Tangent *)m)->curve);
3491         break;
3492       case LS_MODIFIER_CREASE_ANGLE:
3493         write_curvemapping(wd, ((LineStyleThicknessModifier_CreaseAngle *)m)->curve);
3494         break;
3495       case LS_MODIFIER_CURVATURE_3D:
3496         write_curvemapping(wd, ((LineStyleThicknessModifier_Curvature_3D *)m)->curve);
3497         break;
3498     }
3499   }
3500 }
3501
3502 static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifiers)
3503 {
3504   LineStyleModifier *m;
3505
3506   for (m = modifiers->first; m; m = m->next) {
3507     int struct_nr;
3508     switch (m->type) {
3509       case LS_MODIFIER_SAMPLING:
3510         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_Sampling);
3511         break;
3512       case LS_MODIFIER_BEZIER_CURVE:
3513         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_BezierCurve);
3514         break;
3515       case LS_MODIFIER_SINUS_DISPLACEMENT:
3516         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_SinusDisplacement);
3517         break;
3518       case LS_MODIFIER_SPATIAL_NOISE:
3519         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_SpatialNoise);
3520         break;
3521       case LS_MODIFIER_PERLIN_NOISE_1D:
3522         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_PerlinNoise1D);
3523         break;
3524       case LS_MODIFIER_PERLIN_NOISE_2D:
3525         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_PerlinNoise2D);
3526         break;
3527       case LS_MODIFIER_BACKBONE_STRETCHER:
3528         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_BackboneStretcher);
3529         break;
3530       case LS_MODIFIER_TIP_REMOVER:
3531         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_TipRemover);
3532         break;
3533       case LS_MODIFIER_POLYGONIZATION:
3534         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_Polygonalization);
3535         break;
3536       case LS_MODIFIER_GUIDING_LINES:
3537         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_GuidingLines);
3538         break;
3539       case LS_MODIFIER_BLUEPRINT:
3540         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_Blueprint);
3541         break;
3542       case LS_MODIFIER_2D_OFFSET:
3543         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_2DOffset);
3544         break;
3545       case LS_MODIFIER_2D_TRANSFORM:
3546         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_2DTransform);
3547         break;
3548       case LS_MODIFIER_SIMPLIFICATION:
3549         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleGeometryModifier_Simplification);
3550         break;
3551       default:
3552         struct_nr = SDNA_TYPE_FROM_STRUCT(LineStyleModifier); /* this should not happen */
3553     }
3554     writestruct_nr(wd, DATA, struct_nr, 1, m);
3555   }
3556 }
3557
3558 static void write_linestyle(WriteData *wd, FreestyleLineStyle *linestyle)
3559 {
3560   if (linestyle->id.us > 0 || wd->use_memfile) {
3561     writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle);
3562     write_iddata(wd, &linestyle->id);
3563
3564     if (linestyle->adt) {
3565       write_animdata(wd, linestyle->adt);
3566     }
3567
3568     write_linestyle_color_modifiers(wd, &linestyle->color_modifiers);
3569     write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers);
3570     write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers);
3571     write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers);
3572     for (int a = 0; a < MAX_MTEX; a++) {
3573       if (linestyle->mtex[a]) {
3574         writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]);
3575       }
3576     }
3577     if (linestyle->nodetree) {
3578       writestruct(wd, DATA, bNodeTree, 1, linestyle->nodetree);
3579       write_nodetree_nolib(wd, linestyle->nodetree);
3580     }
3581   }
3582 }
3583
3584 static void write_cachefile(WriteData *wd, CacheFile *cache_file)
3585 {
3586   if (cache_file->id.us > 0 || wd->use_memfile) {
3587     writestruct(wd, ID_CF, CacheFile, 1, cache_file);
3588
3589     if (cache_file->adt) {
3590       write_animdata(wd, cache_file->adt);
3591     }
3592   }
3593 }
3594
3595 static void write_workspace(WriteData *wd, WorkSpace *workspace)
3596 {
3597   ListBase *layouts = BKE_workspace_layouts_get(workspace);
3598
3599   writestruct(wd, ID_WS, WorkSpace, 1, workspace);
3600   writelist(wd, DATA, WorkSpaceLayout, layouts);
3601   writelist(wd, DATA, WorkSpaceDataRelation, &workspace->hook_layout_relations);
3602   writelist(wd, DATA, wmOwnerID, &workspace->owner_ids);
3603   writelist(wd, DATA, bToolRef, &workspace->tools);
3604   for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) {
3605     if (tref->properties) {
3606       IDP_WriteProperty(tref->properties, wd);
3607     }
3608   }
3609 }
3610
3611 /* Keep it last of write_foodata functions. */
3612 static void write_libraries(WriteData *wd, Main *main)
3613 {
3614   ListBase *lbarray[MAX_LIBARRAY];
3615   ID *id;
3616   int a, tot;
3617   bool found_one;
3618
3619   for (; main; main = main->next) {
3620     a = tot = set_listbasepointers(main, lbarray);
3621
3622     /* test: is lib being used */
3623     if (main->curlib && main->curlib->packedfile) {
3624       found_one = true;
3625     }
3626     else {
3627       found_one = false;
3628       while (!found_one && tot--) {
3629         for (id = lbarray[tot]->first; id; id = id->next) {
3630           if (id->us > 0 && (id->tag & LIB_TAG_EXTERN)) {
3631             found_one = true;
3632             break;
3633           }
3634         }
3635       }
3636     }
3637
3638     /* To be able to restore 'quit.blend' and temp saves,
3639      * the packed blend has to be in undo buffers... */
3640     /* XXX needs rethink, just like save UI in undo files now -
3641      * would be nice to append things only for the 'quit.blend' and temp saves. */
3642     if (found_one) {
3643       /* Not overridable. */
3644
3645       writestruct(wd, ID_LI, Library, 1, main->curlib);
3646       write_iddata(wd, &main->curlib->id);
3647
3648       if (main->curlib->packedfile) {
3649         PackedFile *pf = main->curlib->packedfile;
3650         writestruct(wd, DATA, PackedFile, 1, pf);
3651         writedata(wd, DATA, pf->size, pf->data);
3652         if (wd->use_memfile == false) {
3653           printf("write packed .blend: %s\n", main->curlib->name);
3654         }
3655       }
3656
3657       /* Write link placeholders for all direct linked IDs. */
3658       while (a--) {
3659         for (id = lbarray[a]->first; id; id = id->next) {
3660           if (id->us > 0 && (id->tag & LIB_TAG_EXTERN)) {
3661             if (!BKE_idcode_is_linkable(GS(id->name))) {
3662               printf(
3663                   "ERROR: write file: data-block '%s' from lib '%s' is not linkable "
3664                   "but is flagged as directly linked",
3665                   id->name,
3666                   main->curlib->filepath);
3667               BLI_assert(0);
3668             }
3669             writestruct(wd, ID_LINK_PLACEHOLDER, ID, 1, id);
3670           }
3671         }
3672       }
3673     }
3674   }
3675
3676   mywrite_flush(wd);
3677 }
3678
3679 /* context is usually defined by WM, two cases where no WM is available:
3680  * - for forward compatibility, curscreen has to be saved
3681  * - for undofile, curscene needs to be saved */
3682 static void write_global(WriteData *wd, int fileflags, Main *mainvar)
3683 {
3684   const bool is_undo = wd->use_memfile;
3685   FileGlobal fg;
3686   bScreen *screen;
3687   Scene *scene;
3688   ViewLayer *view_layer;
3689   char subvstr[8];
3690
3691   /* prevent mem checkers from complaining */
3692   memset(fg._pad, 0, sizeof(fg._pad));
3693   memset(fg.filename, 0, sizeof(fg.filename));
3694   memset(fg.build_hash, 0, sizeof(fg.build_hash));
3695   fg._pad1 = NULL;
3696
3697   current_screen_compat(mainvar, is_undo, &screen, &scene, &view_layer);
3698
3699   /* XXX still remap G */
3700   fg.curscreen = screen;
3701   fg.curscene = scene;
3702   fg.cur_view_layer = view_layer;
3703
3704   /* prevent to save this, is not good convention, and feature with concerns... */
3705   fg.fileflags = (fileflags & ~G_FILE_FLAG_ALL_RUNTIME);
3706
3707   fg.globalf = G.f;
3708   BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename));
3709   sprintf(subvstr, "%4d", BLENDER_SUBVERSION);
3710   memcpy(fg.subvstr, subvstr, 4);
3711
3712   fg.subversion = BLENDER_SUBVERSION;
3713   fg.minversion = BLENDER_MINVERSION;
3714   fg.minsubversion = BLENDER_MINSUBVERSION;
3715 #ifdef WITH_BUILDINFO
3716   {
3717     extern unsigned long build_commit_timestamp;
3718     extern char build_hash[];
3719     /* TODO(sergey): Add branch name to file as well? */
3720     fg.build_commit_timestamp = build_commit_timestamp;
3721     BLI_strncpy(fg.build_hash, build_hash, sizeof(fg.build_hash));
3722   }
3723 #else
3724   fg.build_commit_timestamp = 0;
3725   BLI_strncpy(fg.build_hash, "unknown", sizeof(fg.build_hash));
3726 #endif
3727   writestruct(wd, GLOB, FileGlobal, 1, &fg);
3728 }
3729
3730 /* preview image, first 2 values are width and height
3731  * second are an RGBA image (uchar)
3732  * note, this uses 'TEST' since new types will segfault on file load for older blender versions.
3733  */
3734 static void write_thumb(WriteData *wd, const BlendThumbnail *thumb)
3735 {
3736   if (thumb) {
3737     writedata(wd, TEST, BLEN_THUMB_MEMSIZE_FILE(thumb->width, thumb->height), thumb);
3738   }
3739 }
3740
3741 /** \} */
3742
3743 /* -------------------------------------------------------------------- */
3744 /** \name File Writing (Private)
3745  * \{ */
3746
3747 /* if MemFile * there's filesave to memory */
3748 static bool write_file_handle(Main *mainvar,
3749                               WriteWrap *ww,
3750                               MemFile *compare,
3751                               MemFile *current,
3752                               int write_flags,
3753                               const BlendThumbnail *thumb)
3754 {
3755   BHead bhead;
3756   ListBase mainlist;
3757   char buf[16];
3758   WriteData *wd;
3759
3760   blo_split_main(&mainlist, mainvar);
3761
3762   wd = mywrite_begin(ww, compare, current);
3763
3764   sprintf(buf,
3765           "BLENDER%c%c%.3d",
3766           (sizeof(void *) == 8) ? '-' : '_',
3767           (ENDIAN_ORDER == B_ENDIAN) ? 'V' : 'v',
3768           BLENDER_VERSION);
3769
3770   mywrite(wd, buf, 12);
3771
3772   write_renderinfo(wd, mainvar);
3773   write_thumb(wd, thumb);
3774   write_global(wd, write_flags, mainvar);
3775
3776   /* The windowmanager and screen often change,
3777    * avoid thumbnail detecting changes because of this. */
3778   mywrite_flush(wd);
3779
3780   OverrideLibraryStorage *override_storage =
3781       wd->use_memfile ? NULL : BKE_override_library_operations_store_initialize();
3782
3783   /* This outer loop allows to save first data-blocks from real mainvar,
3784    * then the temp ones from override process,
3785    * if needed, without duplicating whole code. */
3786   Main *bmain = mainvar;
3787   do {
3788     ListBase *lbarray[MAX_LIBARRAY];
3789     int a = set_listbasepointers(bmain, lbarray);
3790     while (a--) {
3791       ID *id = lbarray[a]->first;
3792
3793       if (id && GS(id->name) == ID_LI) {
3794         continue; /* Libraries are handled separately below. */
3795       }
3796
3797       for (; id; id = id->next) {
3798         /* We should never attempt to write non-regular IDs
3799          * (i.e. all kind of temp/runtime ones). */
3800         BLI_assert(
3801             (id->tag & (LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT | LIB_TAG_NOT_ALLOCATED)) == 0);
3802
3803         const bool do_override = !ELEM(override_storage, NULL, bmain) && id->override_library;
3804
3805         if (do_override) {
3806           BKE_override_library_operations_store_start(bmain, override_storage, id);
3807         }
3808
3809         switch ((ID_Type)GS(id->name)) {
3810           case ID_WM:
3811             write_windowmanager(wd, (wmWindowManager *)id);
3812             break;
3813           case ID_WS:
3814             write_workspace(wd, (WorkSpace *)id);
3815             break;
3816           case ID_SCR:
3817             write_screen(wd, (bScreen *)id);
3818             break;
3819           case ID_MC:
3820             write_movieclip(wd, (MovieClip *)id);
3821             break;
3822           case ID_MSK:
3823             write_mask(wd, (Mask *)id);
3824             break;
3825           case ID_SCE:
3826             write_scene(wd, (Scene *)id);
3827             break;
3828           case ID_CU:
3829             write_curve(wd, (Curve *)id);
3830             break;
3831           case ID_MB:
3832             write_mball(wd, (MetaBall *)id);
3833             break;
3834           case ID_IM:
3835             write_image(wd, (Image *)id);
3836             break;
3837           case ID_CA:
3838             write_camera(wd, (Camera *)id);
3839             break;
3840           case ID_LA:
3841             write_light(wd, (Light *)id);
3842             break;
3843           case ID_LT:
3844             write_lattice(wd, (Lattice *)id);
3845             break;
3846           case ID_VF:
3847             write_vfont(wd, (VFont *)id);
3848             break;
3849           case ID_KE:
3850             write_key(wd, (Key *)id);
3851             break;
3852           case ID_WO:
3853             write_world(wd, (World *)id);
3854             break;
3855           case ID_TXT:
3856             write_text(wd, (Text *)id);
3857             break;
3858           case ID_SPK:
3859             write_speaker(wd, (Speaker *)id);
3860             break;
3861           case ID_LP:
3862             write_probe(wd, (LightProbe *)id);
3863             break;
3864           case ID_SO:
3865             write_sound(wd, (bSound *)id);
3866             break;
3867           case ID_GR:
3868             write_collection(wd, (Collection *)id);
3869             break;
3870           case ID_AR:
3871             write_armature(wd, (bArmature *)id);
3872             break;
3873           case ID_AC:
3874             write_action(wd, (bAction *)id);
3875             break;
3876           case ID_OB:
3877             write_object(wd, (Object *)id);
3878             break;
3879           case ID_MA:
3880             write_material(wd, (Material *)id);
3881             break;
3882           case ID_TE:
3883             write_texture(wd, (Tex *)id);
3884             break;
3885           case ID_ME:
3886             write_mesh(wd, (Mesh *)id);
3887             break;
3888           case ID_PA:
3889             write_particlesettings(wd, (ParticleSettings *)id);
3890             break;
3891           case ID_NT:
3892             write_nodetree(wd, (bNodeTree *)id);
3893             break;
3894           case ID_BR:
3895             write_brush(wd, (Brush *)id);
3896             break;
3897           case ID_PAL:
3898             write_palette(wd, (Palette *)id);
3899             break;
3900           case ID_PC:
3901             write_paintcurve(wd, (PaintCurve *)id);
3902             break;
3903           case ID_GD:
3904             write_gpencil(wd, (bGPdata *)id);
3905             break;
3906           case ID_LS:
3907             write_linestyle(wd, (FreestyleLineStyle *)id);
3908             break;
3909           case ID_CF:
3910             write_cachefile(wd, (CacheFile *)id);
3911             break;
3912           case ID_LI:
3913             /* Do nothing, handled below - and should never be reached. */
3914             BLI_assert(0);
3915             break;
3916           case ID_IP:
3917             /* Do nothing, deprecated. */
3918             break;
3919           default:
3920             /* Should never be reached. */
3921             BLI_assert(0);
3922             break;
3923         }
3924
3925         if (do_override) {
3926           BKE_override_library_operations_store_end(override_storage, id);
3927         }
3928       }
3929
3930       mywrite_flush(wd);
3931     }
3932   } while ((bmain != override_storage) && (bmain = override_storage));
3933
3934   if (override_storage) {
3935     BKE_override_library_operations_store_finalize(override_storage);
3936     override_storage = NULL;
3937   }
3938
3939   /* Special handling, operating over split Mains... */
3940   write_libraries(wd, mainvar->next);
3941
3942   /* So changes above don't cause a 'DNA1' to be detected as changed on undo. */
3943   mywrite_flush(wd);
3944
3945   if (write_flags & G_FILE_USERPREFS) {
3946     write_userdef(wd, &U);
3947   }
3948
3949   /* Write DNA last, because (to be implemented) test for which structs are written.
3950    *
3951    * Note that we *borrow* the pointer to 'DNAstr',
3952    * so writing each time uses the same address and doesn't cause unnecessary undo overhead. */
3953   writedata(wd, DNA1, wd->sdna->data_len, wd->sdna->data);
3954
3955   /* end of file */
3956   memset(&bhead, 0, sizeof(BHead));
3957   bhead.code = ENDB;
3958   mywrite(wd, &bhead, sizeof(BHead));
3959
3960   blo_join_main(&mainlist);
3961
3962   return mywrite_end(wd);
3963 }
3964
3965 /* do reverse file history: .blend1 -> .blend2, .blend -> .blend1 */
3966 /* return: success(0), failure(1) */
3967 static bool do_history(const char *name, ReportList *reports)
3968 {
3969   char tempname1[FILE_MAX], tempname2[FILE_MAX];
3970   int hisnr = U.versions;
3971
3972   if (U.versions == 0) {
3973     return 0;
3974   }
3975
3976   if (strlen(name) < 2) {
3977     BKE_report(reports, RPT_ERROR, "Unable to make version backup: filename too short");
3978     return 1;
3979   }
3980
3981   while (hisnr > 1) {
3982     BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr - 1);
3983     if (BLI_exists(tempname1)) {
3984       BLI_snprintf(tempname2, sizeof(tempname2), "%s%d", name, hisnr);
3985
3986       if (BLI_rename(tempname1, tempname2)) {
3987         BKE_report(reports, RPT_ERROR, "Unable to make version backup");
3988         return true;
3989       }
3990     }
3991     hisnr--;
3992   }
3993
3994   /* is needed when hisnr==1 */
3995   if (BLI_exists(name)) {
3996     BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr);
3997
3998     if (BLI_rename(name, tempname1)) {
3999       BKE_report(reports, RPT_ERROR, "Unable to make version backup");
4000       return true;
4001     }
4002   }
4003
4004   return 0;
4005 }
4006
4007 /** \} */
4008
4009 /* -------------------------------------------------------------------- */
4010 /** \name File Writing (Public)
4011  * \{ */
4012
4013 /**
4014  * \return Success.
4015  */
4016 bool BLO_write_file(Main *mainvar,
4017                     const char *filepath,
4018                     int write_flags,
4019                     ReportList *reports,
4020                     const BlendThumbnail *thumb)
4021 {
4022   char tempname[FILE_MAX + 1];
4023   eWriteWrapType ww_type;
4024   WriteWrap ww;
4025
4026   /* path backup/restore */
4027   void *path_list_backup = NULL;
4028   const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
4029
4030   if (G.debug & G_DEBUG_IO && mainvar->lock != NULL) {
4031     BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *BEFORE* save to disk");
4032     BLO_main_validate_libraries(mainvar, reports);
4033     BLO_main_validate_shapekeys(mainvar, reports);
4034   }
4035
4036   /* open temporary file, so we preserve the original in case we crash */
4037   BLI_snprintf(tempname, sizeof(tempname), "%s@", filepath);
4038
4039   if (write_flags & G_FILE_COMPRESS) {
4040     ww_type = WW_WRAP_ZLIB;
4041   }
4042   else {
4043     ww_type = WW_WRAP_NONE;
4044   }
4045
4046   ww_handle_init(ww_type, &ww);
4047
4048   if (ww.open(&ww, tempname) == false) {
4049     BKE_reportf(
4050         reports, RPT_ERROR, "Cannot open file %s for writing: %s", tempname, strerror(errno));
4051     return 0;
4052   }
4053
4054   /* check if we need to backup and restore paths */
4055   if (UNLIKELY((write_flags & G_FILE_RELATIVE_REMAP) && (G_FILE_SAVE_COPY & write_flags))) {
4056     path_list_backup = BKE_bpath_list_backup(mainvar, path_list_flag);
4057   }
4058
4059   /* remapping of relative paths to new file location */
4060   if (write_flags & G_FILE_RELATIVE_REMAP) {
4061     char dir1[FILE_MAX];
4062     char dir2[FILE_MAX];
4063     BLI_split_dir_part(filepath, dir1, sizeof(dir1));
4064     BLI_split_dir_part(mainvar->name, dir2, sizeof(dir2));
4065
4066     /* just in case there is some subtle difference */
4067     BLI_cleanup_dir(mainvar->name, dir1);
4068     BLI_cleanup_dir(mainvar->name, dir2);
4069
4070     if (G.relbase_valid && (BLI_path_cmp(dir1, dir2) == 0)) {
4071       write_flags &= ~G_FILE_RELATIVE_REMAP;
4072     }
4073     else {
4074       if (G.relbase_valid) {
4075         /* blend may not have been saved before. Tn this case
4076          * we should not have any relative paths, but if there
4077          * is somehow, an invalid or empty G_MAIN->name it will
4078          * print an error, don't try make the absolute in this case. */
4079         BKE_bpath_absolute_convert(mainvar, BKE_main_blendfile_path_from_global(), NULL);
4080       }
4081     }
4082   }
4083
4084   if (write_flags & G_FILE_RELATIVE_REMAP) {
4085     /* note, making relative to something OTHER then G_MAIN->name */
4086     BKE_bpath_relative_convert(mainvar, filepath, NULL);
4087   }
4088
4089   /* actual file writing */
4090   const bool err = write_file_handle(mainvar, &ww, NULL, NULL, write_flags, thumb);
4091
4092   ww.close(&ww);
4093
4094   if (UNLIKELY(path_list_backup)) {
4095     BKE_bpath_list_restore(mainvar, path_list_flag, path_list_backup);
4096     BKE_bpath_list_free(path_list_backup);
4097   }
4098
4099   if (err) {
4100     BKE_report(reports, RPT_ERROR, strerror(errno));
4101     remove(tempname);
4102
4103     return 0;
4104   }
4105
4106   /* file save to temporary file was successful */
4107   /* now do reverse file history (move .blend1 -> .blend2, .blend -> .blend1) */
4108   if (write_flags & G_FILE_HISTORY) {
4109     const bool err_hist = do_history(filepath, reports);
4110     if (err_hist) {
4111       BKE_report(reports, RPT_ERROR, "Version backup failed (file saved with @)");
4112       return 0;
4113     }
4114   }
4115
4116   if (BLI_rename(tempname, filepath) != 0) {
4117     BKE_report(reports, RPT_ERROR, "Cannot change old file (file saved with @)");
4118     return 0;
4119   }
4120
4121   if (G.debug & G_DEBUG_IO && mainvar->lock != NULL) {
4122     BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *AFTER* save to disk");
4123     BLO_main_validate_libraries(mainvar, reports);
4124   }
4125
4126   return 1;
4127 }
4128
4129 /**
4130  * \return Success.
4131  */
4132 bool BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, int write_flags)
4133 {
4134   write_flags &= ~G_FILE_USERPREFS;
4135
4136   const bool err = write_file_handle(mainvar, NULL, compare, current, write_flags, NULL);
4137
4138   return (err == 0);
4139 }
4140
4141 /** \} */