Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenloader / intern / writefile.c
index 5941f96041c2a1d1de3e811dfdf4b21e72443e8d..d566058f4a77497c83dfcd6c69e6c07adca66472 100644 (file)
 
 /* allow writefile to use deprecated functionality (for forward compatibility code) */
 #define DNA_DEPRECATED_ALLOW
+/* Allow using DNA struct members that are marked as private for read/write.
+ * Note: Each header that uses this needs to define its own way of handling
+ * it. There's no generic implementation, direct use does nothing. */
+#define DNA_PRIVATE_READ_WRITE_ALLOW
 
 #include "DNA_anim_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_key_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_lamp_types.h"
+#include "DNA_layer_types.h"
 #include "DNA_linestyle_types.h"
 #include "DNA_meta_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_object_force_types.h"
 #include "DNA_packedFile_types.h"
 #include "DNA_particle_types.h"
+#include "DNA_lightprobe_types.h"
 #include "DNA_property_types.h"
 #include "DNA_rigidbody_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_vfont_types.h"
 #include "DNA_world_types.h"
 #include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
 #include "DNA_movieclip_types.h"
 #include "DNA_mask_types.h"
 
 #include "BKE_curve.h"
 #include "BKE_constraint.h"
 #include "BKE_global.h" // for G
+#include "BKE_group.h"
 #include "BKE_idcode.h"
 #include "BKE_library.h" // for  set_listbasepointers
+#include "BKE_library_override.h"
 #include "BKE_main.h"
 #include "BKE_node.h"
 #include "BKE_report.h"
 #include "BKE_fcurve.h"
 #include "BKE_pointcache.h"
 #include "BKE_mesh.h"
+#include "BKE_workspace.h"
 
 #ifdef USE_NODE_COMPAT_CUSTOMNODES
 #include "NOD_socket.h"  /* for sock->default_value data */
@@ -675,6 +685,25 @@ static void write_iddata(void *wd, const ID *id)
        if (id->properties && !ELEM(GS(id->name), ID_WM)) {
                IDP_WriteProperty(id->properties, wd);
        }
+
+       if (id->override_static) {
+               writestruct(wd, DATA, IDOverrideStatic, 1, id->override_static);
+
+               writelist(wd, DATA, IDOverrideStaticProperty, &id->override_static->properties);
+               for (IDOverrideStaticProperty *op = id->override_static->properties.first; op; op = op->next) {
+                       writedata(wd, DATA, strlen(op->rna_path) + 1, op->rna_path);
+
+                       writelist(wd, DATA, IDOverrideStaticPropertyOperation, &op->operations);
+                       for (IDOverrideStaticPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
+                               if (opop->subitem_reference_name) {
+                                       writedata(wd, DATA, strlen(opop->subitem_reference_name) + 1, opop->subitem_reference_name);
+                               }
+                               if (opop->subitem_local_name) {
+                                       writedata(wd, DATA, strlen(opop->subitem_local_name) + 1, opop->subitem_local_name);
+                               }
+                       }
+               }
+       }
 }
 
 static void write_previews(WriteData *wd, const PreviewImage *prv_orig)
@@ -1078,10 +1107,13 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
  * Take care using 'use_active_win', since we wont want the currently active window
  * to change which scene renders (currently only used for undo).
  */
-static void current_screen_compat(Main *mainvar, bScreen **r_screen, bool use_active_win)
+static void current_screen_compat(
+        Main *mainvar, bool use_active_win,
+        bScreen **r_screen, Scene **r_scene, ViewLayer **r_render_layer)
 {
        wmWindowManager *wm;
        wmWindow *window = NULL;
+       WorkSpace *workspace;
 
        /* find a global current screen in the first open window, to have
         * a reasonable default for reading in older versions */
@@ -1105,8 +1137,11 @@ static void current_screen_compat(Main *mainvar, bScreen **r_screen, bool use_ac
                        window = wm->windows.first;
                }
        }
