From 39b8a3306830957132931c2966c3c3afff5cdfb3 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 29 Nov 2017 15:05:03 +0100 Subject: Merge ID static override, part I: core changes in DNA, BKE and .blend read/write. See https://developer.blender.org/D2417 for details. Note that since static overrides rely heavily on RNA, this commit is essentially invisible from user PoV, more in next commits. --- source/blender/blenloader/intern/readfile.c | 51 +++++ source/blender/blenloader/intern/writefile.c | 294 +++++++++++++++------------ 2 files changed, 220 insertions(+), 125 deletions(-) (limited to 'source/blender/blenloader') diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 57dab868752..2d885fcec17 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -136,6 +136,7 @@ #include "BKE_layer.h" #include "BKE_library.h" // for which_libbase #include "BKE_library_idmap.h" +#include "BKE_library_override.h" #include "BKE_library_query.h" #include "BKE_idcode.h" #include "BKE_idprop.h" @@ -2214,6 +2215,42 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p /* ************ READ ID *************** */ +static void lib_link_id(FileData *fd, Main *main) +{ + ListBase *lbarray[MAX_LIBARRAY]; + int base_count, i; + + base_count = set_listbasepointers(main, lbarray); + + for (i = 0; i < base_count; i++) { + ListBase *lb = lbarray[i]; + ID *id; + + for (id = lb->first; id; id = id->next) { + if (id->override_static) { + id->override_static->reference = newlibadr_us(fd, id->lib, id->override_static->reference); + id->override_static->storage = newlibadr_us(fd, id->lib, id->override_static->storage); + } + } + } +} + +static void direct_link_id_override_property_operation_cb(FileData *fd, void *data) +{ + IDOverrideStaticPropertyOperation *opop = data; + + opop->subitem_reference_name = newdataadr(fd, opop->subitem_reference_name); + opop->subitem_local_name = newdataadr(fd, opop->subitem_local_name); +} + +static void direct_link_id_override_property_cb(FileData *fd, void *data) +{ + IDOverrideStaticProperty *op = data; + + op->rna_path = newdataadr(fd, op->rna_path); + link_list_ex(fd, &op->operations, direct_link_id_override_property_operation_cb); +} + static void direct_link_id(FileData *fd, ID *id) { /*link direct data of ID properties*/ @@ -2223,6 +2260,12 @@ static void direct_link_id(FileData *fd, ID *id) IDP_DirectLinkGroup_OrFree(&id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } id->py_instance = NULL; + + /* Link direct data of overrides. */ + if (id->override_static) { + id->override_static = newdataadr(fd, id->override_static); + link_list_ex(fd, &id->override_static->properties, direct_link_id_override_property_cb); + } } /* ************ READ CurveMapping *************** */ @@ -8683,6 +8726,8 @@ static void lib_link_all(FileData *fd, Main *main) { oldnewmap_sort(fd); + lib_link_id(fd, main); + /* No load UI for undo memfiles */ if (fd->memfile == NULL) { lib_link_windowmanager(fd, main); @@ -8908,6 +8953,12 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false); + /* Now that all our data-blocks are loaded, we can re-generate overrides from their references. */ + if (fd->memfile == NULL) { + /* Do not apply in undo case! */ + BKE_main_override_static_update(bfd->main); + } + lib_verify_nodetree(bfd->main, true); fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 6c39b0d486a..30ca75d7da4 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -170,6 +170,7 @@ #include "BKE_global.h" // for G #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" @@ -683,6 +684,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) @@ -3789,6 +3809,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); @@ -3923,137 +3945,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_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; + 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... */ -- cgit v1.2.3