diff options
Diffstat (limited to 'source/blender/blenloader/intern')
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 603 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_260.c | 1 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_280.c | 824 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_legacy.c | 10 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 65 |
5 files changed, 861 insertions, 642 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 85c67047be0..44aa8a40993 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -123,13 +123,13 @@ #include "BKE_brush.h" #include "BKE_cachefile.h" #include "BKE_cloth.h" +#include "BKE_collection.h" #include "BKE_constraint.h" #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_effect.h" #include "BKE_fcurve.h" #include "BKE_global.h" // for G -#include "BKE_group.h" #include "BKE_layer.h" #include "BKE_library.h" // for which_libbase #include "BKE_library_idmap.h" @@ -258,9 +258,10 @@ static void *read_struct(FileData *fd, BHead *bh, const char *blockname); static void direct_link_modifiers(FileData *fd, ListBase *lb); static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name); static BHead *find_bhead_from_idname(FileData *fd, const char *idname); + +#ifdef USE_COLLECTION_COMPAT_28 static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc); -static SceneCollection *get_scene_collection_active_or_create( - struct Scene *scene, struct ViewLayer *view_layer, const int flag); +#endif /* this function ensures that reports are printed, * in the case of libraray linking errors this is important! @@ -4835,7 +4836,7 @@ static void lib_link_object(FileData *fd, Main *main) } else { ob->dup_group = NULL; - ob->transflag &= ~OB_DUPLIGROUP; + ob->transflag &= ~OB_DUPLICOLLECTION; } ob->proxy = newlibadr_us(fd, ob->id.lib, ob->proxy); @@ -5343,9 +5344,6 @@ static void direct_link_object(FileData *fd, Object *ob) { PartEff *paf; - /* weak weak... this was only meant as draw flag, now is used in give_base_to_objects too */ - ob->flag &= ~OB_FROMGROUP; - /* XXX This should not be needed - but seems like it can happen in some cases, so for now play safe... */ ob->proxy_from = NULL; @@ -5543,6 +5541,208 @@ static void direct_link_object(FileData *fd, Object *ob) ob->preview = direct_link_preview_image(fd, ob->preview); } +static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *view_settings) +{ + view_settings->curve_mapping = newdataadr(fd, view_settings->curve_mapping); + + if (view_settings->curve_mapping) + direct_link_curvemapping(fd, view_settings->curve_mapping); +} + +/* ***************** READ VIEW LAYER *************** */ + +static void direct_link_layer_collections(FileData *fd, ListBase *lb, bool master) +{ + link_list(fd, lb); + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { +#ifdef USE_COLLECTION_COMPAT_28 + lc->scene_collection = newdataadr(fd, lc->scene_collection); +#endif + + /* Master collection is not a real datablock. */ + if (master) { + lc->collection = newdataadr(fd, lc->collection); + } + + direct_link_layer_collections(fd, &lc->layer_collections, false); + } +} + +static void direct_link_view_layer(FileData *fd, ViewLayer *view_layer) +{ + view_layer->stats = NULL; + link_list(fd, &view_layer->object_bases); + view_layer->basact = newdataadr(fd, view_layer->basact); + + direct_link_layer_collections(fd, &view_layer->layer_collections, true); + view_layer->active_collection = newdataadr(fd, view_layer->active_collection); + + view_layer->id_properties = newdataadr(fd, view_layer->id_properties); + IDP_DirectLinkGroup_OrFree(&view_layer->id_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + + link_list(fd, &(view_layer->freestyle_config.modules)); + link_list(fd, &(view_layer->freestyle_config.linesets)); + + BLI_listbase_clear(&view_layer->drawdata); + view_layer->object_bases_array = NULL; + view_layer->object_bases_hash = NULL; +} + +static void lib_link_layer_collection(FileData *fd, Library *lib, LayerCollection *layer_collection, bool master) +{ + /* Master collection is not a real datablock. */ + if (!master) { + layer_collection->collection = newlibadr(fd, lib, layer_collection->collection); + } + + for (LayerCollection *layer_collection_nested = layer_collection->layer_collections.first; + layer_collection_nested != NULL; + layer_collection_nested = layer_collection_nested->next) + { + lib_link_layer_collection(fd, lib, layer_collection_nested, false); + } +} + +static void lib_link_view_layer(FileData *fd, Library *lib, ViewLayer *view_layer) +{ + /* tag scene layer to update for collection tree evaluation */ + view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY; + + for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) { + fmc->script = newlibadr(fd, lib, fmc->script); + } + + for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) { + fls->linestyle = newlibadr_us(fd, lib, fls->linestyle); + fls->group = newlibadr_us(fd, lib, fls->group); + } + + for (Base *base = view_layer->object_bases.first, *base_next = NULL; base; base = base_next) { + base_next = base->next; + + /* we only bump the use count for the collection objects */ + base->object = newlibadr(fd, lib, base->object); + base->flag |= BASE_DIRTY_ENGINE_SETTINGS; + + if (base->object == NULL) { + /* Free in case linked object got lost. */ + BLI_freelinkN(&view_layer->object_bases, base); + } + } + + for (LayerCollection *layer_collection = view_layer->layer_collections.first; + layer_collection != NULL; + layer_collection = layer_collection->next) + { + lib_link_layer_collection(fd, lib, layer_collection, true); + } + + IDP_LibLinkProperty(view_layer->id_properties, fd); +} + +/* ***************** READ COLLECTION *************** */ + +#ifdef USE_COLLECTION_COMPAT_28 +static void direct_link_scene_collection(FileData *fd, SceneCollection *sc) +{ + link_list(fd, &sc->objects); + link_list(fd, &sc->scene_collections); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + direct_link_scene_collection(fd, nsc); + } +} + +static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollection *sc) +{ + for (LinkData *link = sc->objects.first; link; link = link->next) { + link->data = newlibadr_us(fd, lib, link->data); + BLI_assert(link->data); + } + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + lib_link_scene_collection(fd, lib, nsc); + } +} +#endif + +static void direct_link_collection(FileData *fd, Collection *collection) +{ + link_list(fd, &collection->gobject); + link_list(fd, &collection->children); + + collection->preview = direct_link_preview_image(fd, collection->preview); + + collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; + BLI_listbase_clear(&collection->object_cache); + BLI_listbase_clear(&collection->parents); + +#ifdef USE_COLLECTION_COMPAT_28 + /* This runs before the very first doversion. */ + if (collection->collection != NULL) { + collection->collection = newdataadr(fd, collection->collection); + direct_link_scene_collection(fd, collection->collection); + } + + if (collection->view_layer != NULL) { + collection->view_layer = newdataadr(fd, collection->view_layer); + direct_link_view_layer(fd, collection->view_layer); + } +#endif +} + +static void lib_link_collection_data(FileData *fd, Library *lib, Collection *collection) +{ + for (CollectionObject *cob = collection->gobject.first, *cob_next = NULL; cob; cob = cob_next) { + cob_next = cob->next; + cob->ob = newlibadr_us(fd, lib, cob->ob); + + if (cob->ob == NULL) { + BLI_assert(!"Collection linked object got lost"); // TODO: remove, only for testing now + BLI_freelinkN(&collection->gobject, cob); + } + } + + for (CollectionChild *child = collection->children.first, *child_next = NULL; child; child = child_next) { + child_next = child->next; + child->collection = newlibadr_us(fd, lib, child->collection); + + if (child->collection == NULL || + BKE_collection_find_cycle(collection, child->collection)) + { + BLI_assert(!"Collection child got lost"); // TODO: remove, only for testing now + BLI_freelinkN(&collection->children, child); + } + else { + CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), "CollectionParent"); + cparent->collection = collection; + BLI_addtail(&child->collection->parents, cparent); + } + } +} + +static void lib_link_collection(FileData *fd, Main *main) +{ + for (Collection *collection = main->collection.first; collection; collection = collection->id.next) { + if (collection->id.tag & LIB_TAG_NEED_LINK) { + collection->id.tag &= ~LIB_TAG_NEED_LINK; + IDP_LibLinkProperty(collection->id.properties, fd); + +#ifdef USE_COLLECTION_COMPAT_28 + if (collection->collection) { + lib_link_scene_collection(fd, collection->id.lib, collection->collection); + } + + if (collection->view_layer) { + lib_link_view_layer(fd, collection->id.lib, collection->view_layer); + } +#endif + + lib_link_collection_data(fd, collection->id.lib, collection); + } + } +} + /* ************ READ SCENE ***************** */ /* patch for missing scene IDs, can't be in do-versions */ @@ -5605,41 +5805,6 @@ static bool scene_validate_setscene__liblink(Scene *sce, const int totscene) } #endif -static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollection *sc) -{ - for (LinkData *link = sc->objects.first; link; link = link->next) { - link->data = newlibadr_us(fd, lib, link->data); - BLI_assert(link->data); - } - - for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { - lib_link_scene_collection(fd, lib, nsc); - } -} - -static void lib_link_view_layer(FileData *fd, Library *lib, ViewLayer *view_layer) -{ - /* tag scene layer to update for collection tree evaluation */ - view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY; - - for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) { - fmc->script = newlibadr(fd, lib, fmc->script); - } - - for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) { - fls->linestyle = newlibadr_us(fd, lib, fls->linestyle); - fls->group = newlibadr_us(fd, lib, fls->group); - } - - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - /* we only bump the use count for the collection objects */ - base->object = newlibadr(fd, lib, base->object); - base->flag |= BASE_DIRTY_ENGINE_SETTINGS; - } - - IDP_LibLinkProperty(view_layer->id_properties, fd); -} - static void lib_link_scene(FileData *fd, Main *main) { #ifdef USE_SETSCENE_CHECK @@ -5750,7 +5915,7 @@ static void lib_link_scene(FileData *fd, Main *main) BKE_sequencer_update_sound_bounds_all(sce); - /* rigidbody world relies on it's linked groups */ + /* rigidbody world relies on it's linked collections */ if (sce->rigidbody_world) { RigidBodyWorld *rbw = sce->rigidbody_world; if (rbw->group) @@ -5780,7 +5945,15 @@ static void lib_link_scene(FileData *fd, Main *main) /* Motion Tracking */ sce->clip = newlibadr_us(fd, sce->id.lib, sce->clip); - lib_link_scene_collection(fd, sce->id.lib, sce->collection); +#ifdef USE_COLLECTION_COMPAT_28 + if (sce->collection) { + lib_link_scene_collection(fd, sce->id.lib, sce->collection); + } +#endif + + if (sce->master_collection) { + lib_link_collection_data(fd, sce->id.lib, sce->master_collection); + } for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) { lib_link_view_layer(fd, sce->id.lib, view_layer); @@ -5881,57 +6054,6 @@ static void direct_link_sequence_modifiers(FileData *fd, ListBase *lb) } } -static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *view_settings) -{ - view_settings->curve_mapping = newdataadr(fd, view_settings->curve_mapping); - - if (view_settings->curve_mapping) - direct_link_curvemapping(fd, view_settings->curve_mapping); -} - -static void direct_link_scene_collection(FileData *fd, SceneCollection *sc) -{ - link_list(fd, &sc->objects); - link_list(fd, &sc->scene_collections); - - for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { - direct_link_scene_collection(fd, nsc); - } -} - -static void direct_link_layer_collections(FileData *fd, ListBase *lb) -{ - link_list(fd, lb); - for (LayerCollection *lc = lb->first; lc; lc = lc->next) { - lc->scene_collection = newdataadr(fd, lc->scene_collection); - - link_list(fd, &lc->object_bases); - - for (LinkData *link = lc->object_bases.first; link; link = link->next) { - link->data = newdataadr(fd, link->data); - } - - direct_link_layer_collections(fd, &lc->layer_collections); - } -} - -static void direct_link_view_layer(FileData *fd, ViewLayer *view_layer) -{ - view_layer->stats = NULL; - link_list(fd, &view_layer->object_bases); - view_layer->basact = newdataadr(fd, view_layer->basact); - direct_link_layer_collections(fd, &view_layer->layer_collections); - - view_layer->id_properties = newdataadr(fd, view_layer->id_properties); - IDP_DirectLinkGroup_OrFree(&view_layer->id_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - - link_list(fd, &(view_layer->freestyle_config.modules)); - link_list(fd, &(view_layer->freestyle_config.linesets)); - - BLI_listbase_clear(&view_layer->drawdata); - view_layer->object_bases_array = NULL; -} - /** * Workspaces store a render layer pointer which can only be read after scene is read. */ @@ -6206,11 +6328,18 @@ static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain) direct_link_curvemapping(fd, &sce->r.mblur_shutter_curve); +#ifdef USE_COLLECTION_COMPAT_28 /* this runs before the very first doversion */ if (sce->collection) { sce->collection = newdataadr(fd, sce->collection); direct_link_scene_collection(fd, sce->collection); } +#endif + + if (sce->master_collection) { + sce->master_collection = newdataadr(fd, sce->master_collection); + direct_link_collection(fd, sce->master_collection); + } /* insert into global old-new map for reading without UI (link_global accesses it again) */ link_glob_list(fd, &sce->view_layers); @@ -7553,71 +7682,6 @@ static void lib_link_sound(FileData *fd, Main *main) } } } -/* ***************** READ GROUP *************** */ - -static void direct_link_group(FileData *fd, Group *group) -{ - link_list(fd, &group->gobject); - - group->preview = direct_link_preview_image(fd, group->preview); - - /* This runs before the very first doversion. */ - if (group->collection != NULL) { - group->collection = newdataadr(fd, group->collection); - direct_link_scene_collection(fd, group->collection); - } - - if (group->view_layer != NULL) { - group->view_layer = newdataadr(fd, group->view_layer); - direct_link_view_layer(fd, group->view_layer); - } -} - -static void lib_link_group(FileData *fd, Main *main) -{ - for (Group *group = main->group.first; group; group = group->id.next) { - if (group->id.tag & LIB_TAG_NEED_LINK) { - group->id.tag &= ~LIB_TAG_NEED_LINK; - IDP_LibLinkProperty(group->id.properties, fd); - - if (group->view_layer == NULL) { - /* Old file, this is required for doversion. */ - bool add_us = false; - - GroupObject *go, *gon; - go = group->gobject.first; - while (go) { - gon = go->next; - go->ob = newlibadr_real_us(fd, group->id.lib, go->ob); - if (go->ob != NULL) { - go->ob->flag |= OB_FROMGROUP; - /* If group has an object, it increments user... */ - add_us = true; - } - else { - /* Remove NULL objects. */ - BLI_remlink(&group->gobject, go); - MEM_freeN(go); - } - go = gon; - } - - if (add_us) { - id_us_ensure_real(&group->id); - } - /* The rest of the read code is only for new files, skip it. */ - continue; - } - - lib_link_scene_collection(fd, group->id.lib, group->collection); - lib_link_view_layer(fd, group->id.lib, group->view_layer); - - if (!BLI_listbase_is_empty(&group->view_layer->object_bases)) { - id_us_ensure_real(&group->id); - } - } - } -} /* ***************** READ MOVIECLIP *************** */ @@ -8355,7 +8419,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short direct_link_lightprobe(fd, (LightProbe *)id); break; case ID_GR: - direct_link_group(fd, (Group *)id); + direct_link_collection(fd, (Collection *)id); break; case ID_AR: direct_link_armature(fd, (bArmature*)id); @@ -8563,7 +8627,7 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_speaker(fd, main); lib_link_lightprobe(fd, main); lib_link_sound(fd, main); - lib_link_group(fd, main); + lib_link_collection(fd, main); lib_link_armature(fd, main); lib_link_action(fd, main); lib_link_vfont(fd, main); @@ -8774,6 +8838,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) if (fd->memfile == NULL) { /* Do not apply in undo case! */ BKE_main_override_static_update(bfd->main); + BKE_collections_after_lib_link(bfd->main); } lib_verify_nodetree(bfd->main, true); @@ -9207,18 +9272,21 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting } } -static void expand_group(FileData *fd, Main *mainvar, Group *group) +static void expand_collection(FileData *fd, Main *mainvar, Collection *collection) { - GroupObject *go; - - for (go = group->gobject.first; go; go = go->next) { - expand_doit(fd, mainvar, go->ob); + for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) { + expand_doit(fd, mainvar, cob->ob); } - if (group->collection != NULL) { - expand_scene_collection(fd, mainvar, group->collection); + for (CollectionChild *child = collection->children.first; child; child = child->next) { + expand_doit(fd, mainvar, child->collection); } +#ifdef USE_COLLECTION_COMPAT_28 + if (collection->collection != NULL) { + expand_scene_collection(fd, mainvar, collection->collection); + } +#endif } static void expand_key(FileData *fd, Main *mainvar, Key *key) @@ -9531,16 +9599,18 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) } } +#ifdef USE_COLLECTION_COMPAT_28 static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc) { for (LinkData *link = sc->objects.first; link; link = link->next) { expand_doit(fd, mainvar, link->data); } - for (SceneCollection *nsc= sc->scene_collections.first; nsc; nsc = nsc->next) { + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { expand_scene_collection(fd, mainvar, nsc); } } +#endif static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) { @@ -9626,7 +9696,15 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) expand_doit(fd, mainvar, sce->clip); - expand_scene_collection(fd, mainvar, sce->collection); +#ifdef USE_COLLECTION_COMPAT_28 + if (sce->collection) { + expand_scene_collection(fd, mainvar, sce->collection); + } +#endif + + if (sce->master_collection) { + expand_collection(fd, mainvar, sce->master_collection); + } } static void expand_camera(FileData *fd, Main *mainvar, Camera *ca) @@ -9833,7 +9911,7 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) expand_action(fd, mainvar, (bAction *)id); // XXX deprecated - old animation system break; case ID_GR: - expand_group(fd, mainvar, (Group *)id); + expand_collection(fd, mainvar, (Collection *)id); break; case ID_NT: expand_nodetree(fd, mainvar, (bNodeTree *)id); @@ -9881,11 +9959,11 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) /* ***************************** */ -static bool object_in_any_scene(Main *mainvar, Object *ob) +static bool object_in_any_scene(Main *bmain, Object *ob) { Scene *sce; - for (sce = mainvar->scene.first; sce; sce = sce->id.next) { + for (sce = bmain->scene.first; sce; sce = sce->id.next) { if (BKE_scene_object_find(sce, ob)) { return true; } @@ -9894,25 +9972,34 @@ static bool object_in_any_scene(Main *mainvar, Object *ob) return false; } -static void give_base_to_objects( - Main *mainvar, Scene *scene, ViewLayer *view_layer, Library *lib, const short flag) +static Collection *get_collection_active( + Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag) +{ + if (flag & FILE_ACTIVE_COLLECTION) { + LayerCollection *lc = BKE_layer_collection_get_active(view_layer); + return lc->collection; + } + else { + return BKE_collection_add(bmain, scene->master_collection, NULL); + } +} + +static void add_loose_objects_to_scene( + Main *mainvar, Main *bmain, Scene *scene, ViewLayer *view_layer, Library *lib, const short flag) { - Object *ob; - Base *base; - SceneCollection *scene_collection = NULL; const bool is_link = (flag & FILE_LINK) != 0; BLI_assert(scene); - /* Give all objects which are LIB_TAG_INDIRECT a base, or for a group when *lib has been set. */ - for (ob = mainvar->object.first; ob; ob = ob->id.next) { + /* Give all objects which are LIB_TAG_INDIRECT a base, or for a collection when *lib has been set. */ + for (Object *ob = mainvar->object.first; ob; ob = ob->id.next) { if ((ob->id.tag & LIB_TAG_INDIRECT) && (ob->id.tag & LIB_TAG_PRE_EXISTING) == 0) { bool do_it = false; if (ob->id.us == 0) { do_it = true; } - else if (!is_link && (ob->id.lib == lib) && (object_in_any_scene(mainvar, ob) == 0)) { + else if (!is_link && (ob->id.lib == lib) && (object_in_any_scene(bmain, ob) == 0)) { /* When appending, make sure any indirectly loaded objects get a base, else they cant be accessed at all * (see T27437). */ do_it = true; @@ -9921,17 +10008,14 @@ static void give_base_to_objects( if (do_it) { CLAMP_MIN(ob->id.us, 0); - if (scene_collection == NULL) { - scene_collection = get_scene_collection_active_or_create(scene, view_layer, FILE_ACTIVE_COLLECTION); - } - - BKE_collection_object_add(&scene->id, scene_collection, ob); - base = BKE_view_layer_base_find(view_layer, ob); + Collection *active_collection = get_collection_active(bmain, scene, view_layer, FILE_ACTIVE_COLLECTION); + BKE_collection_object_add(bmain, active_collection, ob); + Base *base = BKE_view_layer_base_find(view_layer, ob); BKE_scene_object_base_flag_sync_from_base(base); if (flag & FILE_AUTOSELECT) { /* Note that link_object_postprocess() already checks for FILE_AUTOSELECT flag, - * but it will miss objects from non-instantiated groups... */ + * but it will miss objects from non-instantiated collections... */ if (base->flag & BASE_SELECTABLED) { base->flag |= BASE_SELECTED; BKE_scene_object_base_flag_sync_from_base(base); @@ -9946,42 +10030,45 @@ static void give_base_to_objects( } } -static void give_base_to_groups( - Main *mainvar, Scene *scene, ViewLayer *view_layer, Library *UNUSED(lib), const short UNUSED(flag)) +static void add_collections_to_scene( + Main *mainvar, Main *bmain, Scene *scene, ViewLayer *view_layer, Library *UNUSED(lib), const short flag) { - Group *group; - Base *base; - Object *ob; - SceneCollection *scene_collection; - - /* If the group is empty this function is not even called, so it's safe to ensure a collection at this point. */ - scene_collection = get_scene_collection_active_or_create(scene, view_layer, FILE_ACTIVE_COLLECTION); + Collection *active_collection = get_collection_active(bmain, scene, view_layer, FILE_ACTIVE_COLLECTION); /* Give all objects which are tagged a base. */ - for (group = mainvar->group.first; group; group = group->id.next) { - if (group->id.tag & LIB_TAG_DOIT) { - /* Any indirect group should not have been tagged. */ - BLI_assert((group->id.tag & LIB_TAG_INDIRECT) == 0); + for (Collection *collection = mainvar->collection.first; collection; collection = collection->id.next) { + if (collection->id.tag & LIB_TAG_DOIT) { + if (flag & FILE_GROUP_INSTANCE) { + /* Any indirect collection should not have been tagged. */ + BLI_assert((collection->id.tag & LIB_TAG_INDIRECT) == 0); + + /* BKE_object_add(...) messes with the selection. */ + Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2); + ob->type = OB_EMPTY; - /* BKE_object_add(...) messes with the selection. */ - ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2); - ob->type = OB_EMPTY; + BKE_collection_object_add(bmain, active_collection, ob); + Base *base = BKE_view_layer_base_find(view_layer, ob); - BKE_collection_object_add(&scene->id, scene_collection, ob); - base = BKE_view_layer_base_find(view_layer, ob); + if (base->flag & BASE_SELECTABLED) { + base->flag |= BASE_SELECTED; + } - if (base->flag & BASE_SELECTABLED) { - base->flag |= BASE_SELECTED; - } + BKE_scene_object_base_flag_sync_from_base(base); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + view_layer->basact = base; - BKE_scene_object_base_flag_sync_from_base(base); - DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); - view_layer->basact = base; + /* Assign the collection. */ + ob->dup_group = collection; + ob->transflag |= OB_DUPLICOLLECTION; + copy_v3_v3(ob->loc, scene->cursor.location); + } + else { + /* Add collection as child of active collection. */ + BKE_collection_child_add(bmain, active_collection, collection); - /* Assign the group. */ - ob->dup_group = group; - ob->transflag |= OB_DUPLIGROUP; - copy_v3_v3(ob->loc, scene->cursor.location); + collection->id.tag &= ~LIB_TAG_INDIRECT; + collection->id.tag |= LIB_TAG_EXTERN; + } } } } @@ -10055,35 +10142,19 @@ static ID *link_named_part( return id; } -static SceneCollection *get_scene_collection_active_or_create( - struct Scene *scene, struct ViewLayer *view_layer, const int flag) -{ - LayerCollection *lc = NULL; - - if (flag & FILE_ACTIVE_COLLECTION) { - lc = BKE_layer_collection_get_active_ensure(scene, view_layer); - } - else { - SceneCollection *sc = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL); - lc = BKE_collection_link(view_layer, sc); - } - - return lc->scene_collection; -} - -static void link_object_postprocess(ID *id, Scene *scene, ViewLayer *view_layer, const int flag) +static void link_object_postprocess(ID *id, Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag) { if (scene) { /* link to scene */ Base *base; Object *ob; - SceneCollection *sc; + Collection *collection; ob = (Object *)id; ob->mode = OB_MODE_OBJECT; - sc = get_scene_collection_active_or_create(scene, view_layer, flag); - BKE_collection_object_add(&scene->id, sc, ob); + collection = get_collection_active(bmain, scene, view_layer, flag); + BKE_collection_object_add(bmain, collection, ob); base = BKE_view_layer_base_find(view_layer, ob); BKE_scene_object_base_flag_sync_from_base(base); @@ -10121,11 +10192,11 @@ void BLO_library_link_copypaste(Main *mainl, BlendHandle *bh) id_sort_by_name(lb, id); if (bhead->code == ID_OB) { - /* Instead of instancing Base's directly, postpone until after groups are loaded - * otherwise the base's flag is set incorrectly when groups are used */ + /* Instead of instancing Base's directly, postpone until after collections are loaded + * otherwise the base's flag is set incorrectly when collections are used */ Object *ob = (Object *)id; ob->mode = OB_MODE_OBJECT; - /* ensure give_base_to_objects runs on this object */ + /* ensure add_loose_objects_to_scene runs on this object */ BLI_assert(id->us == 0); } } @@ -10134,17 +10205,16 @@ void BLO_library_link_copypaste(Main *mainl, BlendHandle *bh) static ID *link_named_part_ex( Main *mainl, FileData *fd, const short idcode, const char *name, const int flag, - Scene *scene, ViewLayer *view_layer) + Main *bmain, Scene *scene, ViewLayer *view_layer) { ID *id = link_named_part(mainl, fd, idcode, name, flag); if (id && (GS(id->name) == ID_OB)) { /* loose object: give a base */ - link_object_postprocess(id, scene, view_layer, flag); + link_object_postprocess(id, bmain, scene, view_layer, flag); } else if (id && (GS(id->name) == ID_GR)) { - /* tag as needing to be instantiated */ - if (flag & FILE_GROUP_INSTANCE) - id->tag |= LIB_TAG_DOIT; + /* tag as needing to be instantiated or linked */ + id->tag |= LIB_TAG_DOIT; } return id; @@ -10167,24 +10237,24 @@ ID *BLO_library_link_named_part(Main *mainl, BlendHandle **bh, const short idcod /** * Link a named datablock from an external blend file. - * Optionally instantiate the object/group in the scene when the flags are set. + * Optionally instantiate the object/collection in the scene when the flags are set. * * \param mainl The main database to link from (not the active one). * \param bh The blender file handle. * \param idcode The kind of datablock to link. * \param name The name of the datablock (without the 2 char ID prefix). * \param flag Options for linking, used for instantiating. - * \param scene The scene in which to instantiate objects/groups (if NULL, no instantiation is done). - * \param v3d The active View3D (only to define active layers for instantiated objects & groups, can be NULL). + * \param scene The scene in which to instantiate objects/collections (if NULL, no instantiation is done). + * \param v3d The active View3D (only to define active layers for instantiated objects & collections, can be NULL). * \return the linked ID when found. */ ID *BLO_library_link_named_part_ex( Main *mainl, BlendHandle **bh, const short idcode, const char *name, const int flag, - Scene *scene, ViewLayer *view_layer) + Main *bmain, Scene *scene, ViewLayer *view_layer) { FileData *fd = (FileData*)(*bh); - return link_named_part_ex(mainl, fd, idcode, name, flag, scene, view_layer); + return link_named_part_ex(mainl, fd, idcode, name, flag, bmain, scene, view_layer); } static void link_id_part(ReportList *reports, FileData *fd, Main *mainvar, ID *id, ID **r_id) @@ -10237,8 +10307,8 @@ static Main *library_link_begin(Main *mainvar, FileData **fd, const char *filepa (*fd)->mainlist = MEM_callocN(sizeof(ListBase), "FileData.mainlist"); - /* clear for group instantiating tag */ - BKE_main_id_tag_listbase(&(mainvar->group), LIB_TAG_DOIT, false); + /* clear for collection instantiating tag */ + BKE_main_id_tag_listbase(&(mainvar->collection), LIB_TAG_DOIT, false); /* make mains */ blo_split_main((*fd)->mainlist, mainvar); @@ -10297,7 +10367,7 @@ static void split_main_newid(Main *mainptr, Main *main_newid) } /* scene and v3d may be NULL. */ -static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene *scene, ViewLayer *view_layer) +static void library_link_end(Main *mainl, FileData **fd, const short flag, Main *bmain, Scene *scene, ViewLayer *view_layer) { Main *mainvar; Library *curlib; @@ -10327,6 +10397,7 @@ static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene mainl = NULL; /* blo_join_main free's mainl, cant use anymore */ lib_link_all(*fd, mainvar); + BKE_collections_after_lib_link(mainvar); /* Yep, second splitting... but this is a very cheap operation, so no big deal. */ blo_split_main((*fd)->mainlist, mainvar); @@ -10350,22 +10421,19 @@ static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene lib_verify_nodetree(mainvar, false); fix_relpaths_library(G.main->name, mainvar); /* make all relative paths, relative to the open blend file */ - /* Give a base to loose objects. If group append, do it for objects too. - * Only directly linked objects & groups are instantiated by `BLO_library_link_named_part_ex()` & co, + /* Give a base to loose objects and collections. + * Only directly linked objects & collections are instantiated by `BLO_library_link_named_part_ex()` & co, * here we handle indirect ones and other possible edge-cases. */ if (scene) { - give_base_to_objects(mainvar, scene, view_layer, curlib, flag); - - if (flag & FILE_GROUP_INSTANCE) { - give_base_to_groups(mainvar, scene, view_layer, curlib, flag); - } + add_collections_to_scene(mainvar, bmain, scene, view_layer, curlib, flag); + add_loose_objects_to_scene(mainvar, bmain, scene, view_layer, curlib, flag); } else { /* printf("library_append_end, scene is NULL (objects wont get bases)\n"); */ } - /* clear group instantiating tag */ - BKE_main_id_tag_listbase(&(mainvar->group), LIB_TAG_DOIT, false); + /* clear collection instantiating tag */ + BKE_main_id_tag_listbase(&(mainvar->collection), LIB_TAG_DOIT, false); /* patch to prevent switch_endian happens twice */ if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) { @@ -10376,19 +10444,20 @@ static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene /** * Finalize linking from a given .blend file (library). - * Optionally instance the indirect object/group in the scene when the flags are set. + * Optionally instance the indirect object/collection in the scene when the flags are set. * \note Do not use \a bh after calling this function, it may frees it. * * \param mainl The main database to link from (not the active one). * \param bh The blender file handle (WARNING! may be freed by this function!). * \param flag Options for linking, used for instantiating. - * \param scene The scene in which to instantiate objects/groups (if NULL, no instantiation is done). - * \param view_layer The scene layer in which to instantiate objects/groups (if NULL, no instantiation is done). + * \param bmain The main database in which to instantiate objects/collections + * \param scene The scene in which to instantiate objects/collections (if NULL, no instantiation is done). + * \param view_layer The scene layer in which to instantiate objects/collections (if NULL, no instantiation is done). */ -void BLO_library_link_end(Main *mainl, BlendHandle **bh, int flag, Scene *scene, ViewLayer *view_layer) +void BLO_library_link_end(Main *mainl, BlendHandle **bh, int flag, Main *bmain, Scene *scene, ViewLayer *view_layer) { FileData *fd = (FileData*)(*bh); - library_link_end(mainl, &fd, flag, scene, view_layer); + library_link_end(mainl, &fd, flag, bmain, scene, view_layer); *bh = (BlendHandle*)fd; } diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 1d8bea40381..8e0795f7e34 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -2265,7 +2265,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main) if (!ELEM(so->outlinevis, SO_SCENES, - SO_GROUPS, SO_LIBRARIES, SO_SEQUENCE, SO_DATA_API)) diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index c3a634f1e74..43302408dc4 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -59,7 +59,6 @@ #include "BKE_constraint.h" #include "BKE_customdata.h" #include "BKE_freestyle.h" -#include "BKE_group.h" #include "BKE_idprop.h" #include "BKE_layer.h" #include "BKE_main.h" @@ -75,7 +74,6 @@ #include "MEM_guardedalloc.h" - static bScreen *screen_parent_find(const bScreen *screen) { /* can avoid lookup if screen state isn't maximized/full (parent and child store the same state) */ @@ -185,6 +183,162 @@ static void do_version_workspaces_after_lib_link(Main *bmain) } } +#ifdef USE_COLLECTION_COMPAT_28 +enum { + COLLECTION_DEPRECATED_VISIBLE = (1 << 0), + COLLECTION_DEPRECATED_VIEWPORT = (1 << 0), + COLLECTION_DEPRECATED_SELECTABLE = (1 << 1), + COLLECTION_DEPRECATED_DISABLED = (1 << 2), + COLLECTION_DEPRECATED_RENDER = (1 << 3), +}; + +static void do_version_view_layer_visibility(ViewLayer *view_layer) +{ + /* Convert from deprecated VISIBLE flag to DISABLED */ + LayerCollection *lc; + for (lc = view_layer->layer_collections.first; + lc; + lc = lc->next) + { + if (lc->flag & COLLECTION_DEPRECATED_DISABLED) { + lc->flag &= ~COLLECTION_DEPRECATED_DISABLED; + } + + if ((lc->flag & COLLECTION_DEPRECATED_VISIBLE) == 0) { + lc->flag |= COLLECTION_DEPRECATED_DISABLED; + } + + lc->flag |= COLLECTION_DEPRECATED_VIEWPORT | COLLECTION_DEPRECATED_RENDER; + } +} + +static void do_version_layer_collection_pre(ViewLayer *view_layer, + ListBase *lb, + GSet *enabled_set, + GSet *selectable_set) +{ + /* Convert from deprecated DISABLED to new layer collection and collection flags */ + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { + if (lc->scene_collection) { + if (!(lc->flag & COLLECTION_DEPRECATED_DISABLED)) { + BLI_gset_insert(enabled_set, lc->scene_collection); + } + if (lc->flag & COLLECTION_DEPRECATED_SELECTABLE) { + BLI_gset_insert(selectable_set, lc->scene_collection); + } + } + + do_version_layer_collection_pre(view_layer, &lc->layer_collections, enabled_set, selectable_set); + } +} + +static void do_version_layer_collection_post(ViewLayer *view_layer, + ListBase *lb, + GSet *enabled_set, + GSet *selectable_set, + GHash *collection_map) +{ + /* Apply layer collection exclude flags. */ + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { + if (!(lc->collection->flag & COLLECTION_IS_MASTER)) { + SceneCollection *sc = BLI_ghash_lookup(collection_map, lc->collection); + const bool enabled = (sc && BLI_gset_haskey(enabled_set, sc)); + const bool selectable = (sc && BLI_gset_haskey(selectable_set, sc)); + + if (!enabled) { + lc->flag |= LAYER_COLLECTION_EXCLUDE; + } + if (enabled && !selectable) { + lc->collection->flag |= COLLECTION_RESTRICT_SELECT; + } + } + + do_version_layer_collection_post(view_layer, &lc->layer_collections, enabled_set, selectable_set, collection_map); + } +} + +static void do_version_scene_collection_convert(Main *bmain, + SceneCollection *sc, + Collection *collection, + GHash *collection_map) +{ + if (collection_map) { + BLI_ghash_insert(collection_map, collection, sc); + } + + for (SceneCollection *nsc = sc->scene_collections.first; nsc;) { + SceneCollection *nsc_next = nsc->next; + Collection *ncollection = BKE_collection_add(bmain, collection, nsc->name); + do_version_scene_collection_convert(bmain, nsc, ncollection, collection_map); + nsc = nsc_next; + } + + for (LinkData *link = sc->objects.first; link; link = link->next) { + Object *ob = link->data; + if (ob) { + BKE_collection_object_add(bmain, collection, ob); + id_us_min(&ob->id); + } + } + + BLI_freelistN(&sc->objects); + MEM_freeN(sc); +} + +static void do_version_group_collection_to_collection(Main *bmain, Collection *group) +{ + /* Convert old 2.8 group collections to new unified collections. */ + if (group->collection) { + do_version_scene_collection_convert(bmain, group->collection, group, NULL); + } + + group->collection = NULL; + id_fake_user_set(&group->id); +} + +static void do_version_scene_collection_to_collection(Main *bmain, Scene *scene) +{ + /* Convert old 2.8 scene collections to new unified collections. */ + + /* Temporarily clear view layers so we don't do any layer collection syncing + * and destroy old flags that we want to restore. */ + ListBase view_layers = scene->view_layers; + BLI_listbase_clear(&scene->view_layers); + + if (!scene->master_collection) { + scene->master_collection = BKE_collection_master_add(); + } + + /* Convert scene collections. */ + GHash *collection_map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + if (scene->collection) { + do_version_scene_collection_convert(bmain, scene->collection, scene->master_collection, collection_map); + scene->collection = NULL; + } + + scene->view_layers = view_layers; + + /* Convert layer collections. */ + ViewLayer *view_layer; + for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + GSet *enabled_set = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + GSet *selectable_set = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + + do_version_layer_collection_pre(view_layer, &view_layer->layer_collections, enabled_set, selectable_set); + BKE_layer_collection_sync(scene, view_layer); + do_version_layer_collection_post(view_layer, &view_layer->layer_collections, enabled_set, selectable_set, collection_map); + + BLI_gset_free(enabled_set, NULL); + BLI_gset_free(selectable_set, NULL); + + BKE_layer_collection_sync(scene, view_layer); + } + + BLI_ghash_free(collection_map, NULL, NULL); +} +#endif + + enum { DO_VERSION_COLLECTION_VISIBLE = 0, DO_VERSION_COLLECTION_HIDE = 1, @@ -192,311 +346,348 @@ enum { DO_VERSION_COLLECTION_HIDE_ALL = 3, }; -void do_versions_after_linking_280(Main *main) +static void do_version_layers_to_collections(Main *bmain, Scene *scene) { - if (!MAIN_VERSION_ATLEAST(main, 280, 0)) { - for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { - /* since we don't have access to FileData we check the (always valid) first render layer instead */ - if (scene->view_layers.first == NULL) { - SceneCollection *sc_master = BKE_collection_master(&scene->id); - BLI_strncpy(sc_master->name, "Master Collection", sizeof(sc_master->name)); - - struct DoVersionSceneCollections { - SceneCollection *collections[20]; - int created; - const char *suffix; - int flag_viewport; - int flag_render; - } collections[] = - { - { - .collections = {NULL}, - .created = 0, - .suffix = "", - .flag_viewport = COLLECTION_SELECTABLE, - .flag_render = COLLECTION_SELECTABLE - }, - { - .collections = {NULL}, - .created = 0, - .suffix = " - Hide Viewport", - .flag_viewport = COLLECTION_SELECTABLE, - .flag_render = COLLECTION_SELECTABLE - }, - { - .collections = {NULL}, - .created = 0, - .suffix = " - Hide Render", - .flag_viewport = COLLECTION_SELECTABLE, - .flag_render = COLLECTION_SELECTABLE | COLLECTION_DISABLED - }, - { - .collections = {NULL}, - .created = 0, - .suffix = " - Hide Render All", - .flag_viewport = COLLECTION_SELECTABLE | COLLECTION_DISABLED, - .flag_render = COLLECTION_SELECTABLE | COLLECTION_DISABLED - } - }; - - for (int layer = 0; layer < 20; layer++) { - for (Base *base = scene->base.first; base; base = base->next) { - if (base->lay & (1 << layer)) { - int collection_index = -1; - if ((base->object->restrictflag & OB_RESTRICT_VIEW) && - (base->object->restrictflag & OB_RESTRICT_RENDER)) - { - collection_index = DO_VERSION_COLLECTION_HIDE_ALL; - } - else if (base->object->restrictflag & OB_RESTRICT_VIEW) { - collection_index = DO_VERSION_COLLECTION_HIDE; - } - else if (base->object->restrictflag & OB_RESTRICT_RENDER) { - collection_index = DO_VERSION_COLLECTION_HIDE_RENDER; - } - else { - collection_index = DO_VERSION_COLLECTION_VISIBLE; - } + /* Since we don't have access to FileData we check the (always valid) first + * render layer instead. */ + if (!scene->master_collection) { + scene->master_collection = BKE_collection_master_add(); + } - /* Create collections when needed only. */ - if ((collections[collection_index].created & (1 << layer)) == 0) { - char name[MAX_NAME]; - - if ((collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) == 0) { - BLI_snprintf(name, - sizeof(sc_master->name), - "Collection %d%s", - layer + 1, - collections[DO_VERSION_COLLECTION_VISIBLE].suffix); - collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer] = - BKE_collection_add(&scene->id, sc_master, COLLECTION_TYPE_NONE, name); - collections[DO_VERSION_COLLECTION_VISIBLE].created |= (1 << layer); - } - - if (collection_index != DO_VERSION_COLLECTION_VISIBLE) { - SceneCollection *sc_parent; - sc_parent = collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer]; - BLI_snprintf(name, - sizeof(sc_master->name), - "Collection %d%s", - layer + 1, - collections[collection_index].suffix); - collections[collection_index].collections[layer] = BKE_collection_add( - &scene->id, - sc_parent, - COLLECTION_TYPE_NONE, - name); - collections[collection_index].created |= (1 << layer); - } - } + if (scene->view_layers.first) { + return; + } - BKE_collection_object_add( - &scene->id, collections[collection_index].collections[layer], base->object); - } + /* Create collections from layers. */ + Collection *collection_master = BKE_collection_master(scene); - if (base->flag & SELECT) { - base->object->flag |= SELECT; - } - else { - base->object->flag &= ~SELECT; - } - } + struct DoVersionSceneCollections { + Collection *collections[20]; + int created; + const char *suffix; + int flag; + } collections[] = + { + { + .collections = {NULL}, + .created = 0, + .suffix = "", + .flag = 0, + }, + { + .collections = {NULL}, + .created = 0, + .suffix = " - Hide Viewport", + .flag = COLLECTION_RESTRICT_VIEW, + }, + { + .collections = {NULL}, + .created = 0, + .suffix = " - Hide Render", + .flag = COLLECTION_RESTRICT_RENDER, + }, + { + .collections = {NULL}, + .created = 0, + .suffix = " - Hide Render All", + .flag = COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER, + } + }; + + for (int layer = 0; layer < 20; layer++) { + for (Base *base = scene->base.first; base; base = base->next) { + if (base->lay & (1 << layer)) { + int collection_index = -1; + if ((base->object->restrictflag & OB_RESTRICT_VIEW) && + (base->object->restrictflag & OB_RESTRICT_RENDER)) + { + collection_index = DO_VERSION_COLLECTION_HIDE_ALL; + } + else if (base->object->restrictflag & OB_RESTRICT_VIEW) { + collection_index = DO_VERSION_COLLECTION_HIDE; + } + else if (base->object->restrictflag & OB_RESTRICT_RENDER) { + collection_index = DO_VERSION_COLLECTION_HIDE_RENDER; + } + else { + collection_index = DO_VERSION_COLLECTION_VISIBLE; } - /* Re-order the nested hidden collections. */ - SceneCollection *scene_collection_parent = sc_master->scene_collections.first; + /* Create collections when needed only. */ + if ((collections[collection_index].created & (1 << layer)) == 0) { + char name[MAX_NAME]; - for (int layer = 0; layer < 20; layer++) { - if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) { + if ((collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) == 0) { + BLI_snprintf(name, + sizeof(collection_master->id.name), + "Collection %d%s", + layer + 1, + collections[DO_VERSION_COLLECTION_VISIBLE].suffix); - if ((collections[DO_VERSION_COLLECTION_HIDE].created & (1 << layer)) && - (collections[DO_VERSION_COLLECTION_HIDE].collections[layer] != - scene_collection_parent->scene_collections.first)) - { - BLI_listbase_swaplinks( - &scene_collection_parent->scene_collections, - collections[DO_VERSION_COLLECTION_HIDE].collections[layer], - scene_collection_parent->scene_collections.first); - } + Collection *collection = BKE_collection_add(bmain, collection_master, name); + collection->flag |= collections[DO_VERSION_COLLECTION_VISIBLE].flag; + collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer] = collection; + collections[DO_VERSION_COLLECTION_VISIBLE].created |= (1 << layer); - if ((collections[DO_VERSION_COLLECTION_HIDE_ALL].created & (1 << layer)) && - (collections[DO_VERSION_COLLECTION_HIDE_ALL].collections[layer] != - scene_collection_parent->scene_collections.last)) - { - BLI_listbase_swaplinks( - &scene_collection_parent->scene_collections, - collections[DO_VERSION_COLLECTION_HIDE_ALL].collections[layer], - scene_collection_parent->scene_collections.last); + if (!(scene->lay & (1 << layer))) { + collection->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER; } + } - scene_collection_parent = scene_collection_parent->next; + if (collection_index != DO_VERSION_COLLECTION_VISIBLE) { + Collection *collection_parent; + collection_parent = collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer]; + BLI_snprintf(name, + sizeof(collection_master->id.name), + "Collection %d%s", + layer + 1, + collections[collection_index].suffix); + + Collection *collection = BKE_collection_add(bmain, collection_parent, name); + collection->flag |= collections[collection_index].flag; + collections[collection_index].collections[layer] = collection; + collections[collection_index].created |= (1 << layer); + + if (!(scene->lay & (1 << layer))) { + collection->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER; + } } } - BLI_assert(scene_collection_parent == NULL); - /* Handle legacy render layers. */ - { - for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) { - - ViewLayer *view_layer = BKE_view_layer_add(scene, srl->name); - - if (srl->samples != 0) { - /* It is up to the external engine to handle - * its own doversion in this case. */ - BKE_override_view_layer_int_add( - view_layer, - ID_SCE, - "samples", - srl->samples); - } + /* Note usually this would do slow collection syncing for view layers, + * but since no view layers exists yet at this point it's fast. */ + BKE_collection_object_add(bmain, + collections[collection_index].collections[layer], base->object); + } - if (srl->mat_override) { - BKE_override_view_layer_datablock_add( - view_layer, - ID_MA, - "self", - (ID *)srl->mat_override); - } + if (base->flag & SELECT) { + base->object->flag |= SELECT; + } + else { + base->object->flag &= ~SELECT; + } + } + } - if (srl->layflag & SCE_LAY_DISABLE) { - view_layer->flag &= ~VIEW_LAYER_RENDER; - } + /* Re-order the nested hidden collections. */ + CollectionChild *child_parent = collection_master->children.first; + Collection *collection_parent = (child_parent) ? child_parent->collection : NULL; - if ((srl->layflag & SCE_LAY_FRS) == 0) { - view_layer->flag &= ~VIEW_LAYER_FREESTYLE; - } + for (int layer = 0; layer < 20; layer++) { + if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) { + CollectionChild *hide_child = BLI_findptr(&collection_parent->children, collections[DO_VERSION_COLLECTION_HIDE].collections[layer], offsetof(CollectionChild, collection)); - /* XXX If we are to keep layflag it should be merged with flag (dfelinto). */ - view_layer->layflag = srl->layflag; - /* XXX Not sure if we should keep the passes (dfelinto). */ - view_layer->passflag = srl->passflag; - view_layer->pass_xor = srl->pass_xor; - view_layer->pass_alpha_threshold = srl->pass_alpha_threshold; + if ((collections[DO_VERSION_COLLECTION_HIDE].created & (1 << layer)) && + (hide_child != collection_parent->children.first)) + { + BLI_listbase_swaplinks( + &collection_parent->children, + hide_child, + collection_parent->children.first); + } - BKE_freestyle_config_free(&view_layer->freestyle_config, true); - view_layer->freestyle_config = srl->freestyleConfig; - view_layer->id_properties = srl->prop; + CollectionChild *hide_all_child = BLI_findptr(&collection_parent->children, collections[DO_VERSION_COLLECTION_HIDE_ALL].collections[layer], offsetof(CollectionChild, collection)); - /* unlink master collection */ - BKE_collection_unlink(view_layer, view_layer->layer_collections.first); + if ((collections[DO_VERSION_COLLECTION_HIDE_ALL].created & (1 << layer)) && + (hide_all_child != collection_parent->children.last)) + { + BLI_listbase_swaplinks( + &collection_parent->children, + hide_all_child, + collection_parent->children.last); + } - /* Add new collection bases. */ - for (int layer = 0; layer < 20; layer++) { - if ((scene->lay & srl->lay & ~(srl->lay_exclude) & (1 << layer)) || - (srl->lay_zmask & (scene->lay | srl->lay_exclude) & (1 << layer))) - { - if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) { - - LayerCollection *layer_collection_parent; - layer_collection_parent = BKE_collection_link( - view_layer, - collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer]); - - if (srl->lay_zmask & (1 << layer)) { - BKE_override_layer_collection_boolean_add( - layer_collection_parent, - ID_OB, - "cycles.is_holdout", - true); - } - - if ((srl->lay & (1 << layer)) == 0) { - BKE_override_layer_collection_boolean_add( - layer_collection_parent, - ID_OB, - "cycles_visibility.camera", - false); - } - - LayerCollection *layer_collection_child; - layer_collection_child = layer_collection_parent->layer_collections.first; - - for (int j = 1; j < 4; j++) { - if (collections[j].created & (1 << layer)) { - layer_collection_child->flag = COLLECTION_VIEWPORT | - COLLECTION_RENDER | - collections[j].flag_render; - layer_collection_child = layer_collection_child->next; - } - } - BLI_assert(layer_collection_child == NULL); - } - } - } + child_parent = child_parent->next; + collection_parent = (child_parent) ? child_parent->collection : NULL; + } + } + BLI_assert(collection_parent == NULL); - /* for convenience set the same active object in all the layers */ - if (scene->basact) { - view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object); - } + /* Handle legacy render layers. */ + bool have_override = false; - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if ((base->flag & BASE_SELECTABLED) && (base->object->flag & SELECT)) { - base->flag |= BASE_SELECTED; - } - } - } - } - BLI_freelistN(&scene->r.layers); + for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) { + ViewLayer *view_layer = BKE_view_layer_add(scene, srl->name); - ViewLayer *view_layer = BKE_view_layer_add(scene, "Viewport"); - /* If we ported all the original render layers, we don't need to make the viewport layer renderable. */ - if (!BLI_listbase_is_single(&scene->view_layers)) { - view_layer->flag &= ~VIEW_LAYER_RENDER; - } + if (srl->samples != 0) { + have_override = true; - /* If layer was not set, disable it. */ - LayerCollection *layer_collection_parent; - layer_collection_parent = - ((LayerCollection *)view_layer->layer_collections.first)->layer_collections.first; + /* It is up to the external engine to handle + * its own doversion in this case. */ + BKE_override_view_layer_int_add( + view_layer, + ID_SCE, + "samples", + srl->samples); + } - for (int layer = 0; layer < 20; layer++) { - if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) { - const bool is_disabled = (scene->lay & (1 << layer)) == 0; + if (srl->mat_override) { + have_override = true; - /* We only need to disable the parent collection. */ - if (is_disabled) { - layer_collection_parent->flag |= COLLECTION_DISABLED; - } + BKE_override_view_layer_datablock_add( + view_layer, + ID_MA, + "self", + (ID *)srl->mat_override); + } - LayerCollection *layer_collection_child; - layer_collection_child = layer_collection_parent->layer_collections.first; + if (srl->layflag & SCE_LAY_DISABLE) { + view_layer->flag &= ~VIEW_LAYER_RENDER; + } - for (int j = 1; j < 4; j++) { - if (collections[j].created & (1 << layer)) { - layer_collection_child->flag = COLLECTION_VIEWPORT | - COLLECTION_RENDER | - collections[j].flag_viewport; - layer_collection_child = layer_collection_child->next; - } - } - BLI_assert(layer_collection_child == NULL); - layer_collection_parent = layer_collection_parent->next; + if ((srl->layflag & SCE_LAY_FRS) == 0) { + view_layer->flag &= ~VIEW_LAYER_FREESTYLE; + } + + /* XXX If we are to keep layflag it should be merged with flag (dfelinto). */ + view_layer->layflag = srl->layflag; + /* XXX Not sure if we should keep the passes (dfelinto). */ + view_layer->passflag = srl->passflag; + view_layer->pass_xor = srl->pass_xor; + view_layer->pass_alpha_threshold = srl->pass_alpha_threshold; + + BKE_freestyle_config_free(&view_layer->freestyle_config, true); + view_layer->freestyle_config = srl->freestyleConfig; + view_layer->id_properties = srl->prop; + + /* Set exclusion and overrides. */ + for (int layer = 0; layer < 20; layer++) { + if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) { + Collection *collection = collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer]; + LayerCollection *lc = BKE_layer_collection_first_from_scene_collection(view_layer, collection); + + if (srl->lay_exclude & (1 << layer)) { + /* Disable excluded layer. */ + have_override = true; + lc->flag |= LAYER_COLLECTION_EXCLUDE; + for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) { + nlc->flag |= LAYER_COLLECTION_EXCLUDE; } } - BLI_assert(layer_collection_parent == NULL); + else if ((scene->lay & srl->lay & ~(srl->lay_exclude) & (1 << layer)) || + (srl->lay_zmask & (scene->lay | srl->lay_exclude) & (1 << layer))) + { + if (srl->lay_zmask & (1 << layer)) { + have_override = true; + + BKE_override_layer_collection_boolean_add( + lc, + ID_OB, + "cycles.is_holdout", + true); + } - /* convert active base */ - if (scene->basact) { - view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object); - } + if ((srl->lay & (1 << layer)) == 0) { + have_override = true; - /* convert selected bases */ - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if ((base->flag & BASE_SELECTABLED) && (base->object->flag & SELECT)) { - base->flag |= BASE_SELECTED; + BKE_override_layer_collection_boolean_add( + lc, + ID_OB, + "cycles_visibility.camera", + false); } + } - /* keep lay around for forward compatibility (open those files in 2.79) */ - base->lay = base->object->lay; + LayerCollection *nlc = lc->layer_collections.first; + for (int j = 1; j < 4; j++) { + if (collections[j].created & (1 << layer)) { + nlc = nlc->next; + } } + BLI_assert(nlc == NULL); + } + } + + /* for convenience set the same active object in all the layers */ + if (scene->basact) { + view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object); + } + + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTABLED) && (base->object->flag & SELECT)) { + base->flag |= BASE_SELECTED; + } + } + } + + BLI_freelistN(&scene->r.layers); + + /* If render layers included overrides, we also create a vanilla + * viewport layer without them. */ + if (have_override) { + ViewLayer *view_layer = BKE_view_layer_add(scene, "Viewport"); + + /* Make it first in the list. */ + BLI_remlink(&scene->view_layers, view_layer); + BLI_addhead(&scene->view_layers, view_layer); + + /* If we ported all the original render layers, we don't need to make the viewport layer renderable. */ + if (!BLI_listbase_is_single(&scene->view_layers)) { + view_layer->flag &= ~VIEW_LAYER_RENDER; + } + + /* convert active base */ + if (scene->basact) { + view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object); + } + + /* convert selected bases */ + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTABLED) && (base->object->flag & SELECT)) { + base->flag |= BASE_SELECTED; + } - /* remove bases once and for all */ - for (Base *base = scene->base.first; base; base = base->next) { - id_us_min(&base->object->id); + /* keep lay around for forward compatibility (open those files in 2.79) */ + base->lay = base->object->lay; + } + } + + /* remove bases once and for all */ + for (Base *base = scene->base.first; base; base = base->next) { + id_us_min(&base->object->id); + } + + BLI_freelistN(&scene->base); + scene->basact = NULL; +} + +void do_versions_after_linking_280(Main *main) +{ + bool use_collection_compat_28 = true; + + if (!MAIN_VERSION_ATLEAST(main, 280, 0)) { + use_collection_compat_28 = false; + + /* Convert group layer visibility flags to hidden nested collection. */ + for (Collection *collection = main->collection.first; collection; collection = collection->id.next) { + Collection *collection_hidden = NULL; + + if (collection->flag & (COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER)) { + continue; + } + + for (CollectionObject *cob = collection->gobject.first, *cob_next = NULL; cob; cob = cob_next) { + cob_next = cob->next; + Object *ob = cob->ob; + + if (!(ob->lay & collection->layer)) { + if (collection_hidden == NULL) { + collection_hidden = BKE_collection_add(main, collection, "Hidden"); + collection_hidden->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER; + } + + BKE_collection_object_add(main, collection_hidden, ob); + BKE_collection_object_remove(main, collection, ob, true); } - BLI_freelistN(&scene->base); - scene->basact = NULL; } + + /* Add fake user for all existing groups. */ + id_fake_user_set(&collection->id); + } + + /* Convert layers to collections. */ + for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { + do_version_layers_to_collections(main, scene); } } @@ -507,11 +698,11 @@ void do_versions_after_linking_280(Main *main) ViewLayer *layer = screen->scene->view_layers.first; for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { - for (SpaceLink *view_layer = sa->spacedata.first; view_layer; view_layer = view_layer->next) { - if (view_layer->spacetype == SPACE_OUTLINER) { - SpaceOops *soutliner = (SpaceOops *)view_layer; + for (SpaceLink *space = sa->spacedata.first; space; space = space->next) { + if (space->spacetype == SPACE_OUTLINER) { + SpaceOops *soutliner = (SpaceOops *)space; - soutliner->outlinevis = SO_COLLECTIONS; + soutliner->outlinevis = SO_VIEW_LAYER; if (BLI_listbase_count_at_most(&layer->layer_collections, 2) == 1) { if (soutliner->treestore == NULL) { @@ -566,7 +757,7 @@ void do_versions_after_linking_280(Main *main) } } - { + if (!MAIN_VERSION_ATLEAST(main, 280, 4)) { for (WorkSpace *workspace = main->workspaces.first; workspace; workspace = workspace->id.next) { if (workspace->view_layer) { /* During 2.8 work we temporarly stored view-layer in the @@ -584,42 +775,7 @@ void do_versions_after_linking_280(Main *main) } } - { - /* Since we don't have access to FileData we check the (always valid) master collection of the group. */ - for (Group *group = main->group.first; group; group = group->id.next) { - if (group->collection == NULL) { - BKE_group_init(group); - SceneCollection *sc = GROUP_MASTER_COLLECTION(group); - SceneCollection *sc_hidden = NULL; - - for (GroupObject *go = group->gobject.first; go; go = go->next) { - if (go->ob->lay & group->layer) { - BKE_collection_object_add(&group->id, sc, go->ob); - } - else { - if (sc_hidden == NULL) { - sc_hidden = BKE_collection_add(&group->id, sc, COLLECTION_TYPE_GROUP_INTERNAL, "Hidden"); - } - BKE_collection_object_add(&group->id, sc_hidden, go->ob); - } - } - - if (sc_hidden != NULL) { - LayerCollection *layer_collection_master, *layer_collection_hidden; - layer_collection_master = group->view_layer->layer_collections.first; - layer_collection_hidden = layer_collection_master->layer_collections.first; - layer_collection_hidden->flag |= COLLECTION_DISABLED; - } - } - - GroupObject *go; - while ((go = BLI_pophead(&group->gobject))) { - MEM_freeN(go); - } - } - } - - { + if (!MAIN_VERSION_ATLEAST(main, 280, 4)) { for (Object *object = main->object.first; object; object = object->id.next) { #ifndef VERSION_280_SUBVERSION_4 /* If any object already has an initialized value for @@ -687,38 +843,26 @@ void do_versions_after_linking_280(Main *main) } } } -} -static void do_version_view_layer_visibility(ViewLayer *view_layer) -{ - LayerCollection *layer_collection; - for (layer_collection = view_layer->layer_collections.first; - layer_collection; - layer_collection = layer_collection->next) - { - if (layer_collection->flag & COLLECTION_DISABLED) { - BKE_collection_enable(view_layer, layer_collection); - layer_collection->flag &= ~COLLECTION_DISABLED; +#ifdef USE_COLLECTION_COMPAT_28 + if (use_collection_compat_28 && !MAIN_VERSION_ATLEAST(main, 280, 14)) { + for (Collection *group = main->collection.first; group; group = group->id.next) { + do_version_group_collection_to_collection(main, group); } - if ((layer_collection->flag & (1 << 0)) == 0) { /* !COLLECTION_VISIBLE */ - layer_collection->flag |= COLLECTION_DISABLED; + for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { + do_version_scene_collection_to_collection(main, scene); } - layer_collection->flag |= COLLECTION_VIEWPORT | COLLECTION_RENDER; } +#endif } void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main) { + bool use_collection_compat_28 = true; if (!MAIN_VERSION_ATLEAST(main, 280, 0)) { - if (!DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "view_layers")) { - for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { - /* Master Collection */ - scene->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection"); - BLI_strncpy(scene->collection->name, "Master Collection", sizeof(scene->collection->name)); - } - } + use_collection_compat_28 = false; for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { scene->r.gauss = 1.5f; @@ -835,7 +979,9 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main) printf("You need to combine transparency and emission shaders to the converted Principled shader nodes.\n"); } - if ((DNA_struct_elem_find(fd->filesdna, "ViewLayer", "FreestyleConfig", "freestyle_config") == false) && +#ifdef USE_COLLECTION_COMPAT_28 + if (use_collection_compat_28 && + (DNA_struct_elem_find(fd->filesdna, "ViewLayer", "FreestyleConfig", "freestyle_config") == false) && DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "view_layers")) { for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { @@ -849,9 +995,11 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main) } } } +#endif } - if (!MAIN_VERSION_ATLEAST(main, 280, 3)) { +#ifdef USE_COLLECTION_COMPAT_28 + if (use_collection_compat_28 && !MAIN_VERSION_ATLEAST(main, 280, 3)) { for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { ViewLayer *view_layer; for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { @@ -859,12 +1007,13 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main) } } - for (Group *group = main->group.first; group; group = group->id.next) { + for (Collection *group = main->collection.first; group; group = group->id.next) { if (group->view_layer != NULL) { do_version_view_layer_visibility(group->view_layer); } } } +#endif if (!MAIN_VERSION_ATLEAST(main, 280, 6)) { if (DNA_struct_elem_find(fd->filesdna, "SpaceOops", "int", "filter") == false) { @@ -881,14 +1030,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main) if (!ELEM(so->outlinevis, SO_SCENES, - SO_GROUPS, SO_LIBRARIES, SO_SEQUENCE, SO_DATA_API, - SO_ID_ORPHANS, - SO_COLLECTIONS)) + SO_ID_ORPHANS)) { - so->outlinevis = SO_COLLECTIONS; + so->outlinevis = SO_VIEW_LAYER; } } } @@ -1079,7 +1226,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main) } } - { + if (!MAIN_VERSION_ATLEAST(main, 280, 14)) { if (!DNA_struct_elem_find(fd->filesdna, "Scene", "SceneDisplay", "display")) { /* Initialize new scene.SceneDisplay */ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { @@ -1309,6 +1456,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main) if (sl->spacetype == SPACE_OUTLINER) { SpaceOops *soops = (SpaceOops *)sl; soops->filter_id_type = ID_GR; + soops->outlinevis = SO_VIEW_LAYER; } } } diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 57530c6a004..9e0c3f3ccdc 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1661,7 +1661,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) Curve *cu; Material *ma; Mesh *me; - Group *group; + Collection *collection; Nurb *nu; BezTriple *bezt; BPoint *bp; @@ -1818,9 +1818,9 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) for (me = main->mesh.first; me; me = me->id.next) customdata_version_242(me); - for (group = main->group.first; group; group = group->id.next) - if (group->layer == 0) - group->layer = (1 << 20) - 1; + for (collection = main->collection.first; collection; collection = collection->id.next) + if (collection->layer == 0) + collection->layer = (1 << 20) - 1; /* now, subversion control! */ if (main->subversionfile < 3) { @@ -2471,7 +2471,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) idproperties_fix_group_lengths(main->vfont); idproperties_fix_group_lengths(main->text); idproperties_fix_group_lengths(main->sound); - idproperties_fix_group_lengths(main->group); + idproperties_fix_group_lengths(main->collection); idproperties_fix_group_lengths(main->armature); idproperties_fix_group_lengths(main->action); idproperties_fix_group_lengths(main->nodetree); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 507fe2e082c..8ea1205be38 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -162,9 +162,9 @@ #include "BKE_blender_version.h" #include "BKE_bpath.h" #include "BKE_curve.h" +#include "BKE_collection.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" @@ -1380,13 +1380,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 */ - FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object) + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object) { if (object != dw->ob) { dw->index++; } } - FOREACH_GROUP_OBJECT_END; + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } } writestruct(wd, DATA, ParticleDupliWeight, 1, dw); @@ -2356,6 +2356,31 @@ static void write_lamp(WriteData *wd, Lamp *la) } } +static void write_collection_nolib(WriteData *wd, Collection *collection) +{ + /* Shared function for collection datablocks and scene master collection. */ + write_previews(wd, collection->preview); + + for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) { + writestruct(wd, DATA, CollectionObject, 1, cob); + } + + for (CollectionChild *child = collection->children.first; child; child = child->next) { + writestruct(wd, DATA, CollectionChild, 1, child); + } +} + +static void write_collection(WriteData *wd, Collection *collection) +{ + if (collection->id.us > 0 || wd->use_memfile) { + /* write LibData */ + writestruct(wd, ID_GR, Collection, 1, collection); + write_iddata(wd, &collection->id); + + write_collection_nolib(wd, collection); + } +} + static void write_sequence_modifiers(WriteData *wd, ListBase *modbase) { SequenceModifierData *smd; @@ -2397,24 +2422,11 @@ 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); - write_layer_collections(wd, &lc->layer_collections); } } @@ -2623,12 +2635,16 @@ 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->master_collection) { + writestruct(wd, DATA, Collection, 1, sce->master_collection); + write_collection_nolib(wd, sce->master_collection); + } + /* Freed on doversion. */ BLI_assert(sce->layer_properties == NULL); } @@ -3046,19 +3062,6 @@ static void write_probe(WriteData *wd, LightProbe *prb) } } -static void write_group(WriteData *wd, Group *group) -{ - if (group->id.us > 0 || wd->use_memfile) { - /* write LibData */ - writestruct(wd, ID_GR, Group, 1, group); - write_iddata(wd, &group->id); - - write_previews(wd, group->preview); - write_scene_collection(wd, group->collection); - write_view_layer(wd, group->view_layer); - } -} - static void write_nodetree(WriteData *wd, bNodeTree *ntree) { if (ntree->id.us > 0 || wd->use_memfile) { @@ -3859,7 +3862,7 @@ static bool write_file_handle( write_sound(wd, (bSound *)id); break; case ID_GR: - write_group(wd, (Group *)id); + write_collection(wd, (Collection *)id); break; case ID_AR: write_armature(wd, (bArmature *)id); |