+       workspace = (window) ? BKE_workspace_active_get(window->workspace_hook) : NULL;
 
-       *r_screen = (window) ? window->screen : NULL;
+       *r_screen = (window) ? BKE_workspace_active_screen_get(window->workspace_hook) : NULL;
+       *r_scene = (window) ? window->scene : NULL;
+       *r_render_layer = (window) ? BKE_workspace_view_layer_get(workspace, *r_scene) : NULL;
 }
 
 typedef struct RenderInfo {
@@ -1122,13 +1157,11 @@ static void write_renderinfo(WriteData *wd, Main *mainvar)
 {
        bScreen *curscreen;
        Scene *sce, *curscene = NULL;
+       ViewLayer *render_layer;
        RenderInfo data;
 
        /* XXX in future, handle multiple windows with multiple screens? */
-       current_screen_compat(mainvar, &curscreen, false);
-       if (curscreen) {
-               curscene = curscreen->scene;
-       }
+       current_screen_compat(mainvar, false, &curscreen, &curscene, &render_layer);
 
        for (sce = mainvar->scene.first; sce; sce = sce->id.next) {
                if (sce->id.lib == NULL && (sce == curscene || (sce->r.scemode & R_BG_RENDER))) {
@@ -1313,9 +1346,13 @@ static void write_particlesettings(WriteData *wd, ParticleSettings *part)
                        if (dw->ob != NULL) {
                                dw->index = 0;
                                if (part->dup_group) { /* can be NULL if lining fails or set to None */
-                                       for (GroupObject *go = part->dup_group->gobject.first;
-                                            go && go->ob != dw->ob;
-                                            go = go->next, dw->index++);
+                                       FOREACH_GROUP_OBJECT(part->dup_group, object)
+                                       {
+                                               if (object != dw->ob) {
+                                                       dw->index++;
+                                               }
+                                       }
+                                       FOREACH_GROUP_OBJECT_END
                                }
                        }
                        writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
@@ -1684,6 +1721,13 @@ static void write_defgroups(WriteData *wd, ListBase *defbase)
        }
 }
 
+static void write_fmaps(WriteData *wd, ListBase *fbase)
+{
+       for (bFaceMap *fmap = fbase->first; fmap; fmap = fmap->next) {
+               writestruct(wd, DATA, bFaceMap, 1, fmap);
+       }
+}
+
 static void write_modifiers(WriteData *wd, ListBase *modbase)
 {
        ModifierData *md;
@@ -1721,6 +1765,8 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
                        SmokeModifierData *smd = (SmokeModifierData *)md;
 
                        if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
+                               writestruct(wd, DATA, SmokeDomainSettings, 1, smd->domain);
+
                                if (smd->domain) {
                                        write_pointcaches(wd, &(smd->domain->ptcaches[0]));
 
@@ -1734,11 +1780,8 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
                                        if (smd->domain->coba) {
                                                writestruct(wd, DATA, ColorBand, 1, smd->domain->coba);
                                        }
-                               }
 
-                               writestruct(wd, DATA, SmokeDomainSettings, 1, smd->domain);
 
-                               if (smd->domain) {
                                        /* cleanup the fake pointcache */
                                        BKE_ptcache_free_list(&smd->domain->ptcaches[1]);
                                        smd->domain->point_cache[1] = NULL;
@@ -1888,6 +1931,7 @@ static void write_object(WriteData *wd, Object *ob)
 
                write_pose(wd, ob->pose);
                write_defgroups(wd, &ob->defbase);
+               write_fmaps(wd, &ob->fmaps);
                write_constraints(wd, &ob->constraints);
                write_motionpath(wd, ob->mpath);
 
@@ -1970,6 +2014,10 @@ static void write_camera(WriteData *wd, Camera *cam)
                if (cam->adt) {
                        write_animdata(wd, cam->adt);
                }
+
+               for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
+                       writestruct(wd, DATA, CameraBGImage, 1, bgpic);
+               }
        }
 }
 
@@ -2120,6 +2168,10 @@ static void write_customdata(
                else if (layer->type == CD_GRID_PAINT_MASK) {
                        write_grid_paint_mask(wd, count, layer->data);
                }
+               else if (layer->type == CD_FACEMAP) {
+                       const int *layer_data = layer->data;
+                       writedata(wd, DATA, sizeof(*layer_data) * count, layer_data);
+               }
                else {
                        CustomData_file_write_info(layer->type, &structname, &structnum);
                        if (structnum) {
@@ -2534,6 +2586,55 @@ static void write_paint(WriteData *wd, Paint *p)
        }
 }
 
+static void write_scene_collection(WriteData *wd, SceneCollection *sc)
+{
+       writestruct(wd, DATA, SceneCollection, 1, sc);
+
+       writelist(wd, DATA, LinkData, &sc->objects);
+
+       for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+               write_scene_collection(wd, nsc);
+       }
+}
+
+static void write_layer_collections(WriteData *wd, ListBase *lb)
+{
+       for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+               writestruct(wd, DATA, LayerCollection, 1, lc);
+
+               writelist(wd, DATA, LinkData, &lc->object_bases);
+               writelist(wd, DATA, CollectionOverride, &lc->overrides);
+
+               if (lc->properties) {
+                       IDP_WriteProperty(lc->properties, wd);
+               }
+
+               write_layer_collections(wd, &lc->layer_collections);
+       }
+}
+
+static void write_view_layer(WriteData *wd, ViewLayer *view_layer)
+{
+       writestruct(wd, DATA, ViewLayer, 1, view_layer);
+       writelist(wd, DATA, Base, &view_layer->object_bases);
+       if (view_layer->properties) {
+               IDP_WriteProperty(view_layer->properties, wd);
+       }
+
+       if (view_layer->id_properties) {
+               IDP_WriteProperty(view_layer->id_properties, wd);
+       }
+
+       for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) {
+               writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
+       }
+
+       for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) {
+               writestruct(wd, DATA, FreestyleLineSet, 1, fls);
+       }
+       write_layer_collections(wd, &view_layer->layer_collections);
+}
+
 static void write_scene(WriteData *wd, Scene *sce)
 {
        /* write LibData */
@@ -2546,10 +2647,6 @@ static void write_scene(WriteData *wd, Scene *sce)
        write_keyingsets(wd, &sce->keyingsets);
 
        /* direct data */
-       for (Base *base = sce->base.first; base; base = base->next) {
-               writestruct(wd, DATA, Base, 1, base);
-       }
-
        ToolSettings *tos = sce->toolsettings;
        writestruct(wd, DATA, ToolSettings, 1, tos);
        if (tos->vpaint) {
@@ -2697,24 +2794,6 @@ static void write_scene(WriteData *wd, Scene *sce)
                writestruct(wd, DATA, TimeMarker, 1, marker);
        }
 
-       /* writing dynamic list of TransformOrientations to the blend file */
-       for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) {
-               writestruct(wd, DATA, TransformOrientation, 1, ts);
-       }
-
-       for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
-               writestruct(wd, DATA, SceneRenderLayer, 1, srl);
-               if (srl->prop) {
-                       IDP_WriteProperty(srl->prop, wd);
-               }
-               for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
-                       writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
-               }
-               for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
-                       writestruct(wd, DATA, FreestyleLineSet, 1, fls);
-               }
-       }
-
        /* writing MultiView to the blend file */
        for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) {
                writestruct(wd, DATA, SceneRenderView, 1, srv);
@@ -2736,6 +2815,19 @@ static void write_scene(WriteData *wd, Scene *sce)
 
        write_previews(wd, sce->preview);
        write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
+       write_scene_collection(wd, sce->collection);
+
+       for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+               write_view_layer(wd, view_layer);
+       }
+
+       if (sce->layer_properties) {
+               IDP_WriteProperty(sce->layer_properties, wd);
+       }
+
+       if (sce->collection_properties) {
+               IDP_WriteProperty(sce->collection_properties, wd);
+       }
 }
 
 static void write_gpencil(WriteData *wd, bGPdata *gpd)
