From 984cd29fdab0f3da4ad50d4df193b1c6710c904f Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 19 May 2017 19:34:15 +0200 Subject: Implement support for Append objects in Blender 2.8 Note for users ============== The active_layer option used for the filebrowser operators is now called active_collection. If there is no collections in the scenelayer or if this option is not selected we automatically create a new collection for the new objects. This is the same behaviour of trying to add a new object when there is no collection. Note for developers =================== For those cases I moved the object user count handling from readfile to the scene collection system. It's working fine for those, but we still need to re-visit this for Add objects, and Duplicate - In those cases the usercount is 2 when it should be 1. Reviewers: mont29, sergey Differential Revision: https://developer.blender.org/D2686 --- .../blender/blenkernel/intern/blender_copybuffer.c | 4 +- source/blender/blenloader/BLO_readfile.h | 5 +- source/blender/blenloader/intern/readfile.c | 114 ++++++++++++--------- source/blender/editors/space_file/filesel.c | 2 +- source/blender/editors/space_view3d/view3d_ops.c | 4 +- .../blender/windowmanager/intern/wm_files_link.c | 30 ++++-- 6 files changed, 92 insertions(+), 67 deletions(-) diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c index 964825f86d3..206b0f2a8cc 100644 --- a/source/blender/blenkernel/intern/blender_copybuffer.c +++ b/source/blender/blenkernel/intern/blender_copybuffer.c @@ -118,7 +118,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); + SceneLayer *sl = CTX_data_scene_layer(C); Main *mainl = NULL; Library *lib; BlendHandle *bh; @@ -143,7 +143,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re BLO_library_link_copypaste(mainl, bh); - BLO_library_link_end(mainl, &bh, flag, scene, v3d); + BLO_library_link_end(mainl, &bh, flag, scene, sl); /* mark all library linked objects to be updated */ BKE_main_lib_objects_recalc_all(bmain); diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index e6fc4703248..0213a4ee997 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -43,6 +43,7 @@ struct Main; struct MemFile; struct ReportList; struct Scene; +struct SceneLayer; struct UserDef; struct View3D; struct bContext; @@ -114,9 +115,9 @@ struct ID *BLO_library_link_named_part(struct Main *mainl, BlendHandle **bh, con struct ID *BLO_library_link_named_part_ex( struct Main *mainl, BlendHandle **bh, const short idcode, const char *name, const short flag, - struct Scene *scene, struct View3D *v3d, + struct Scene *scene, struct SceneLayer *sl, const bool use_placeholders, const bool force_indirect); -void BLO_library_link_end(struct Main *mainl, BlendHandle **bh, short flag, struct Scene *scene, struct View3D *v3d); +void BLO_library_link_end(struct Main *mainl, BlendHandle **bh, short flag, struct Scene *scene, struct SceneLayer *sl); void BLO_library_link_copypaste(struct Main *mainl, BlendHandle *bh); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index cd8cbabc2d7..60b77a25646 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9956,11 +9956,11 @@ static bool object_in_any_scene(Main *mainvar, Object *ob) return false; } -static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Library *lib, const short flag) +static void give_base_to_objects( + Main *mainvar, Scene *scene, SceneLayer *sl, SceneCollection *sc, Library *lib, const short flag) { Object *ob; - BaseLegacy *base; - const unsigned int active_lay = (flag & FILE_ACTIVELAY) ? BKE_screen_view3d_layer_active(v3d, scene) : 0; + Base *base; const bool is_link = (flag & FILE_LINK) != 0; BLI_assert(scene); @@ -9980,25 +9980,22 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra } if (do_it) { - base = MEM_callocN(sizeof(BaseLegacy), __func__); - BLI_addtail(&scene->base, base); + CLAMP_MIN(ob->id.us, 0); + + BKE_collection_object_add(scene, sc, ob); + base = BKE_scene_layer_base_find(sl, ob); + BKE_scene_object_base_flag_sync_from_base(base); - if (active_lay) { - ob->lay = active_lay; - } if (flag & FILE_AUTOSELECT) { /* Note that link_object_postprocess() already checks for FILE_AUTOSELECT flag, * but it will miss objects from non-instanciated groups... */ - ob->flag |= SELECT; + if (base->flag & BASE_SELECTABLED) { + base->flag |= BASE_SELECTED; + BKE_scene_base_flag_sync_from_base(base); + } /* do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level */ } - base->object = ob; - base->lay = ob->lay; - BKE_scene_base_flag_sync_from_object(base); - - CLAMP_MIN(ob->id.us, 0); - id_us_plus_no_lib((ID *)ob); ob->id.tag &= ~LIB_TAG_INDIRECT; ob->id.tag |= LIB_TAG_EXTERN; @@ -10008,12 +10005,12 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra } static void give_base_to_groups( - Main *mainvar, Scene *scene, View3D *v3d, Library *UNUSED(lib), const short UNUSED(flag)) + Main *mainvar, Scene *scene, SceneLayer *sl, SceneCollection *sc, + Library *UNUSED(lib), const short UNUSED(flag)) { Group *group; - BaseLegacy *base; + Base *base; Object *ob; - const unsigned int active_lay = BKE_screen_view3d_layer_active(v3d, scene); /* give all objects which are tagged a base */ for (group = mainvar->group.first; group; group = group->id.next) { @@ -10024,14 +10021,17 @@ static void give_base_to_groups( /* BKE_object_add(...) messes with the selection */ ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2); ob->type = OB_EMPTY; - ob->lay = active_lay; - /* assign the base */ - base = BKE_scene_base_add(scene, ob); - base->flag_legacy |= SELECT; - BKE_scene_base_flag_sync_from_base(base); + BKE_collection_object_add(scene, sc, ob); + base = BKE_scene_layer_base_find(sl, ob); + + 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); - scene->basact = base; + sl->basact = base; /* assign the group */ ob->dup_group = group; @@ -10108,31 +10108,42 @@ static ID *link_named_part( return id; } -static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const short flag) +static SceneCollection *get_scene_collection_active_or_create(struct Scene *scene, struct SceneLayer *sl, const short flag) { - if (scene) { - BaseLegacy *base; - Object *ob; + LayerCollection *lc = NULL; - base = MEM_callocN(sizeof(BaseLegacy), "app_nam_part"); - BLI_addtail(&scene->base, base); + if (flag & FILE_ACTIVELAY) { + lc = BKE_layer_collection_get_active_ensure(scene, sl); + } + else { + SceneCollection *sc = BKE_collection_add(scene, NULL, NULL); + lc = BKE_collection_link(sl, sc); + } - ob = (Object *)id; + return lc->scene_collection; +} - /* link at active layer (view3d if available in context, else scene one */ - if (flag & FILE_ACTIVELAY) { - ob->lay = BKE_screen_view3d_layer_active(v3d, scene); - } +static void link_object_postprocess(ID *id, Scene *scene, SceneLayer *sl, const short flag) +{ + if (scene) { + /* link to scene */ + Base *base; + Object *ob; + SceneCollection *sc; + ob = (Object *)id; ob->mode = OB_MODE_OBJECT; - base->lay = ob->lay; - base->object = ob; - base->flag_legacy = ob->flag; - id_us_plus_no_lib((ID *)ob); + + sc = get_scene_collection_active_or_create(scene, sl, flag); + BKE_collection_object_add(scene, sc, ob); + base = BKE_scene_layer_base_find(sl, ob); + BKE_scene_object_base_flag_sync_from_base(base); if (flag & FILE_AUTOSELECT) { - base->flag_legacy |= SELECT; - BKE_scene_base_flag_sync_from_base(base); + if (base->flag & BASE_SELECTABLED) { + base->flag |= BASE_SELECTED; + BKE_scene_base_flag_sync_from_base(base); + } /* do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level */ } } @@ -10175,12 +10186,12 @@ 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 short flag, - Scene *scene, View3D *v3d, const bool use_placeholders, const bool force_indirect) + Scene *scene, SceneLayer *sl, const bool use_placeholders, const bool force_indirect) { ID *id = link_named_part(mainl, fd, idcode, name, use_placeholders, force_indirect); if (id && (GS(id->name) == ID_OB)) { /* loose object: give a base */ - link_object_postprocess(id, scene, v3d, flag); + link_object_postprocess(id, scene, sl, flag); } else if (id && (GS(id->name) == ID_GR)) { /* tag as needing to be instantiated */ @@ -10224,11 +10235,11 @@ ID *BLO_library_link_named_part(Main *mainl, BlendHandle **bh, const short idcod ID *BLO_library_link_named_part_ex( Main *mainl, BlendHandle **bh, const short idcode, const char *name, const short flag, - Scene *scene, View3D *v3d, + Scene *scene, SceneLayer *sl, const bool use_placeholders, const bool force_indirect) { FileData *fd = (FileData*)(*bh); - return link_named_part_ex(mainl, fd, idcode, name, flag, scene, v3d, use_placeholders, force_indirect); + return link_named_part_ex(mainl, fd, idcode, name, flag, scene, sl, use_placeholders, force_indirect); } static void link_id_part(ReportList *reports, FileData *fd, Main *mainvar, ID *id, ID **r_id) @@ -10341,7 +10352,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, View3D *v3d) +static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene *scene, SceneLayer *sl) { Main *mainvar; Library *curlib; @@ -10397,10 +10408,11 @@ static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene * Only directly linked objects & groups 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, v3d, curlib, flag); + SceneCollection *sc = get_scene_collection_active_or_create(scene, sl, FILE_ACTIVELAY); + give_base_to_objects(mainvar, scene, sl, sc, curlib, flag); if (flag & FILE_GROUP_INSTANCE) { - give_base_to_groups(mainvar, scene, v3d, curlib, flag); + give_base_to_groups(mainvar, scene, sl, sc, curlib, flag); } } else { @@ -10426,12 +10438,12 @@ static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene * \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 v3d The active View3D (only to define active layers for instantiated objects & groups, can be NULL). + * \param sl The scene layer in which to instantiate objects/groups (if NULL, no instantiation is done). */ -void BLO_library_link_end(Main *mainl, BlendHandle **bh, short flag, Scene *scene, View3D *v3d) +void BLO_library_link_end(Main *mainl, BlendHandle **bh, short flag, Scene *scene, SceneLayer *sl) { FileData *fd = (FileData*)(*bh); - library_link_end(mainl, &fd, flag, scene, v3d); + library_link_end(mainl, &fd, flag, scene, sl); *bh = (BlendHandle*)fd; } diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 7abe5ff5070..96b241647b6 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -228,7 +228,7 @@ short ED_fileselect_set_params(SpaceFile *sfile) if (params->type == FILE_LOADLIB) { params->flag |= RNA_boolean_get(op->ptr, "link") ? FILE_LINK : 0; params->flag |= RNA_boolean_get(op->ptr, "autoselect") ? FILE_AUTOSELECT : 0; - params->flag |= RNA_boolean_get(op->ptr, "active_layer") ? FILE_ACTIVELAY : 0; + params->flag |= RNA_boolean_get(op->ptr, "active_collection") ? FILE_ACTIVELAY : 0; } if ((prop = RNA_struct_find_property(op->ptr, "display_type"))) { diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index f6abc40959b..e2b19075f95 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -119,7 +119,7 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op) if (RNA_boolean_get(op->ptr, "autoselect")) flag |= FILE_AUTOSELECT; - if (RNA_boolean_get(op->ptr, "active_layer")) + if (RNA_boolean_get(op->ptr, "active_collection")) flag |= FILE_ACTIVELAY; BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend"); @@ -152,7 +152,7 @@ static void VIEW3D_OT_pastebuffer(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select pasted objects"); - RNA_def_boolean(ot->srna, "active_layer", true, "Active Layer", "Put pasted objects on the active layer"); + RNA_def_boolean(ot->srna, "active_collection", true, "Active Collection", "Put pasted objects on the active collection"); } /* ************************** registration **********************************/ diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index e4f88b255ac..871c817384c 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -59,6 +59,7 @@ #include "BLO_readfile.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_remap.h" #include "BKE_global.h" @@ -68,6 +69,7 @@ #include "BKE_idcode.h" +#include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "IMB_colormanagement.h" @@ -131,7 +133,7 @@ static short wm_link_append_flag(wmOperator *op) if (RNA_boolean_get(op->ptr, "autoselect")) flag |= FILE_AUTOSELECT; - if (RNA_boolean_get(op->ptr, "active_layer")) + if (RNA_boolean_get(op->ptr, "active_collection")) flag |= FILE_ACTIVELAY; if ((prop = RNA_struct_find_property(op->ptr, "relative_path")) && RNA_property_boolean_get(op->ptr, prop)) flag |= FILE_RELPATH; @@ -212,7 +214,7 @@ static WMLinkAppendDataItem *wm_link_append_data_item_add( } static void wm_link_do( - WMLinkAppendData *lapp_data, ReportList *reports, Main *bmain, Scene *scene, View3D *v3d, + WMLinkAppendData *lapp_data, ReportList *reports, Main *bmain, Scene *scene, SceneLayer *sl, const bool use_placeholders, const bool force_indirect) { Main *mainl; @@ -261,7 +263,7 @@ static void wm_link_do( } new_id = BLO_library_link_named_part_ex( - mainl, &bh, item->idcode, item->name, flag, scene, v3d, use_placeholders, force_indirect); + mainl, &bh, item->idcode, item->name, flag, scene, sl, use_placeholders, force_indirect); if (new_id) { /* If the link is successful, clear item's libs 'todo' flags. @@ -271,7 +273,7 @@ static void wm_link_do( } } - BLO_library_link_end(mainl, &bh, flag, scene, v3d); + BLO_library_link_end(mainl, &bh, flag, scene, sl); BLO_blendhandle_close(bh); } } @@ -280,6 +282,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); PropertyRNA *prop; WMLinkAppendData *lapp_data; char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX]; @@ -334,8 +337,8 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) /* from here down, no error returns */ - if (scene && RNA_boolean_get(op->ptr, "autoselect")) { - BKE_scene_base_deselect_all(scene); + if (sl && RNA_boolean_get(op->ptr, "autoselect")) { + BKE_scene_layer_base_deselect_all(sl); } /* tag everything, all untagged data can be made local @@ -405,7 +408,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) /* XXX We'd need re-entrant locking on Main for this to work... */ /* BKE_main_lock(bmain); */ - wm_link_do(lapp_data, op->reports, bmain, scene, CTX_wm_view3d(C), false, false); + wm_link_do(lapp_data, op->reports, bmain, scene, sl, false, false); /* BKE_main_unlock(bmain); */ @@ -445,6 +448,15 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) * link into other scenes from this blend file */ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); + /* TODO(sergey): Use proper flag for tagging here. */ + + /* TODO (dalai): Temporary solution! + * Ideally we only need to tag the new objects themselves, not the scene. This way we'll avoid flush of + * collection properties to all objects and limit update to the particular object only. + * But afraid first we need to change collection evaluation in DEG according to depsgraph manifesto. + */ + DEG_id_tag_update(&scene->id, 0); + /* recreate dependency graph to include new objects */ DEG_scene_relations_rebuild(bmain, scene); @@ -471,8 +483,8 @@ static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link) prop = RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select new objects"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "active_layer", true, - "Active Layer", "Put new objects on the active layer"); + prop = RNA_def_boolean(ot->srna, "active_collection", true, + "Active Collection", "Put new objects on the active collection"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "instance_groups", is_link, "Instance Groups", "Create Dupli-Group instances for each group"); -- cgit v1.2.3