@@ -2777,8 +2869,16 @@ static void write_windowmanager(WriteData *wd, wmWindowManager *wm)
        write_iddata(wd, &wm->id);
 
        for (wmWindow *win = wm->windows.first; win; win = win->next) {
+
+               /* update deprecated screen member (for so loading in 2.7x uses the correct screen) */
+               win->screen = BKE_workspace_active_screen_get(win->workspace_hook);
+
                writestruct(wd, DATA, wmWindow, 1, win);
+               writestruct(wd, DATA, WorkSpaceInstanceHook, 1, win->workspace_hook);
                writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
+
+               /* data is written, clear deprecated data again */
+               win->screen = NULL;
        }
 }
 
@@ -2869,6 +2969,8 @@ static void write_screen(WriteData *wd, bScreen *sc)
        writestruct(wd, ID_SCRN, bScreen, 1, sc);
        write_iddata(wd, &sc->id);
 
+       write_previews(wd, sc->preview);
+
        /* direct data */
        for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) {
                writestruct(wd, DATA, ScrVert, 1, sv);
@@ -2915,11 +3017,8 @@ static void write_screen(WriteData *wd, bScreen *sc)
 
                        if (sl->spacetype == SPACE_VIEW3D) {
                                View3D *v3d = (View3D *)sl;
-                               BGpic *bgpic;
                                writestruct(wd, DATA, View3D, 1, v3d);
-                               for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
-                                       writestruct(wd, DATA, BGpic, 1, bgpic);
-                               }
+
                                if (v3d->localvd) {
                                        writestruct(wd, DATA, View3D, 1, v3d->localvd);
                                }
@@ -3117,6 +3216,19 @@ static void write_sound(WriteData *wd, bSound *sound)
        }
 }
 
+static void write_probe(WriteData *wd, LightProbe *prb)
+{
+       if (prb->id.us > 0 || wd->current) {
+               /* write LibData */
+               writestruct(wd, ID_LP, LightProbe, 1, prb);
+               write_iddata(wd, &prb->id);
+
+               if (prb->adt) {
+                       write_animdata(wd, prb->adt);
+               }
+       }
+}
+
 static void write_group(WriteData *wd, Group *group)
 {
        if (group->id.us > 0 || wd->current) {
@@ -3125,10 +3237,8 @@ static void write_group(WriteData *wd, Group *group)
                write_iddata(wd, &group->id);
 
                write_previews(wd, group->preview);
-
-               for (GroupObject *go = group->gobject.first; go; go = go->next) {
-                       writestruct(wd, DATA, GroupObject, 1, go);
-               }
+               write_scene_collection(wd, group->collection);
+               write_view_layer(wd, group->view_layer);
        }
 }
 
@@ -3662,6 +3772,18 @@ static void write_cachefile(WriteData *wd, CacheFile *cache_file)
        }
 }
 
+static void write_workspace(WriteData *wd, WorkSpace *workspace)
+{
+       ListBase *layouts = BKE_workspace_layouts_get(workspace);
+       ListBase *transform_orientations = BKE_workspace_transform_orientations_get(workspace);
+
+       writestruct(wd, ID_WS, WorkSpace, 1, workspace);
+       writelist(wd, DATA, WorkSpaceLayout, layouts);
+       writelist(wd, DATA, WorkSpaceDataRelation, &workspace->hook_layout_relations);
+       writelist(wd, DATA, WorkSpaceDataRelation, &workspace->scene_viewlayer_relations);
+       writelist(wd, DATA, TransformOrientation, transform_orientations);
+}
+
 /* Keep it last of write_foodata functions. */
 static void write_libraries(WriteData *wd, Main *main)
 {
@@ -3693,6 +3815,8 @@ static void write_libraries(WriteData *wd, Main *main)
                /* XXX needs rethink, just like save UI in undo files now - would be nice to append things only for the]
                 * quit.blend and temp saves */
                if (found_one) {
+                       /* Not overridable. */
+
                        writestruct(wd, ID_LI, Library, 1, main->curlib);
                        write_iddata(wd, &main->curlib->id);
 
@@ -3731,18 +3855,22 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
        const bool is_undo = (wd->current != NULL);
        FileGlobal fg;
        bScreen *screen;
+       Scene *scene;
+       ViewLayer *render_layer;
        char subvstr[8];
 
        /* prevent mem checkers from complaining */
        memset(fg.pad, 0, sizeof(fg.pad));
        memset(fg.filename, 0, sizeof(fg.filename));
        memset(fg.build_hash, 0, sizeof(fg.build_hash));
+       fg.pad1 = NULL;
 
-       current_screen_compat(mainvar, &screen, is_undo);
+       current_screen_compat(mainvar, is_undo, &screen, &scene, &render_layer);
 
        /* XXX still remap G */
        fg.curscreen = screen;
-       fg.curscene = screen ? screen->scene : NULL;
+       fg.curscene = scene;
+       fg.cur_view_layer = render_layer;
 
        /* prevent to save this, is not good convention, and feature with concerns... */
        fg.fileflags = (fileflags & ~G_FILE_FLAGS_RUNTIME);
@@ -3824,131 +3952,159 @@ static bool write_file_handle(
         * avoid thumbnail detecting changes because of this. */
        mywrite_flush(wd);
 
-       ListBase *lbarray[MAX_LIBARRAY];
-       int a = set_listbasepointers(mainvar, lbarray);
-       while (a--) {
-               ID *id = lbarray[a]->first;
+       OverrideStaticStorage *override_storage = !wd->current ? BKE_override_static_operations_store_initialize() : NULL;
 
-               if (id && GS(id->name) == ID_LI) {
-                       continue;  /* Libraries are handled separately below. */
-               }
+       /* This outer loop allows to save first datablocks from real mainvar, then the temp ones from override process,
+        * if needed, without duplicating whole code. */
+       Main *bmain = mainvar;
+       do {
+               ListBase *lbarray[MAX_LIBARRAY];
+               int a = set_listbasepointers(bmain, lbarray);
+               while (a--) {
+                       ID *id = lbarray[a]->first;
 
-               for (; id; id = id->next) {
-                       /* We should never attempt to write non-regular IDs (i.e. all kind of temp/runtime ones). */
-                       BLI_assert((id->tag & (LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT | LIB_TAG_NOT_ALLOCATED)) == 0);
+                       if (id && GS(id->name) == ID_LI) {
+                               continue;  /* Libraries are handled separately below. */
+                       }
 
-                       switch ((ID_Type)GS(id->name)) {
-                               case ID_WM:
-                                       write_windowmanager(wd, (wmWindowManager *)id);
-                                       break;
-                               case ID_SCR:
-                                       write_screen(wd, (bScreen *)id);
-                                       break;
-                               case ID_MC:
-                                       write_movieclip(wd, (MovieClip *)id);
-                                       break;
-                               case ID_MSK:
-                                       write_mask(wd, (Mask *)id);
-                                       break;
-                               case ID_SCE:
-                                       write_scene(wd, (Scene *)id);
-                                       break;
-                               case ID_CU:
-                                       write_curve(wd, (Curve *)id);
-                                       break;
-                               case ID_MB:
-                                       write_mball(wd, (MetaBall *)id);
-                                       break;
-                               case ID_IM:
-                                       write_image(wd, (Image *)id);
-                                       break;
-                               case ID_CA:
-                                       write_camera(wd, (Camera *)id);
-                                       break;
-                               case ID_LA:
-                                       write_lamp(wd, (Lamp *)id);
-                                       break;
-                               case ID_LT:
-                                       write_lattice(wd, (Lattice *)id);
-                                       break;
-                               case ID_VF:
-                                       write_vfont(wd, (VFont *)id);
-                                       break;
-                               case ID_KE:
-                                       write_key(wd, (Key *)id);
-                                       break;
-                               case ID_WO:
-                                       write_world(wd, (World *)id);
-                                       break;
-                               case ID_TXT:
-                                       write_text(wd, (Text *)id);
-                                       break;
-                               case ID_SPK:
-                                       write_speaker(wd, (Speaker *)id);
-                                       break;
-                               case ID_SO:
-                                       write_sound(wd, (bSound *)id);
-                                       break;
-                               case ID_GR:
-                                       write_group(wd, (Group *)id);
-                                       break;
-                               case ID_AR:
-                                       write_armature(wd, (bArmature *)id);
-                                       break;
-                               case ID_AC:
-                                       write_action(wd, (bAction *)id);
-                                       break;
-                               case ID_OB:
-                                       write_object(wd, (Object *)id);
-                                       break;
-                               case ID_MA:
-                                       write_material(wd, (Material *)id);
-                                       break;
-                               case ID_TE:
-                                       write_texture(wd, (Tex *)id);
-                                       break;
-                               case ID_ME:
-                                       write_mesh(wd, (Mesh *)id);
-                                       break;
-                               case ID_PA:
-                                       write_particlesettings(wd, (ParticleSettings *)id);
-                                       break;
-                               case ID_NT:
-                                       write_nodetree(wd, (bNodeTree *)id);
-                                       break;
-                               case ID_BR:
-                                       write_brush(wd, (Brush *)id);
-                                       break;
-                               case ID_PAL:
-                                       write_palette(wd, (Palette *)id);
-                                       break;
-                               case ID_PC:
-                                       write_paintcurve(wd, (PaintCurve *)id);
-                                       break;
-                               case ID_GD:
-                                       write_gpencil(wd, (bGPdata *)id);
-                                       break;
-                               case ID_LS:
-                                       write_linestyle(wd, (FreestyleLineStyle *)id);
-                                       break;
-                               case ID_CF:
-                                       write_cachefile(wd, (CacheFile *)id);
-                                       break;
-                               case ID_LI:
-                                       /* Do nothing, handled below - and should never be reached. */
-                                       BLI_assert(0);
-                                       break;
-                               case ID_IP:
-                                       /* Do nothing, deprecated. */
-                                       break;
-                               default:
-                                       /* Should never be reached. */
-                                       BLI_assert(0);
-                                       break;
+                       for (; id; id = id->next) {
+                               /* We should never attempt to write non-regular IDs (i.e. all kind of temp/runtime ones). */
+                               BLI_assert((id->tag & (LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT | LIB_TAG_NOT_ALLOCATED)) == 0);
+
+                               const bool do_override = !ELEM(override_storage, NULL, bmain) && id->override_static;
+
+                               if (do_override) {
+                                       BKE_override_static_operations_store_start(override_storage, id);
+                               }
+
+                               switch ((ID_Type)GS(id->name)) {
+                                       case ID_WM:
+                                               write_windowmanager(wd, (wmWindowManager *)id);
+                                               break;
+                                       case ID_WS:
+                                               write_workspace(wd, (WorkSpace *)id);
+                                               break;
+                                       case ID_SCR:
+                                               write_screen(wd, (bScreen *)id);
+                                               break;
+                                       case ID_MC:
+                                               write_movieclip(wd, (MovieClip *)id);
+                                               break;
+                                       case ID_MSK:
+                                               write_mask(wd, (Mask *)id);
+                                               break;
+                                       case ID_SCE:
+                                               write_scene(wd, (Scene *)id);
+                                               break;
+                                       case ID_CU:
+                                               write_curve(wd, (Curve *)id);
+                                               break;
+                                       case ID_MB:
+                                               write_mball(wd, (MetaBall *)id);
+                                               break;
+                                       case ID_IM:
+                                               write_image(wd, (Image *)id);
+                                               break;
+                                       case ID_CA:
+                                               write_camera(wd, (Camera *)id);
+                                               break;
+                                       case ID_LA:
+                                               write_lamp(wd, (Lamp *)id);
+                                               break;
+                                       case ID_LT:
+                                               write_lattice(wd, (Lattice *)id);
+                                               break;
+                                       case ID_VF:
+                                               write_vfont(wd, (VFont *)id);
+                                               break;
+                                       case ID_KE:
+                                               write_key(wd, (Key *)id);
+                                               break;
+                                       case ID_WO:
+                                               write_world(wd, (World *)id);
+                                               break;
+                                       case ID_TXT:
+                                               write_text(wd, (Text *)id);
+                                               break;
+                                       case ID_SPK:
+                                               write_speaker(wd, (Speaker *)id);
+                                               break;
+                                       case ID_LP:
+                                               write_probe(wd, (LightProbe *)id);
+                                               break;
+                                       case ID_SO:
+                                               write_sound(wd, (bSound *)id);
+                                               break;
+                                       case ID_GR:
+                                               write_group(wd, (Group *)id);
+                                               break;
+                                       case ID_AR:
+                                               write_armature(wd, (bArmature *)id);
+                                               break;
+                                       case ID_AC:
+                                               write_action(wd, (bAction *)id);
+                                               break;
+                                       case ID_OB:
+                                               write_object(wd, (Object *)id);
+                                               break;
+                                       case ID_MA:
+                                               write_material(wd, (Material *)id);
+                                               break;
+                                       case ID_TE:
+                                               write_texture(wd, (Tex *)id);
+                                               break;
+                                       case ID_ME:
+                                               write_mesh(wd, (Mesh *)id);
+                                               break;
+                                       case ID_PA:
+                                               write_particlesettings(wd, (ParticleSettings *)id);
+                                               break;
+                                       case ID_NT:
+                                               write_nodetree(wd, (bNodeTree *)id);
+                                               break;
+                                       case ID_BR:
+                                               write_brush(wd, (Brush *)id);
+                                               break;
+                                       case ID_PAL:
+                                               write_palette(wd, (Palette *)id);
+                                               break;
+                                       case ID_PC:
+                                               write_paintcurve(wd, (PaintCurve *)id);
+                                               break;
+                                       case ID_GD:
+                                               write_gpencil(wd, (bGPdata *)id);
+                                               break;
+                                       case ID_LS:
+                                               write_linestyle(wd, (FreestyleLineStyle *)id);
+                                               break;
+                                       case ID_CF:
+                                               write_cachefile(wd, (CacheFile *)id);
+                                               break;
+                                       case ID_LI:
+                                               /* Do nothing, handled below - and should never be reached. */
+                                               BLI_assert(0);
+                                               break;
+                                       case ID_IP:
+                                               /* Do nothing, deprecated. */
+                                               break;
+                                       default:
+                                               /* Should never be reached. */
+                                               BLI_assert(0);
+                                               break;
+                               }
+
+                               if (do_override) {
+                                       BKE_override_static_operations_store_end(override_storage, id);
+                               }
                        }
+
+                       mywrite_flush(wd);
                }
+       } while ((bmain != override_storage) && (bmain = override_storage));
 
-               mywrite_flush(wd);
+       if (override_storage) {
+               BKE_override_static_operations_store_finalize(override_storage);
+               override_storage = NULL;
        }
 
        /* Special handling, operating over split Mains... */