diff options
58 files changed, 1373 insertions, 944 deletions
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index 49ecb94248e..23787756121 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -219,13 +219,8 @@ class OBJECT_PT_groups(ObjectButtonsPanel, Panel): row.operator("object.group_remove", text="", icon='X', emboss=False) row.menu("GROUP_MT_specials", icon='DOWNARROW_HLT', text="") - split = col.box().split() - - col = split.column() - col.prop(group, "layers", text="Dupli Visibility") - - col = split.column() - col.prop(group, "dupli_offset", text="") + row = col.box().row() + row.prop(group, "dupli_offset", text="") class OBJECT_PT_display(ObjectButtonsPanel, Panel): diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index 7003547ead2..5e93779b5f6 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -845,7 +845,7 @@ static void import_endjob(void *user_data) if (lc == NULL) { BLI_assert(BLI_listbase_count_ex(&view_layer->layer_collections, 1) == 0); /* when there is no collection linked to this ViewLayer, create one */ - SceneCollection *sc = BKE_collection_add(data->scene, NULL, NULL); + SceneCollection *sc = BKE_collection_add(&data->scene->id, NULL, COLLECTION_TYPE_NONE, NULL); lc = BKE_collection_link(view_layer, sc); } @@ -853,7 +853,7 @@ static void import_endjob(void *user_data) Object *ob = (*iter)->object(); ob->lay = data->scene->lay; - BKE_collection_object_add(data->scene, lc->scene_collection, ob); + BKE_collection_object_add(&data->scene->id, lc->scene_collection, ob); base = BKE_view_layer_base_find(view_layer, ob); BKE_view_layer_base_select(view_layer, base); diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index 52985d3ec56..c305a05ddd0 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -37,28 +37,33 @@ extern "C" { struct Base; struct BLI_Iterator; +struct Group; +struct ID; +struct LayerCollection; struct Main; struct Object; struct Scene; struct SceneCollection; -struct SceneCollection *BKE_collection_add(struct Scene *scene, struct SceneCollection *sc_parent, const char *name); -bool BKE_collection_remove(struct Scene *scene, struct SceneCollection *sc); -struct SceneCollection *BKE_collection_master(const struct Scene *scene); +struct SceneCollection *BKE_collection_add( + struct ID *owner_id, struct SceneCollection *sc_parent, const int type, const char *name); +bool BKE_collection_remove(struct ID *owner_id, struct SceneCollection *sc); +void BKE_collection_copy_data(struct SceneCollection *sc_dst, struct SceneCollection *sc_src, const int flag); +struct SceneCollection *BKE_collection_master(const struct ID *owner_id); void BKE_collection_rename(const struct Scene *scene, struct SceneCollection *sc, const char *name); -void BKE_collection_master_free(struct Scene *scene, const bool do_id_user); -void BKE_collection_object_add(const struct Scene *scene, struct SceneCollection *sc, struct Object *object); +void BKE_collection_master_free(struct ID *owner_id, const bool do_id_user); +bool BKE_collection_object_add(const struct ID *owner_id, struct SceneCollection *sc, struct Object *object); void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst); -void BKE_collection_object_remove(struct Main *bmain, const struct Scene *scene, struct SceneCollection *sc, struct Object *object, const bool free_us); -void BKE_collections_object_remove(struct Main *bmain, struct Scene *scene, struct Object *object, const bool free_us); -void BKE_collection_object_move(const struct Scene *scene, struct SceneCollection *sc_dst, struct SceneCollection *sc_src, struct Object *ob); +bool BKE_collection_object_remove(struct Main *bmain, struct ID *owner_id, struct SceneCollection *sc, struct Object *object, const bool free_us); +bool BKE_collections_object_remove(struct Main *bmain, struct ID *owner_id, struct Object *object, const bool free_us); +void BKE_collection_object_move(struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src, struct Object *ob); void BKE_collection_reinsert_after(const struct Scene *scene, struct SceneCollection *sc_reinsert, struct SceneCollection *sc_after); void BKE_collection_reinsert_into(struct SceneCollection *sc_reinsert, struct SceneCollection *sc_into); -bool BKE_collection_move_above(const struct Scene *scene, struct SceneCollection *sc_dst, struct SceneCollection *sc_src); -bool BKE_collection_move_below(const struct Scene *scene, struct SceneCollection *sc_dst, struct SceneCollection *sc_src); -bool BKE_collection_move_into(const struct Scene *scene, struct SceneCollection *sc_dst, struct SceneCollection *sc_src); +bool BKE_collection_move_above(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src); +bool BKE_collection_move_below(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src); +bool BKE_collection_move_into(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src); typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data); typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data); @@ -75,11 +80,11 @@ void BKE_scene_objects_iterator_begin(struct BLI_Iterator *iter, void *data_in); void BKE_scene_objects_iterator_next(struct BLI_Iterator *iter); void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter); -#define FOREACH_SCENE_COLLECTION(scene, _instance) \ +#define FOREACH_SCENE_COLLECTION(_id, _instance) \ ITER_BEGIN(BKE_scene_collections_iterator_begin, \ BKE_scene_collections_iterator_next, \ BKE_scene_collections_iterator_end, \ - scene, SceneCollection *, _instance) + _id, SceneCollection *, _instance) #define FOREACH_SCENE_COLLECTION_END \ ITER_END diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 1d35e6ab9fc..ac436876dc4 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -41,6 +41,7 @@ struct Object; struct Scene; void BKE_group_free(struct Group *group); +void BKE_group_init(struct Group *group); struct Group *BKE_group_add(struct Main *bmain, const char *name); void BKE_group_copy_data(struct Main *bmain, struct Group *group_dst, const struct Group *group_src, const int flag); struct Group *BKE_group_copy(struct Main *bmain, const struct Group *group); @@ -54,4 +55,24 @@ bool BKE_group_is_animated(struct Group *group, struct Object *parent); void BKE_group_handle_recalc_and_update(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *parent, struct Group *group); +#define FOREACH_GROUP_BASE(_group, _base) \ + for (Base *_base = (Base *)(_group)->view_layer->object_bases.first; \ + _base; \ + _base = _base->next) \ + { + +#define FOREACH_GROUP_BASE_END \ + } + +#define FOREACH_GROUP_OBJECT(_group, _object) \ + for (Base *_base = (Base *)(_group)->view_layer->object_bases.first; \ + _base; \ + _base = _base->next) \ + { \ + Object *_object = _base->object; \ + BLI_assert(_object != NULL); + +#define FOREACH_GROUP_OBJECT_END \ + } + #endif /* __BKE_GROUP_H__ */ diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index ecad9c21f99..55337fa5ed0 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -42,6 +42,7 @@ extern "C" { struct Base; struct EvaluationContext; +struct Group; struct ID; struct IDProperty; struct LayerCollection; @@ -59,6 +60,7 @@ void BKE_layer_exit(void); struct ViewLayer *BKE_view_layer_from_scene_get(const struct Scene *scene); struct ViewLayer *BKE_view_layer_from_workspace_get(const struct Scene *scene, const struct WorkSpace *workspace); struct ViewLayer *BKE_view_layer_add(struct Scene *scene, const char *name); +struct ViewLayer *BKE_view_layer_group_add(struct Group *group); /* DEPRECATED */ struct ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const struct Scene *scene); @@ -68,12 +70,16 @@ void BKE_view_layer_free(struct ViewLayer *view_layer); void BKE_view_layer_selected_objects_tag(struct ViewLayer *view_layer, const int tag); struct Object *BKE_view_layer_camera_find(struct ViewLayer *view_layer); -struct ViewLayer *BKE_view_layer_find_from_collection(const struct Scene *scene, struct LayerCollection *lc); +struct ViewLayer *BKE_view_layer_first_from_id(const struct ID *owner_id); +struct ViewLayer *BKE_view_layer_find_from_collection(const struct ID *owner_id, struct LayerCollection *lc); struct Base *BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob); -struct Base *BKE_view_layer_base_find_by_name(struct ViewLayer *view_layer, struct Object *ob); void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer); void BKE_view_layer_base_select(struct ViewLayer *view_layer, struct Base *selbase); +void BKE_view_layer_copy_data(struct ViewLayer *view_layer_dst, struct ViewLayer *view_layer_src, + struct SceneCollection* mc_dst, struct SceneCollection* mc_src, + const int flag); + void BKE_layer_collection_free(struct ViewLayer *view_layer, struct LayerCollection *lc); struct LayerCollection *BKE_layer_collection_get_active(struct ViewLayer *view_layer); @@ -84,11 +90,11 @@ int BKE_layer_collection_count(struct ViewLayer *view_layer); struct LayerCollection *BKE_layer_collection_from_index(struct ViewLayer *view_layer, const int index); int BKE_layer_collection_findindex(struct ViewLayer *view_layer, const struct LayerCollection *lc); -bool BKE_layer_collection_move_above(const struct Scene *scene, struct LayerCollection *lc_dst, struct LayerCollection *lc_src); -bool BKE_layer_collection_move_below(const struct Scene *scene, struct LayerCollection *lc_dst, struct LayerCollection *lc_src); -bool BKE_layer_collection_move_into(const struct Scene *scene, struct LayerCollection *lc_dst, struct LayerCollection *lc_src); +bool BKE_layer_collection_move_above(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src); +bool BKE_layer_collection_move_below(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src); +bool BKE_layer_collection_move_into(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src); -void BKE_layer_collection_resync(const struct Scene *scene, const struct SceneCollection *sc); +void BKE_layer_collection_resync(const struct ID *owner_id, const struct SceneCollection *sc); struct LayerCollection *BKE_collection_link(struct ViewLayer *view_layer, struct SceneCollection *sc); @@ -102,13 +108,13 @@ bool BKE_scene_has_object(struct Scene *scene, struct Object *ob); /* syncing */ -void BKE_layer_sync_new_scene_collection(struct Scene *scene, const struct SceneCollection *sc_parent, struct SceneCollection *sc); -void BKE_layer_sync_object_link(const struct Scene *scene, struct SceneCollection *sc, struct Object *ob); -void BKE_layer_sync_object_unlink(const struct Scene *scene, struct SceneCollection *sc, struct Object *ob); +void BKE_layer_sync_new_scene_collection(struct ID *owner_id, const struct SceneCollection *sc_parent, struct SceneCollection *sc); +void BKE_layer_sync_object_link(const struct ID *owner_id, struct SceneCollection *sc, struct Object *ob); +void BKE_layer_sync_object_unlink(const struct ID *owner_id, struct SceneCollection *sc, struct Object *ob); /* override */ -void BKE_override_view_layer_datablock_add(struct ViewLayer *view_layer, int id_type, const char *data_path, const struct ID *id); +void BKE_override_view_layer_datablock_add(struct ViewLayer *view_layer, int id_type, const char *data_path, const struct ID *owner_id); void BKE_override_view_layer_int_add(struct ViewLayer *view_layer, int id_type, const char *data_path, const int value); void BKE_override_layer_collection_boolean_add(struct LayerCollection *layer_collection, int id_type, const char *data_path, const bool value); @@ -152,7 +158,7 @@ void BKE_collection_engine_property_value_set_bool(struct IDProperty *props, con /* evaluation */ void BKE_layer_eval_layer_collection_pre(const struct EvaluationContext *eval_ctx, - struct Scene *scene, + struct ID *owner_id, struct ViewLayer *view_layer); void BKE_layer_eval_layer_collection(const struct EvaluationContext *eval_ctx, struct LayerCollection *layer_collection, diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 25305b1d25a..aa5b9e7eb25 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -40,6 +40,7 @@ #include "BKE_main.h" #include "BKE_scene.h" +#include "DNA_group_types.h" #include "DNA_ID.h" #include "DNA_layer_types.h" #include "DNA_object_types.h" @@ -47,15 +48,28 @@ #include "MEM_guardedalloc.h" +static SceneCollection *collection_master_from_id(const ID *owner_id) +{ + switch (GS(owner_id->name)) { + case ID_SCE: + return ((Scene *)owner_id)->collection; + case ID_GR: + return ((Group *)owner_id)->collection; + default: + BLI_assert(!"ID doesn't support collections"); + return NULL; + } +} /** * Add a collection to a collection ListBase and syncronize all render layers * The ListBase is NULL when the collection is to be added to the master collection */ -SceneCollection *BKE_collection_add(Scene *scene, SceneCollection *sc_parent, const char *name) +SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name) { - SceneCollection *sc_master = BKE_collection_master(scene); + SceneCollection *sc_master = collection_master_from_id(owner_id); SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection"); + sc->type = type; if (!name) { name = DATA_("New Collection"); @@ -65,10 +79,10 @@ SceneCollection *BKE_collection_add(Scene *scene, SceneCollection *sc_parent, co sc_parent = sc_master; } - BKE_collection_rename(scene, sc, name); + BKE_collection_rename((Scene *)owner_id, sc, name); BLI_addtail(&sc_parent->scene_collections, sc); - BKE_layer_sync_new_scene_collection(scene, sc_parent, sc); + BKE_layer_sync_new_scene_collection(owner_id, sc_parent, sc); return sc; } @@ -147,25 +161,25 @@ static void layer_collection_remove(ViewLayer *view_layer, ListBase *lb, const S /** * Remove a collection from the scene, and syncronize all render layers */ -bool BKE_collection_remove(Scene *scene, SceneCollection *sc) +bool BKE_collection_remove(ID *owner_id, SceneCollection *sc) { - SceneCollection *sc_master = BKE_collection_master(scene); + SceneCollection *sc_master = collection_master_from_id(owner_id); - /* the master collection cannot be removed */ + /* The master collection cannot be removed. */ if (sc == sc_master) { return false; } - /* unlink from the respective collection tree */ + /* Unlink from the respective collection tree. */ if (!collection_remlink(sc_master, sc)) { BLI_assert(false); } - /* clear the collection items */ + /* Clear the collection items. */ collection_free(sc, true); /* check all layers that use this collection and clear them */ - for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { layer_collection_remove(view_layer, &view_layer->layer_collections, sc); view_layer->active_collection = 0; } @@ -175,11 +189,54 @@ bool BKE_collection_remove(Scene *scene, SceneCollection *sc) } /** - * Returns the master collection + * Copy SceneCollection tree but keep pointing to the same objects + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_collection_copy_data(SceneCollection *sc_dst, SceneCollection *sc_src, const int flag) +{ + BLI_duplicatelist(&sc_dst->objects, &sc_src->objects); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + for (LinkData *link = sc_dst->objects.first; link; link = link->next) { + id_us_plus(link->data); + } + } + + BLI_duplicatelist(&sc_dst->filter_objects, &sc_src->filter_objects); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + for (LinkData *link = sc_dst->filter_objects.first; link; link = link->next) { + id_us_plus(link->data); + } + } + + BLI_duplicatelist(&sc_dst->scene_collections, &sc_src->scene_collections); + for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first; + nsc_src; + nsc_src = nsc_src->next, nsc_dst = nsc_dst->next) + { + BKE_collection_copy_data(nsc_dst, nsc_src, flag); + } +} + +static SceneCollection *master_collection_from_id(const ID *owner_id) +{ + switch (GS(owner_id->name)) { + case ID_SCE: + return ((const Scene *)owner_id)->collection; + case ID_GR: + return ((const Group *)owner_id)->collection; + default: + BLI_assert(!"ID doesn't support scene collection"); + return NULL; + } +} + +/** + * Returns the master collection of the scene or group */ -SceneCollection *BKE_collection_master(const Scene *scene) +SceneCollection *BKE_collection_master(const ID *owner_id) { - return scene->collection; + return master_collection_from_id(owner_id); } struct UniqueNameCheckData { @@ -207,41 +264,58 @@ static bool collection_unique_name_check(void *arg, const char *name) return false; } -void BKE_collection_rename(const Scene *scene, SceneCollection *sc, const char *name) +static void collection_rename(const ID *owner_id, SceneCollection *sc, const char *name) { - SceneCollection *sc_master = BKE_collection_master(scene); + SceneCollection *sc_master = collection_master_from_id(owner_id); struct UniqueNameCheckData data = {.lb = &sc_master->scene_collections, .lookup_sc = sc}; BLI_strncpy(sc->name, name, sizeof(sc->name)); BLI_uniquename_cb(collection_unique_name_check, &data, DATA_("Collection"), '.', sc->name, sizeof(sc->name)); } +void BKE_collection_rename(const Scene *scene, SceneCollection *sc, const char *name) +{ + collection_rename(&scene->id, sc, name); +} + /** * Free (or release) any data used by the master collection (does not free the master collection itself). - * Used only to clear the entire scene data since it's not doing re-syncing of the LayerCollection tree + * Used only to clear the entire scene or group data since it's not doing re-syncing of the LayerCollection tree */ -void BKE_collection_master_free(Scene *scene, const bool do_id_user) +void BKE_collection_master_free(ID *owner_id, const bool do_id_user) { - collection_free(BKE_collection_master(scene), do_id_user); + collection_free(BKE_collection_master(owner_id), do_id_user); } -static void collection_object_add(const Scene *scene, SceneCollection *sc, Object *ob) +static void collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob) { BLI_addtail(&sc->objects, BLI_genericNodeN(ob)); - id_us_plus((ID *)ob); - BKE_layer_sync_object_link(scene, sc, ob); + + if (GS(owner_id->name) == ID_SCE) { + id_us_plus((ID *)ob); + } + else { + BLI_assert(GS(owner_id->name) == ID_GR); + if ((ob->flag & OB_FROMGROUP) == 0) { + ob->flag |= OB_FROMGROUP; + } + } + + BKE_layer_sync_object_link(owner_id, sc, ob); } /** * Add object to collection */ -void BKE_collection_object_add(const Scene *scene, SceneCollection *sc, Object *ob) +bool BKE_collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob) { if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) { /* don't add the same object twice */ - return; + return false; } - collection_object_add(scene, sc, ob); + + collection_object_add(owner_id, sc, ob); + return true; } /** @@ -253,7 +327,7 @@ void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst FOREACH_SCENE_COLLECTION(scene, sc) { if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) { - collection_object_add(scene, sc, ob_dst); + collection_object_add(&scene->id, sc, ob_dst); } } FOREACH_SCENE_COLLECTION_END @@ -274,50 +348,63 @@ void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst * Remove object from collection. * \param bmain: Can be NULL if free_us is false. */ -void BKE_collection_object_remove(Main *bmain, const Scene *scene, SceneCollection *sc, Object *ob, const bool free_us) +bool BKE_collection_object_remove(Main *bmain, ID *owner_id, SceneCollection *sc, Object *ob, const bool free_us) { - LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data)); if (link == NULL) { - return; + return false; } BLI_remlink(&sc->objects, link); MEM_freeN(link); TODO_LAYER_SYNC_FILTER; /* need to remove all instances of ob in scene collections -> filter_objects */ - BKE_layer_sync_object_unlink(scene, sc, ob); + BKE_layer_sync_object_unlink(owner_id, sc, ob); - if (free_us) { - BKE_libblock_free_us(bmain, ob); + if (GS(owner_id->name) == ID_SCE) { + if (free_us) { + BKE_libblock_free_us(bmain, ob); + } + else { + id_us_min(&ob->id); + } } else { - id_us_min(&ob->id); + BLI_assert(GS(owner_id->name) == ID_GR); } + + return true; } /** * Move object from a collection into another */ -void BKE_collection_object_move(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob) +void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob) { - BKE_collection_object_add(scene, sc_dst, ob); - BKE_collection_object_remove(NULL, scene, sc_src, ob, false); + BKE_collection_object_add(owner_id, sc_dst, ob); + BKE_collection_object_remove(NULL, owner_id, sc_src, ob, false); } /** * Remove object from all collections of scene */ -void BKE_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us) +bool BKE_collections_object_remove(Main *bmain, ID *owner_id, Object *ob, const bool free_us) { - BKE_scene_remove_rigidbody_object(scene, ob); + bool removed = false; + if (GS(owner_id->name) == ID_SCE) { + BKE_scene_remove_rigidbody_object((Scene *)owner_id, ob); + } + else { + BLI_assert(GS(owner_id->name) == ID_GR); + } - FOREACH_SCENE_COLLECTION(scene, sc) + FOREACH_SCENE_COLLECTION(owner_id, sc) { - BKE_collection_object_remove(bmain, scene, sc, ob, free_us); + removed |= BKE_collection_object_remove(bmain, owner_id, sc, ob, free_us); } FOREACH_SCENE_COLLECTION_END + return removed; } /* ---------------------------------------------------------------------- */ @@ -353,10 +440,10 @@ static bool is_collection_in_tree(const SceneCollection *sc_reference, SceneColl return find_collection_parent(sc_reference, sc_parent) != NULL; } -bool BKE_collection_move_above(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src) +bool BKE_collection_move_above(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src) { /* Find the SceneCollection the sc_src belongs to */ - SceneCollection *sc_master = BKE_collection_master(scene); + SceneCollection *sc_master = master_collection_from_id(owner_id); /* Master Layer can't be moved around*/ if (ELEM(sc_master, sc_src, sc_dst)) { @@ -386,16 +473,16 @@ bool BKE_collection_move_above(const Scene *scene, SceneCollection *sc_dst, Scen BLI_insertlinkbefore(&sc_dst_parent->scene_collections, sc_dst, sc_src); /* Update the tree */ - BKE_layer_collection_resync(scene, sc_src_parent); - BKE_layer_collection_resync(scene, sc_dst_parent); + BKE_layer_collection_resync(owner_id, sc_src_parent); + BKE_layer_collection_resync(owner_id, sc_dst_parent); return true; } -bool BKE_collection_move_below(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src) +bool BKE_collection_move_below(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src) { /* Find the SceneCollection the sc_src belongs to */ - SceneCollection *sc_master = BKE_collection_master(scene); + SceneCollection *sc_master = master_collection_from_id(owner_id); /* Master Layer can't be moved around*/ if (ELEM(sc_master, sc_src, sc_dst)) { @@ -425,16 +512,16 @@ bool BKE_collection_move_below(const Scene *scene, SceneCollection *sc_dst, Scen BLI_insertlinkafter(&sc_dst_parent->scene_collections, sc_dst, sc_src); /* Update the tree */ - BKE_layer_collection_resync(scene, sc_src_parent); - BKE_layer_collection_resync(scene, sc_dst_parent); + BKE_layer_collection_resync(owner_id, sc_src_parent); + BKE_layer_collection_resync(owner_id, sc_dst_parent); return true; } -bool BKE_collection_move_into(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src) +bool BKE_collection_move_into(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src) { /* Find the SceneCollection the sc_src belongs to */ - SceneCollection *sc_master = BKE_collection_master(scene); + SceneCollection *sc_master = master_collection_from_id(owner_id); if (sc_src == sc_master) { return false; } @@ -460,8 +547,8 @@ bool BKE_collection_move_into(const Scene *scene, SceneCollection *sc_dst, Scene BLI_addtail(&sc_dst->scene_collections, sc_src); /* Update the tree */ - BKE_layer_collection_resync(scene, sc_src_parent); - BKE_layer_collection_resync(scene, sc_dst); + BKE_layer_collection_resync(owner_id, sc_src_parent); + BKE_layer_collection_resync(owner_id, sc_dst); return true; } @@ -471,7 +558,7 @@ bool BKE_collection_move_into(const Scene *scene, SceneCollection *sc_dst, Scene /* scene collection iteractor */ typedef struct SceneCollectionsIteratorData { - Scene *scene; + ID *owner_id; void **array; int tot, cur; } SceneCollectionsIteratorData; @@ -498,17 +585,20 @@ static void scene_collections_build_array(SceneCollection *sc, void *data) (*array)++; } -static void scene_collections_array(Scene *scene, SceneCollection ***collections_array, int *tot) +static void scene_collections_array(ID *owner_id, SceneCollection ***collections_array, int *tot) { - SceneCollection *sc = BKE_collection_master(scene); + SceneCollection *sc; SceneCollection **array; *collections_array = NULL; *tot = 0; - if (scene == NULL) + if (owner_id == NULL) { return; + } + sc = master_collection_from_id(owner_id); + BLI_assert(sc != NULL); scene_collection_callback(sc, scene_collections_count, tot); if (*tot == 0) @@ -524,13 +614,13 @@ static void scene_collections_array(Scene *scene, SceneCollection ***collections */ void BKE_scene_collections_iterator_begin(BLI_Iterator *iter, void *data_in) { - Scene *scene = data_in; + ID *owner_id = data_in; SceneCollectionsIteratorData *data = MEM_callocN(sizeof(SceneCollectionsIteratorData), __func__); - data->scene = scene; + data->owner_id = owner_id; iter->data = data; - scene_collections_array(scene, (SceneCollection ***)&data->array, &data->tot); + scene_collections_array(owner_id, (SceneCollection ***)&data->array, &data->tot); BLI_assert(data->tot != 0); data->cur = 0; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index d21b527bbd6..2f80fbbec46 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -47,6 +47,7 @@ #include "BKE_cloth.h" #include "BKE_effect.h" +#include "BKE_group.h" #include "BKE_layer.h" #include "BKE_modifier.h" #include "BKE_scene.h" @@ -502,12 +503,14 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned /* objects in dupli groups, one level only for now */ if (ob->dup_group && level == 0) { - GroupObject *go; Group *group= ob->dup_group; /* add objects */ - for (go= group->gobject.first; go; go= go->next) - add_collision_object(objs, numobj, maxobj, go->ob, self, level+1, modifier_type); + FOREACH_GROUP_OBJECT(group, object) + { + add_collision_object(objs, numobj, maxobj, object, self, level+1, modifier_type); + } + FOREACH_GROUP_OBJECT_END } } @@ -515,9 +518,7 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned // collision object will exclude self Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type, bool dupli) { - Base *base; Object **objs; - GroupObject *go; unsigned int numobj= 0, maxobj= 100; int level = dupli ? 0 : 1; @@ -526,11 +527,15 @@ Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsi /* gather all collision objects */ if (group) { /* use specified group */ - for (go= group->gobject.first; go; go= go->next) - add_collision_object(&objs, &numobj, &maxobj, go->ob, self, level, modifier_type); + FOREACH_GROUP_OBJECT(group, object) + { + add_collision_object(&objs, &numobj, &maxobj, object, self, level, modifier_type); + } + FOREACH_GROUP_OBJECT_END } else { Scene *sce_iter; + Base *base; /* add objects in same layer in scene */ for (SETLOOPER(scene, sce_iter, base)) { if ((base->flag & BASE_VISIBLED) != 0) { @@ -576,24 +581,28 @@ static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, /* objects in dupli groups, one level only for now */ if (ob->dup_group && level == 0) { - GroupObject *go; Group *group= ob->dup_group; /* add objects */ - for (go= group->gobject.first; go; go= go->next) - add_collider_cache_object(objs, go->ob, self, level+1); + FOREACH_GROUP_OBJECT(group, object) + { + add_collider_cache_object(objs, object, self, level+1); + } + FOREACH_GROUP_OBJECT_END } } ListBase *get_collider_cache(Scene *scene, Object *self, Group *group) { - GroupObject *go; ListBase *objs= NULL; /* add object in same layer in scene */ if (group) { - for (go= group->gobject.first; go; go= go->next) - add_collider_cache_object(&objs, go->ob, self, 0); + FOREACH_GROUP_OBJECT(group, object) + { + add_collider_cache_object(&objs, object, self, 0); + } + FOREACH_GROUP_OBJECT_END } else { Scene *sce_iter; diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 3a4de77a3b5..855216d089b 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -991,7 +991,7 @@ SceneCollection *CTX_data_scene_collection(const bContext *C) /* fallback */ Scene *scene = CTX_data_scene(C); - return BKE_collection_master(scene); + return BKE_collection_master(&scene->id); } int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob) diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 9e292422019..80a31697424 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -491,33 +491,24 @@ static void scene_setSubframe(Scene *scene, float subframe) static int surface_getBrushFlags(DynamicPaintSurface *surface, const ViewLayer *view_layer) { Base *base = NULL; - GroupObject *go = NULL; Object *brushObj = NULL; ModifierData *md = NULL; int flags = 0; if (surface->brush_group) - go = surface->brush_group->gobject.first; + base = FIRSTBASE(surface->brush_group->view_layer); else base = FIRSTBASE(view_layer); - while (base || go) { + while (base) { brushObj = NULL; /* select object */ - if (surface->brush_group) { - if (go->ob) - brushObj = go->ob; - } - else { - brushObj = base->object; - } + brushObj = base->object; - if (surface->brush_group) - go = go->next; - else - base = base->next; + /* next item */ + base = base->next; if (!brushObj) { continue; @@ -5780,7 +5771,6 @@ static int dynamicPaint_doStep(const struct EvaluationContext *eval_ctx, Scene * */ { Base *base = NULL; - GroupObject *go = NULL; Object *brushObj = NULL; ModifierData *md = NULL; ViewLayer *view_layer = eval_ctx->view_layer; @@ -5791,25 +5781,17 @@ static int dynamicPaint_doStep(const struct EvaluationContext *eval_ctx, Scene * /* either from group or from all objects */ if (surface->brush_group) - go = surface->brush_group->gobject.first; + base = FIRSTBASE(surface->brush_group->view_layer); else base = FIRSTBASE(view_layer); - while (base || go) { + while (base) { brushObj = NULL; /* select object */ - if (surface->brush_group) { - if (go->ob) - brushObj = go->ob; - } - else - brushObj = base->object; + brushObj = base->object; /* next item */ - if (surface->brush_group) - go = go->next; - else - base = base->next; + base = base->next; if (!brushObj) { /* skip item */ diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 502ad9c44a7..16124fb4777 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -64,6 +64,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_layer.h" #include "BKE_library.h" #include "BKE_modifier.h" @@ -215,51 +216,41 @@ ListBase *pdInitEffectors( { ViewLayer *view_layer; Base *base; - unsigned int layer= ob_src->lay; ListBase *effectors = NULL; - /* eval_ctx is NULL during deg build */ - if (eval_ctx) { + if (weights->group) { + view_layer = weights->group->view_layer; + } + else if (eval_ctx) { view_layer = eval_ctx->view_layer; } else { + /* eval_ctx is NULL during deg build */ view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene); } - - if (weights->group) { - GroupObject *go; - - for (go= weights->group->gobject.first; go; go= go->next) { - if ( (go->ob->lay & layer) ) { - if ( go->ob->pd && go->ob->pd->forcefield ) - add_object_to_effectors(&effectors, eval_ctx, scene, weights, go->ob, ob_src, for_simulation); - if ( go->ob->particlesystem.first ) { - ParticleSystem *psys= go->ob->particlesystem.first; + for (base = FIRSTBASE(view_layer); base; base = base->next) { + if ((base->flag & BASE_VISIBLED) == 0) { + continue; + } - for ( ; psys; psys=psys->next ) - add_particles_to_effectors(&effectors, eval_ctx, scene, weights, go->ob, psys, psys_src, for_simulation); - } - } + if (base->object->pd && base->object->pd->forcefield) { + add_object_to_effectors(&effectors, eval_ctx, scene, weights, base->object, ob_src, for_simulation); } - } - else { - for (base = FIRSTBASE(view_layer); base; base = base->next) { - if ( base->object->pd && base->object->pd->forcefield ) - add_object_to_effectors(&effectors, eval_ctx, scene, weights, base->object, ob_src, for_simulation); - if ( base->object->particlesystem.first ) { - ParticleSystem *psys= base->object->particlesystem.first; + if (base->object->particlesystem.first) { + ParticleSystem *psys= base->object->particlesystem.first; - for ( ; psys; psys=psys->next ) - add_particles_to_effectors(&effectors, eval_ctx, scene, weights, base->object, psys, psys_src, for_simulation); + for (; psys; psys=psys->next) { + add_particles_to_effectors(&effectors, eval_ctx, scene, weights, base->object, psys, psys_src, for_simulation); } } } - - if (for_simulation) + + if (for_simulation) { pdPrecalculateEffectors(eval_ctx, effectors); - + } + return effectors; } diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index f4555ceac38..7c2eefe657c 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -45,32 +45,53 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BKE_collection.h" #include "BKE_global.h" #include "BKE_group.h" #include "BKE_icons.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_scene.h" -static void free_group_object(GroupObject *go) -{ - MEM_freeN(go); -} - /** Free (or release) any data used by this group (does not free the group itself). */ void BKE_group_free(Group *group) { - /* don't free group itself */ - GroupObject *go; - /* No animdata here. */ + BKE_previewimg_free(&group->preview); - while ((go = BLI_pophead(&group->gobject))) { - free_group_object(go); + if (group->view_layer != NULL) { + BKE_view_layer_free(group->view_layer); + group->view_layer = NULL; } - BKE_previewimg_free(&group->preview); + if (group->collection != NULL) { + BKE_collection_master_free(&group->id, false); + MEM_freeN(group->collection); + group->collection = NULL; + } +} + +/** + * Run when adding new groups or during doversion. + */ +void BKE_group_init(Group *group) +{ + group->collection = MEM_callocN(sizeof(SceneCollection), __func__); + BLI_strncpy(group->collection->name, "Master Collection", sizeof(group->collection->name)); + group->view_layer = NULL; /* groups are not calloced. */ + group->view_layer = BKE_view_layer_group_add(group); + + /* Unlink the master collection. */ + BKE_collection_unlink(group->view_layer, group->view_layer->layer_collections.first); + + /* Create and link a new default collection. */ + SceneCollection *defaut_collection = BKE_collection_add(&group->id, + NULL, + COLLECTION_TYPE_GROUP_INTERNAL, + "Default Collection"); + BKE_collection_link(group->view_layer, defaut_collection); } Group *BKE_group_add(Main *bmain, const char *name) @@ -83,7 +104,7 @@ Group *BKE_group_add(Main *bmain, const char *name) group->layer = (1 << 20) - 1; group->preview = NULL; - + BKE_group_init(group); return group; } @@ -97,7 +118,8 @@ Group *BKE_group_add(Main *bmain, const char *name) */ void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *group_src, const int flag) { - BLI_duplicatelist(&group_dst->gobject, &group_src->gobject); + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; /* Do not copy group's preview (same behavior as for objects). */ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */ @@ -106,6 +128,18 @@ void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *gro else { group_dst->preview = NULL; } + + group_dst->collection = MEM_dupallocN(group_src->collection); + SceneCollection *master_collection_src = BKE_collection_master(&group_src->id); + SceneCollection *master_collection_dst = BKE_collection_master(&group_dst->id); + + /* Recursively creates a new SceneCollection tree. */ + BKE_collection_copy_data(master_collection_dst, master_collection_src, + flag_subdata); + + BKE_view_layer_copy_data(group_dst->view_layer, group_src->view_layer, + master_collection_dst, master_collection_src, + flag_subdata); } Group *BKE_group_copy(Main *bmain, const Group *group) @@ -123,23 +157,19 @@ void BKE_group_make_local(Main *bmain, Group *group, const bool lib_local) /* external */ static bool group_object_add_internal(Group *group, Object *ob) { - GroupObject *go; - if (group == NULL || ob == NULL) { return false; } - - /* check if the object has been added already */ - if (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob))) { + + /* For now always add to master collection of the group. */ + SceneCollection *scene_collection = GROUP_MASTER_COLLECTION(group); + + /* If the object has been added already it returns false. */ + if (BKE_collection_object_add(&group->id, scene_collection, ob) == false) { return false; } - - go = MEM_callocN(sizeof(GroupObject), "groupobject"); - BLI_addtail(&group->gobject, go); - - go->ob = ob; - id_us_ensure_real(&go->ob->id); - + + id_us_ensure_real(&ob->id); return true; } @@ -157,24 +187,17 @@ bool BKE_group_object_add(Group *group, Object *object) } /* also used for (ob == NULL) */ -static int group_object_unlink_internal(Group *group, Object *ob) +static bool group_object_unlink_internal(Group *group, Object *ob) { - GroupObject *go, *gon; - int removed = 0; - if (group == NULL) return 0; - - go = group->gobject.first; - while (go) { - gon = go->next; - if (go->ob == ob) { - BLI_remlink(&group->gobject, go); - free_group_object(go); - removed = 1; - /* should break here since an object being in a group twice cant happen? */ - } - go = gon; + if (group == NULL) { + return false; } - return removed; + + if (BKE_collections_object_remove(NULL, &group->id, ob, false)) { + return true; + } + + return false; } static bool group_object_cyclic_check_internal(Object *object, Group *group) @@ -191,12 +214,13 @@ static bool group_object_cyclic_check_internal(Object *object, Group *group) if (dup_group == group) return true; else { - GroupObject *gob; - for (gob = dup_group->gobject.first; gob; gob = gob->next) { - if (group_object_cyclic_check_internal(gob->ob, group)) { + FOREACH_GROUP_OBJECT(dup_group, group_object) + { + if (group_object_cyclic_check_internal(group_object, dup_group)) { return true; } } + FOREACH_GROUP_OBJECT_END } /* un-flag the object, it's allowed to have the same group multiple times in parallel */ @@ -234,7 +258,7 @@ bool BKE_group_object_exists(Group *group, Object *ob) return false; } else { - return (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob)) != NULL); + return (BLI_findptr(&group->view_layer->object_bases, ob, offsetof(Base, object))); } } @@ -255,17 +279,13 @@ Group *BKE_group_object_find(Group *group, Object *ob) bool BKE_group_is_animated(Group *group, Object *UNUSED(parent)) { - GroupObject *go; - -#if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */ - if (parent->nlastrips.first) - return 1; -#endif - - for (go = group->gobject.first; go; go = go->next) - if (go->ob && go->ob->proxy) + FOREACH_GROUP_OBJECT(group, object) + { + if (object->proxy) { return true; - + } + } + FOREACH_GROUP_OBJECT_END return false; } @@ -317,8 +337,6 @@ static void group_replaces_nla(Object *parent, Object *target, char mode) /* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */ void BKE_group_handle_recalc_and_update(const struct EvaluationContext *eval_ctx, Scene *scene, Object *UNUSED(parent), Group *group) { - GroupObject *go; - #if 0 /* warning, isn't clearing the recalc flag on the object which causes it to run all the time, * not just on frame change. * This isn't working because the animation data is only re-evaluated on frame change so commenting for now @@ -352,12 +370,12 @@ void BKE_group_handle_recalc_and_update(const struct EvaluationContext *eval_ctx #endif { /* only do existing tags, as set by regular depsgraph */ - for (go = group->gobject.first; go; go = go->next) { - if (go->ob) { - if (go->ob->id.tag & LIB_TAG_ID_RECALC_ALL) { - BKE_object_handle_update(eval_ctx, scene, go->ob); - } + FOREACH_GROUP_OBJECT(group, object) + { + if (object->id.tag & LIB_TAG_ID_RECALC_ALL) { + BKE_object_handle_update(eval_ctx, scene, object); } } + FOREACH_GROUP_OBJECT_END } } diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index f841181f7c4..363dc53496f 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -35,12 +35,14 @@ #include "BKE_collection.h" #include "BKE_freestyle.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_idprop.h" #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_workspace.h" +#include "DNA_group_types.h" #include "DNA_ID.h" #include "DNA_layer_types.h" #include "DNA_object_types.h" @@ -102,11 +104,7 @@ ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const Scene *scene) return BKE_view_layer_from_scene_get(scene); } -/** - * Add a new renderlayer - * by default, a renderlayer has the master collection - */ -ViewLayer *BKE_view_layer_add(Scene *scene, const char *name) +static ViewLayer *view_layer_add(const char *name, SceneCollection *master_scene_collection) { if (!name) { name = DATA_("View Layer"); @@ -118,15 +116,10 @@ ViewLayer *BKE_view_layer_add(Scene *scene, const char *name) view_layer->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); layer_engine_settings_init(view_layer->properties, false); - - BLI_addtail(&scene->view_layers, view_layer); - - /* unique name */ BLI_strncpy_utf8(view_layer->name, name, sizeof(view_layer->name)); - BLI_uniquename(&scene->view_layers, view_layer, DATA_("ViewLayer"), '.', offsetof(ViewLayer, name), sizeof(view_layer->name)); - SceneCollection *sc = BKE_collection_master(scene); - layer_collection_add(view_layer, NULL, sc); + /* Link the master collection by default. */ + layer_collection_add(view_layer, NULL, master_scene_collection); /* Pure rendering pipeline settings. */ view_layer->layflag = 0x7FFF; /* solid ztra halo edge strand */ @@ -138,6 +131,35 @@ ViewLayer *BKE_view_layer_add(Scene *scene, const char *name) } /** + * Add a new view layer + * by default, a view layer has the master collection + */ +ViewLayer *BKE_view_layer_add(Scene *scene, const char *name) +{ + SceneCollection *sc = BKE_collection_master(&scene->id); + ViewLayer *view_layer = view_layer_add(name, sc); + + BLI_addtail(&scene->view_layers, view_layer); + + /* unique name */ + BLI_uniquename(&scene->view_layers, view_layer, DATA_("ViewLayer"), '.', offsetof(ViewLayer, name), sizeof(view_layer->name)); + + return view_layer; +} + +/** + * Add a ViewLayer for a Group + * It should be added only once + */ +ViewLayer *BKE_view_layer_group_add(Group *group) +{ + BLI_assert(group->view_layer == NULL); + SceneCollection *sc = BKE_collection_master(&group->id); + ViewLayer *view_layer = view_layer_add(group->id.name + 2, sc); + return view_layer; +} + +/** * Free (or release) any data used by this ViewLayer. */ void BKE_view_layer_free(ViewLayer *view_layer) @@ -204,6 +226,22 @@ void BKE_view_layer_selected_objects_tag(ViewLayer *view_layer, const int tag) } } +/** + * Return the first ViewLayer for a given id + */ +ViewLayer *BKE_view_layer_first_from_id(const ID *owner_id) +{ + switch (GS(owner_id->name)) { + case ID_SCE: + return ((Scene *)owner_id)->view_layers.first; + case ID_GR: + return ((Group *)owner_id)->view_layer; + default: + BLI_assert(!"ID doesn't support view layers"); + return NULL; + } +} + static bool find_scene_collection_in_scene_collections(ListBase *lb, const LayerCollection *lc) { for (LayerCollection *lcn = lb->first; lcn; lcn = lcn->next) { @@ -238,14 +276,25 @@ Object *BKE_view_layer_camera_find(ViewLayer *view_layer) /** * Find the ViewLayer a LayerCollection belongs to */ -ViewLayer *BKE_view_layer_find_from_collection(const Scene *scene, LayerCollection *lc) -{ - for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { - if (find_scene_collection_in_scene_collections(&view_layer->layer_collections, lc)) { - return view_layer; +ViewLayer *BKE_view_layer_find_from_collection(const ID *owner_id, LayerCollection *lc) +{ + switch (GS(owner_id->name)) { + case ID_GR: + return ((Group *)owner_id)->view_layer; + case ID_SCE: + { + Scene *scene = (Scene *)owner_id; + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + if (find_scene_collection_in_scene_collections(&view_layer->layer_collections, lc)) { + return view_layer; + } + } + return NULL; } + default: + BLI_assert(!"ID doesn't support scene layers"); + return NULL; } - return NULL; } /* Base */ @@ -272,6 +321,112 @@ void BKE_view_layer_base_select(struct ViewLayer *view_layer, Base *selbase) } } +/****************************************************************************/ +/* Copying functions for datablocks that use ViewLayer/SceneCollection */ + +/* Find the equivalent SceneCollection in the new tree */ +static SceneCollection *scene_collection_from_new_tree(SceneCollection *sc_reference, SceneCollection *sc_dst, SceneCollection *sc_src) +{ + if (sc_src == sc_reference) { + return sc_dst; + } + + for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first; + nsc_src; + nsc_src = nsc_src->next, nsc_dst = nsc_dst->next) + { + SceneCollection *found = scene_collection_from_new_tree(sc_reference, nsc_dst, nsc_src); + if (found != NULL) { + return found; + } + } + return NULL; +} + +static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src) +{ + LayerCollection *layer_collection_dst = (LayerCollection *)layer_collections_dst->first; + const LayerCollection *layer_collection_src = (const LayerCollection *)layer_collections_src->first; + while (layer_collection_dst != NULL) { + layer_collection_dst->flag = layer_collection_src->flag; + + if (layer_collection_dst->properties != NULL) { + IDP_FreeProperty(layer_collection_dst->properties); + MEM_SAFE_FREE(layer_collection_dst->properties); + } + + if (layer_collection_src->properties != NULL) { + layer_collection_dst->properties = IDP_CopyProperty(layer_collection_src->properties); + } + + layer_collections_sync_flags(&layer_collection_dst->layer_collections, + &layer_collection_src->layer_collections); + + layer_collection_dst = layer_collection_dst->next; + layer_collection_src = layer_collection_src->next; + } +} + +/* recreate the LayerCollection tree */ +static void layer_collections_recreate( + ViewLayer *view_layer_dst, ListBase *lb_src, SceneCollection *mc_dst, SceneCollection *mc_src) +{ + for (LayerCollection *lc_src = lb_src->first; lc_src; lc_src = lc_src->next) { + SceneCollection *sc_dst = scene_collection_from_new_tree(lc_src->scene_collection, mc_dst, mc_src); + BLI_assert(sc_dst); + + /* instead of synchronizing both trees we simply re-create it */ + BKE_collection_link(view_layer_dst, sc_dst); + } +} + +/** + * Only copy internal data of ViewLayer from source to already allocated/initialized destination. + * + * \param mc_src Master Collection the source ViewLayer links in. + * \param mc_dst Master Collection the destination ViewLayer links in. + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_view_layer_copy_data(ViewLayer *view_layer_dst, ViewLayer *view_layer_src, SceneCollection* mc_dst, SceneCollection* mc_src, + const int flag) +{ + IDPropertyTemplate val = {0}; + + if (view_layer_dst->id_properties != NULL) { + view_layer_dst->id_properties = IDP_CopyProperty_ex(view_layer_dst->id_properties, flag); + } + BKE_freestyle_config_copy(&view_layer_dst->freestyle_config, &view_layer_src->freestyle_config, flag); + + view_layer_dst->stats = NULL; + view_layer_dst->properties_evaluated = NULL; + view_layer_dst->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + IDP_MergeGroup_ex(view_layer_dst->properties, view_layer_src->properties, true, flag); + + /* we start fresh with no overrides and no visibility flags set + * instead of syncing both trees we simply unlink and relink the scene collection */ + BLI_listbase_clear(&view_layer_dst->layer_collections); + BLI_listbase_clear(&view_layer_dst->object_bases); + BLI_listbase_clear(&view_layer_dst->drawdata); + + layer_collections_recreate(view_layer_dst, &view_layer_src->layer_collections, mc_dst, mc_src); + + /* Now we handle the syncing for visibility, selectability, ... */ + layer_collections_sync_flags(&view_layer_dst->layer_collections, &view_layer_src->layer_collections); + + Object *active_ob = OBACT(view_layer_src); + for (Base *base_src = view_layer_src->object_bases.first, *base_dst = view_layer_dst->object_bases.first; + base_src; + base_src = base_src->next, base_dst = base_dst->next) + { + base_dst->flag = base_src->flag; + base_dst->flag_legacy = base_src->flag_legacy; + + if (base_dst->object == active_ob) { + view_layer_dst->basact = base_dst; + } + } +} + static void view_layer_object_base_unref(ViewLayer *view_layer, Base *base) { base->refcount--; @@ -416,7 +571,7 @@ LayerCollection *BKE_layer_collection_get_active_ensure(Scene *scene, ViewLayer if (lc == NULL) { BLI_assert(BLI_listbase_is_empty(&view_layer->layer_collections)); /* When there is no collection linked to this ViewLayer, create one. */ - SceneCollection *sc = BKE_collection_add(scene, NULL, NULL); + SceneCollection *sc = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL); lc = BKE_collection_link(view_layer, sc); /* New collection has to be the active one. */ BLI_assert(lc == BKE_layer_collection_get_active(view_layer)); @@ -552,15 +707,15 @@ static void layer_collection_swap( } /** - * Move \a lc_src into \a lc_dst. Both have to be stored in \a sl. + * Move \a lc_src into \a lc_dst. Both have to be stored in \a view_layer. * If \a lc_src is directly linked to the ViewLayer it's unlinked */ -bool BKE_layer_collection_move_into(const Scene *scene, LayerCollection *lc_dst, LayerCollection *lc_src) +bool BKE_layer_collection_move_into(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src) { - ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc_src); + ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); bool is_directly_linked = false; - if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(scene, lc_dst))) { + if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { return false; } @@ -596,7 +751,7 @@ bool BKE_layer_collection_move_into(const Scene *scene, LayerCollection *lc_dst, layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); } - if (!BKE_collection_move_into(scene, lc_dst->scene_collection, lc_src->scene_collection)) { + if (!BKE_collection_move_into(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) { if (!is_directly_linked) { /* Swap back and remove */ layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); @@ -622,13 +777,13 @@ bool BKE_layer_collection_move_into(const Scene *scene, LayerCollection *lc_dst, * Move \a lc_src above \a lc_dst. Both have to be stored in \a view_layer. * If \a lc_src is directly linked to the ViewLayer it's unlinked */ -bool BKE_layer_collection_move_above(const Scene *scene, LayerCollection *lc_dst, LayerCollection *lc_src) +bool BKE_layer_collection_move_above(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src) { - ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc_src); + ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1; const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1; - if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(scene, lc_dst))) { + if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { return false; } @@ -671,7 +826,7 @@ bool BKE_layer_collection_move_above(const Scene *scene, LayerCollection *lc_dst layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); } - if (!BKE_collection_move_above(scene, lc_dst->scene_collection, lc_src->scene_collection)) { + if (!BKE_collection_move_above(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) { if (!is_directly_linked_src) { /* Swap back and remove */ layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); @@ -694,16 +849,16 @@ bool BKE_layer_collection_move_above(const Scene *scene, LayerCollection *lc_dst } /** - * Move \a lc_src below \a lc_dst. Both have to be stored in \a sl. + * Move \a lc_src below \a lc_dst. Both have to be stored in \a view_layer. * If \a lc_src is directly linked to the ViewLayer it's unlinked */ -bool BKE_layer_collection_move_below(const Scene *scene, LayerCollection *lc_dst, LayerCollection *lc_src) +bool BKE_layer_collection_move_below(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src) { - ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc_src); + ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1; const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1; - if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(scene, lc_dst))) { + if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { return false; } @@ -746,7 +901,7 @@ bool BKE_layer_collection_move_below(const Scene *scene, LayerCollection *lc_dst layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); } - if (!BKE_collection_move_below(scene, lc_dst->scene_collection, lc_src->scene_collection)) { + if (!BKE_collection_move_below(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) { if (!is_directly_linked_src) { /* Swap back and remove */ layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); @@ -809,9 +964,9 @@ static bool layer_collection_resync(ViewLayer *view_layer, LayerCollection *lc, * Update the scene layers so that any LayerCollection that points * to \a sc is re-synced again */ -void BKE_layer_collection_resync(const Scene *scene, const SceneCollection *sc) +void BKE_layer_collection_resync(const ID *owner_id, const SceneCollection *sc) { - for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { layer_collection_resync(view_layer, lc, sc); } @@ -1025,9 +1180,9 @@ static LayerCollection *find_layer_collection_by_scene_collection(LayerCollectio /** * Add a new LayerCollection for all the ViewLayers that have sc_parent */ -void BKE_layer_sync_new_scene_collection(Scene *scene, const SceneCollection *sc_parent, SceneCollection *sc) +void BKE_layer_sync_new_scene_collection(ID *owner_id, const SceneCollection *sc_parent, SceneCollection *sc) { - for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { LayerCollection *lc_parent = find_layer_collection_by_scene_collection(lc, sc_parent); if (lc_parent) { @@ -1040,9 +1195,9 @@ void BKE_layer_sync_new_scene_collection(Scene *scene, const SceneCollection *sc /** * Add a corresponding ObjectBase to all the equivalent LayerCollection */ -void BKE_layer_sync_object_link(const Scene *scene, SceneCollection *sc, Object *ob) +void BKE_layer_sync_object_link(const ID *owner_id, SceneCollection *sc, Object *ob) { - for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc); if (found) { @@ -1056,9 +1211,9 @@ void BKE_layer_sync_object_link(const Scene *scene, SceneCollection *sc, Object * Remove the equivalent object base to all layers that have this collection * also remove all reference to ob in the filter_objects */ -void BKE_layer_sync_object_unlink(const Scene *scene, SceneCollection *sc, Object *ob) +void BKE_layer_sync_object_unlink(const ID *owner_id, SceneCollection *sc, Object *ob) { - for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc); if (found) { @@ -1074,9 +1229,9 @@ void BKE_layer_sync_object_unlink(const Scene *scene, SceneCollection *sc, Objec /** * Add a new datablock override */ -void BKE_override_view_layer_datablock_add(ViewLayer *view_layer, int id_type, const char *data_path, const ID *id) +void BKE_override_view_layer_datablock_add(ViewLayer *view_layer, int id_type, const char *data_path, const ID *owner_id) { - UNUSED_VARS(view_layer, id_type, data_path, id); + UNUSED_VARS(view_layer, id_type, data_path, owner_id); TODO_LAYER_OVERRIDE; } @@ -1934,32 +2089,43 @@ static void idproperty_reset(IDProperty **props, IDProperty *props_ref) } void BKE_layer_eval_layer_collection_pre(const struct EvaluationContext *UNUSED(eval_ctx), - Scene *scene, ViewLayer *view_layer) + ID *owner_id, ViewLayer *view_layer) { - DEBUG_PRINT("%s on scene:%s %s (%p)\n", __func__, scene->id.name, view_layer->name, view_layer); + DEBUG_PRINT("%s on %s (%p)\n", __func__, view_layer->name, view_layer); + Scene *scene = (GS(owner_id->name) == ID_SCE) ? (Scene *)owner_id : NULL; + for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { base->flag &= ~(BASE_VISIBLED | BASE_SELECTABLED); - idproperty_reset(&base->collection_properties, scene->collection_properties); + idproperty_reset(&base->collection_properties, scene ? scene->collection_properties : NULL); } /* Sync properties from scene to scene layer. */ - idproperty_reset(&view_layer->properties_evaluated, scene->layer_properties); + idproperty_reset(&view_layer->properties_evaluated, scene ? scene->layer_properties : NULL); IDP_MergeGroup(view_layer->properties_evaluated, view_layer->properties, true); /* TODO(sergey): Is it always required? */ view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY; } +static const char *collection_type_lookup[] = +{ + "None", /* COLLECTION_TYPE_NONE */ + "Group Internal", /* COLLECTION_TYPE_GROUP_INTERNAL */ +}; + void BKE_layer_eval_layer_collection(const struct EvaluationContext *UNUSED(eval_ctx), LayerCollection *layer_collection, LayerCollection *parent_layer_collection) { - DEBUG_PRINT("%s on %s (%p), parent %s (%p)\n", + DEBUG_PRINT("%s on %s (%p) [%s], parent %s (%p) [%s]\n", __func__, layer_collection->scene_collection->name, layer_collection->scene_collection, + collection_type_lookup[layer_collection->scene_collection->type], (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection->name : "NONE", - (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection : NULL); + (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection : NULL, + (parent_layer_collection != NULL) ? collection_type_lookup[parent_layer_collection->scene_collection->type] : ""); + BLI_assert(layer_collection != parent_layer_collection); /* visibility */ layer_collection->flag_evaluated = layer_collection->flag; diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index c0698849045..e25a354c8af 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -75,6 +75,7 @@ #include "BKE_collection.h" #include "BKE_constraint.h" #include "BKE_fcurve.h" +#include "BKE_group.h" #include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_library_query.h" @@ -772,10 +773,11 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call case ID_GR: { Group *group = (Group *) id; - GroupObject *gob; - for (gob = group->gobject.first; gob; gob = gob->next) { - CALLBACK_INVOKE(gob->ob, IDWALK_CB_USER_ONE); + FOREACH_GROUP_OBJECT(group, object) + { + CALLBACK_INVOKE(object, IDWALK_CB_USER_ONE); } + FOREACH_GROUP_OBJECT_END break; } diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index a3376dff98c..fb672cb8b9f 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -270,7 +270,7 @@ static void libblock_remap_data_preprocess_scene_object_unlink( r_id_remap_data->skipped_refcounted++; } else { - BKE_collections_object_remove(r_id_remap_data->bmain, sce, ob, false); + BKE_collections_object_remove(r_id_remap_data->bmain, &sce->id, ob, false); if (!is_indirect) { r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT; } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 5f12a5715ca..bea9e3bdcac 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -746,7 +746,7 @@ Object *BKE_object_add( ob = object_add_common(bmain, view_layer, type, name); layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer); - BKE_collection_object_add(scene, layer_collection->scene_collection, ob); + BKE_collection_object_add(&scene->id, layer_collection->scene_collection, ob); base = BKE_view_layer_base_find(view_layer, ob); BKE_view_layer_base_select(view_layer, base); diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 85635cb7d77..a16acd9d564 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -50,8 +50,9 @@ #include "BKE_animsys.h" #include "BKE_DerivedMesh.h" #include "BKE_font.h" -#include "BKE_group.h" #include "BKE_global.h" +#include "BKE_group.h" +#include "BKE_idprop.h" #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -143,7 +144,8 @@ static void copy_dupli_context(DupliContext *r_ctx, const DupliContext *ctx, Obj */ static DupliObject *make_dupli(const DupliContext *ctx, Object *ob, float mat[4][4], int index, - bool animated, bool hide) + bool animated, bool hide, + IDProperty *collection_properties) { DupliObject *dob; int i; @@ -198,6 +200,10 @@ static DupliObject *make_dupli(const DupliContext *ctx, dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->object->id.name + 2)); } + if (collection_properties) { + dob->collection_properties = IDP_CopyProperty(collection_properties); + } + return dob; } @@ -238,23 +244,23 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild Object *obedit = ctx->scene->obedit; if (ctx->group) { - unsigned int lay = ctx->group->layer; int groupid = 0; - GroupObject *go; - for (go = ctx->group->gobject.first; go; go = go->next, groupid++) { - Object *ob = go->ob; - - if ((ob->lay & lay) && ob != obedit && is_child(ob, parent)) { + FOREACH_GROUP_BASE(ctx->group, base) + { + Object *ob = base->object; + if ((base->flag & BASE_VISIBLED) && ob != obedit && is_child(ob, parent)) { DupliContext pctx; copy_dupli_context(&pctx, ctx, ctx->object, NULL, groupid, false); /* mballs have a different dupli handling */ - if (ob->type != OB_MBALL) + if (ob->type != OB_MBALL) { ob->flag |= OB_DONE; /* doesnt render */ - + } make_child_duplis_cb(&pctx, userdata, ob); } + groupid++; } + FOREACH_GROUP_BASE_END } else { int baseid = 0; @@ -281,13 +287,12 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild /* OB_DUPLIGROUP */ static void make_duplis_group(const DupliContext *ctx) { - bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER); Object *ob = ctx->object; Group *group; - GroupObject *go; + Base *base; float group_mat[4][4]; int id; - bool animated, hide; + bool animated; if (ob->dup_group == NULL) return; group = ob->dup_group; @@ -309,34 +314,18 @@ static void make_duplis_group(const DupliContext *ctx) animated = BKE_group_is_animated(group, ob); - for (go = group->gobject.first, id = 0; go; go = go->next, id++) { - /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ - if (go->ob != ob) { + for (base = group->view_layer->object_bases.first, id = 0; base; base = base->next, id++) { + if (base->object != ob && (base->flag & BASE_VISIBLED)) { float mat[4][4]; - /* Special case for instancing dupli-groups, see: T40051 - * this object may be instanced via dupli-verts/faces, in this case we don't want to render - * (blender convention), but _do_ show in the viewport. - * - * Regular objects work fine but not if we're instancing dupli-groups, - * because the rules for rendering aren't applied to objects they instance. - * We could recursively pass down the 'hide' flag instead, but that seems unnecessary. - */ - if (for_render && go->ob->parent && go->ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES)) { - continue; - } - /* group dupli offset, should apply after everything else */ - mul_m4_m4m4(mat, group_mat, go->ob->obmat); + mul_m4_m4m4(mat, group_mat, base->object->obmat); - /* check the group instance and object layers match, also that the object visible flags are ok. */ - hide = (go->ob->lay & group->layer) == 0 || - (for_render ? go->ob->restrictflag & OB_RESTRICT_RENDER : go->ob->restrictflag & OB_RESTRICT_VIEW); - - make_dupli(ctx, go->ob, mat, id, animated, hide); + BLI_assert(base->collection_properties != NULL); + make_dupli(ctx, base->object, mat, id, animated, false, base->collection_properties); /* recursion */ - make_recursive_duplis(ctx, go->ob, group_mat, id, animated); + make_recursive_duplis(ctx, base->object, group_mat, id, animated); } } } @@ -399,7 +388,7 @@ static void make_duplis_frames(const DupliContext *ctx) BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, (float)scene->r.cfra); - make_dupli(ctx, ob, ob->obmat, scene->r.cfra, false, false); + make_dupli(ctx, ob, ob->obmat, scene->r.cfra, false, false, NULL); } } @@ -484,7 +473,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], */ mul_m4_m4m4(space_mat, obmat, inst_ob->imat); - dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false); + dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false, NULL); if (vdd->orco) copy_v3_v3(dob->orco, vdd->orco[index]); @@ -669,7 +658,7 @@ static void make_duplis_font(const DupliContext *ctx) copy_v3_v3(obmat[3], vec); - make_dupli(ctx, ob, obmat, a, false, false); + make_dupli(ctx, ob, obmat, a, false, false, NULL); } } @@ -775,7 +764,7 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj */ mul_m4_m4m4(space_mat, obmat, inst_ob->imat); - dob = make_dupli(ctx, inst_ob, obmat, a, false, false); + dob = make_dupli(ctx, inst_ob, obmat, a, false, false, NULL); if (use_texcoords) { float w = 1.0f / (float)mp->totloop; @@ -858,7 +847,6 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER; bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); - GroupObject *go; Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; DupliObject *dob; ParticleDupliWeight *dw; @@ -912,10 +900,10 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem return; } else { /*PART_DRAW_GR */ - if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->gobject)) + if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->view_layer->object_bases)) return; - if (BLI_findptr(&part->dup_group->gobject, par, offsetof(GroupObject, ob))) { + if (BLI_findptr(&part->dup_group->view_layer->object_bases, par, offsetof(Base, object))) { return; } } @@ -947,8 +935,12 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem totgroup += dw->count; } else { - for (go = part->dup_group->gobject.first; go; go = go->next) + FOREACH_GROUP_OBJECT(part->dup_group, object) + { + (void) object; totgroup++; + } + FOREACH_GROUP_OBJECT_END } /* we also copy the actual objects to restore afterwards, since @@ -967,11 +959,18 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } } else { - go = part->dup_group->gobject.first; - for (a = 0; a < totgroup; a++, go = go->next) { - oblist[a] = go->ob; - obcopylist[a] = *go->ob; + a = 0; + FOREACH_GROUP_OBJECT(part->dup_group, object) + { + oblist[a] = object; + obcopylist[a] = *object; + a++; + + if (a >= totgroup) { + continue; + } } + FOREACH_GROUP_OBJECT_END } } else { @@ -1060,23 +1059,33 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { - for (go = part->dup_group->gobject.first, b = 0; go; go = go->next, b++) { - + b = 0; + FOREACH_GROUP_OBJECT(part->dup_group, object) + { copy_m4_m4(tmat, oblist[b]->obmat); + /* apply particle scale */ mul_mat3_m4_fl(tmat, size * scale); mul_v3_fl(tmat[3], size * scale); + /* group dupli offset, should apply after everything else */ - if (!is_zero_v3(part->dup_group->dupli_ofs)) + if (!is_zero_v3(part->dup_group->dupli_ofs)) { sub_v3_v3(tmat[3], part->dup_group->dupli_ofs); + } + /* individual particle transform */ mul_m4_m4m4(mat, pamat, tmat); - dob = make_dupli(ctx, go->ob, mat, a, false, false); + dob = make_dupli(ctx, object, mat, a, false, false, NULL); dob->particle_system = psys; - if (use_texcoords) + + if (use_texcoords) { psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); + } + + b++; } + FOREACH_GROUP_OBJECT_END } else { /* to give ipos in object correct offset */ @@ -1121,7 +1130,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); - dob = make_dupli(ctx, ob, mat, a, false, false); + dob = make_dupli(ctx, ob, mat, a, false, false, NULL); dob->particle_system = psys; if (use_texcoords) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); @@ -1238,6 +1247,14 @@ ListBase *object_duplilist(const EvaluationContext *eval_ctx, Scene *sce, Object void free_object_duplilist(ListBase *lb) { + + for (DupliObject *dob = lb->first; dob; dob = dob->next) { + if (dob->collection_properties) { + IDP_FreeProperty(dob->collection_properties); + MEM_freeN(dob->collection_properties); + } + } + BLI_freelistN(lb); MEM_freeN(lb); } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 209c7398d38..7d1c80dca41 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -327,18 +327,17 @@ bool psys_check_edited(ParticleSystem *psys) void psys_check_group_weights(ParticleSettings *part) { ParticleDupliWeight *dw, *tdw; - GroupObject *go; int current = 0; - if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first) { + if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->view_layer->object_bases.first) { /* First try to find NULL objects from their index, * and remove all weights that don't have an object in the group. */ dw = part->dupliweights.first; while (dw) { if (dw->ob == NULL || !BKE_group_object_exists(part->dup_group, dw->ob)) { - go = (GroupObject *)BLI_findlink(&part->dup_group->gobject, dw->index); - if (go) { - dw->ob = go->ob; + Base *base = BLI_findlink(&part->dup_group->view_layer->object_bases, dw->index); + if (base != NULL) { + dw->ob = base->object; } else { tdw = dw->next; @@ -352,21 +351,21 @@ void psys_check_group_weights(ParticleSettings *part) } /* then add objects in the group to new list */ - go = part->dup_group->gobject.first; - while (go) { + FOREACH_GROUP_OBJECT(part->dup_group, object) + { dw = part->dupliweights.first; - while (dw && dw->ob != go->ob) + while (dw && dw->ob != object) { dw = dw->next; - + } + if (!dw) { dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight"); - dw->ob = go->ob; + dw->ob = object; dw->count = 1; BLI_addtail(&part->dupliweights, dw); } - - go = go->next; } + FOREACH_GROUP_OBJECT_END dw = part->dupliweights.first; for (; dw; dw = dw->next) { diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index f75b14579c7..bd4b817c8cd 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -57,6 +57,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_mesh.h" @@ -90,26 +91,30 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw) if (rbw->physics_world) { /* free physics references, we assume that all physics objects in will have been added to the world */ - GroupObject *go; if (rbw->constraints) { - for (go = rbw->constraints->gobject.first; go; go = go->next) { - if (go->ob && go->ob->rigidbody_constraint) { - RigidBodyCon *rbc = go->ob->rigidbody_constraint; - - if (rbc->physics_constraint) + FOREACH_GROUP_OBJECT(rbw->constraints, object) + { + if (object->rigidbody_constraint) { + RigidBodyCon *rbc = object->rigidbody_constraint; + if (rbc->physics_constraint) { RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + } } } + FOREACH_GROUP_OBJECT_END } - if (rbw->group) { - for (go = rbw->group->gobject.first; go; go = go->next) { - if (go->ob && go->ob->rigidbody_object) { - RigidBodyOb *rbo = go->ob->rigidbody_object; - if (rbo->physics_object) + if (rbw->group) { + FOREACH_GROUP_OBJECT(rbw->group, object) + { + if (object->rigidbody_object) { + RigidBodyOb *rbo = object->rigidbody_object; + if (rbo->physics_object) { RB_dworld_remove_body(rbw->physics_world, rbo->physics_object); + } } } + FOREACH_GROUP_OBJECT_END } /* free dynamics world */ RB_dworld_delete(rbw->physics_world); @@ -1124,7 +1129,6 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob) RigidBodyWorld *rbw = scene->rigidbody_world; RigidBodyOb *rbo = ob->rigidbody_object; RigidBodyCon *rbc; - GroupObject *go; int i; if (rbw) { @@ -1144,8 +1148,8 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob) /* remove object from rigid body constraints */ if (rbw->constraints) { - for (go = rbw->constraints->gobject.first; go; go = go->next) { - Object *obt = go->ob; + FOREACH_GROUP_OBJECT(rbw->constraints, obt) + { if (obt && obt->rigidbody_constraint) { rbc = obt->rigidbody_constraint; if (ELEM(ob, rbc->ob1, rbc->ob2)) { @@ -1153,6 +1157,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob) } } } + FOREACH_GROUP_OBJECT_END } } @@ -1186,20 +1191,22 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) /* Update object array and rigid body count so they're in sync with the rigid body group */ static void rigidbody_update_ob_array(RigidBodyWorld *rbw) { - GroupObject *go; int i, n; - n = BLI_listbase_count(&rbw->group->gobject); + n = BLI_listbase_count(&rbw->group->view_layer->object_bases); if (rbw->numbodies != n) { rbw->numbodies = n; rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies); } - for (go = rbw->group->gobject.first, i = 0; go; go = go->next, i++) { - Object *ob = go->ob; - rbw->objects[i] = ob; + i = 0; + FOREACH_GROUP_OBJECT(rbw->group, object) + { + rbw->objects[i] = object; + i++; } + FOREACH_GROUP_OBJECT_END } static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw) @@ -1313,8 +1320,6 @@ static void rigidbody_update_sim_ob(const struct EvaluationContext *eval_ctx, Sc */ static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx, Scene *scene, RigidBodyWorld *rbw, bool rebuild) { - GroupObject *go; - /* update world */ if (rebuild) BKE_rigidbody_validate_sim_world(scene, rbw, true); @@ -1327,24 +1332,22 @@ static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx * Memory management needs redesign here, this is just a dirty workaround. */ if (rebuild && rbw->constraints) { - for (go = rbw->constraints->gobject.first; go; go = go->next) { - Object *ob = go->ob; - if (ob) { - RigidBodyCon *rbc = ob->rigidbody_constraint; - if (rbc && rbc->physics_constraint) { - RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); - RB_constraint_delete(rbc->physics_constraint); - rbc->physics_constraint = NULL; - } + FOREACH_GROUP_OBJECT(rbw->constraints, ob) + { + RigidBodyCon *rbc = ob->rigidbody_constraint; + if (rbc && rbc->physics_constraint) { + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + RB_constraint_delete(rbc->physics_constraint); + rbc->physics_constraint = NULL; } } + FOREACH_GROUP_OBJECT_END } /* update objects */ - for (go = rbw->group->gobject.first; go; go = go->next) { - Object *ob = go->ob; - - if (ob && ob->type == OB_MESH) { + FOREACH_GROUP_OBJECT(rbw->group, ob) + { + if (ob->type == OB_MESH) { /* validate that we've got valid object set up here... */ RigidBodyOb *rbo = ob->rigidbody_object; /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ @@ -1385,62 +1388,59 @@ static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx rigidbody_update_sim_ob(eval_ctx, scene, rbw, ob, rbo); } } + FOREACH_GROUP_OBJECT_END /* update constraints */ if (rbw->constraints == NULL) /* no constraints, move on */ return; - for (go = rbw->constraints->gobject.first; go; go = go->next) { - Object *ob = go->ob; - if (ob) { - /* validate that we've got valid object set up here... */ - RigidBodyCon *rbc = ob->rigidbody_constraint; - /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ - BKE_object_where_is_calc(eval_ctx, scene, ob); + FOREACH_GROUP_OBJECT(rbw->constraints, ob) + { + /* validate that we've got valid object set up here... */ + RigidBodyCon *rbc = ob->rigidbody_constraint; + /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ + BKE_object_where_is_calc(eval_ctx, scene, ob); - if (rbc == NULL) { - /* Since this object is included in the group but doesn't have - * constraint settings (perhaps it was added manually), add! - */ - ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED); - rigidbody_validate_sim_constraint(rbw, ob, true); + if (rbc == NULL) { + /* Since this object is included in the group but doesn't have + * constraint settings (perhaps it was added manually), add! + */ + ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED); + rigidbody_validate_sim_constraint(rbw, ob, true); - rbc = ob->rigidbody_constraint; + rbc = ob->rigidbody_constraint; + } + else { + /* perform simulation data updates as tagged */ + if (rebuild) { + /* World has been rebuilt so rebuild constraint */ + rigidbody_validate_sim_constraint(rbw, ob, true); } - else { - /* perform simulation data updates as tagged */ - if (rebuild) { - /* World has been rebuilt so rebuild constraint */ - rigidbody_validate_sim_constraint(rbw, ob, true); - } - else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) { - rigidbody_validate_sim_constraint(rbw, ob, false); - } - rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE; + else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) { + rigidbody_validate_sim_constraint(rbw, ob, false); } + rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE; } } + FOREACH_GROUP_OBJECT_END } static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw) { - GroupObject *go; - - for (go = rbw->group->gobject.first; go; go = go->next) { - Object *ob = go->ob; - - if (ob) { - RigidBodyOb *rbo = ob->rigidbody_object; - /* reset kinematic state for transformed objects */ - if (rbo && (ob->flag & SELECT) && (G.moving & G_TRANSFORM_OBJ)) { - RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); - RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); - /* deactivate passive objects so they don't interfere with deactivation of active objects */ - if (rbo->type == RBO_TYPE_PASSIVE) - RB_body_deactivate(rbo->physics_object); - } + FOREACH_GROUP_BASE(rbw->group, base) + { + Object *ob = base->object; + RigidBodyOb *rbo = ob->rigidbody_object; + /* Reset kinematic state for transformed objects. */ + if (rbo && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ)) { + RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); + RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); + /* Deactivate passive objects so they don't interfere with deactivation of active objects. */ + if (rbo->type == RBO_TYPE_PASSIVE) + RB_body_deactivate(rbo->physics_object); } } + FOREACH_GROUP_BASE_END } bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) @@ -1567,7 +1567,7 @@ void BKE_rigidbody_rebuild_world(const struct EvaluationContext *eval_ctx, Scene cache = rbw->pointcache; /* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */ - if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->gobject)) { + if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->view_layer->object_bases)) { cache->flag |= PTCACHE_OUTDATED; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index ca31eed6552..b3d7e2affd3 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -151,89 +151,6 @@ static void remove_sequencer_fcurves(Scene *sce) } } -/* copy SceneCollection tree but keep pointing to the same objects */ -static void scene_collection_copy(SceneCollection *sc_dst, SceneCollection *sc_src, const int flag) -{ - BLI_duplicatelist(&sc_dst->objects, &sc_src->objects); - if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { - for (LinkData *link = sc_dst->objects.first; link; link = link->next) { - id_us_plus(link->data); - } - } - - BLI_duplicatelist(&sc_dst->filter_objects, &sc_src->filter_objects); - if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { - for (LinkData *link = sc_dst->filter_objects.first; link; link = link->next) { - id_us_plus(link->data); - } - } - - BLI_duplicatelist(&sc_dst->scene_collections, &sc_src->scene_collections); - for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first; - nsc_src; - nsc_src = nsc_src->next, nsc_dst = nsc_dst->next) - { - scene_collection_copy(nsc_dst, nsc_src, flag); - } -} - -/* Find the equivalent SceneCollection in the new tree */ -static SceneCollection *scene_collection_from_new_tree(SceneCollection *sc_reference, SceneCollection *sc_dst, SceneCollection *sc_src) -{ - if (sc_src == sc_reference) { - return sc_dst; - } - - for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first; - nsc_src; - nsc_src = nsc_src->next, nsc_dst = nsc_dst->next) - { - SceneCollection *found = scene_collection_from_new_tree(sc_reference, nsc_dst, nsc_src); - if (found != NULL) { - return found; - } - } - return NULL; -} - -static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src) -{ - LayerCollection *layer_collection_dst = (LayerCollection *)layer_collections_dst->first; - const LayerCollection *layer_collection_src = (const LayerCollection *)layer_collections_src->first; - while (layer_collection_dst != NULL) { - layer_collection_dst->flag = layer_collection_src->flag; - - if (layer_collection_dst->properties != NULL) { - IDP_FreeProperty(layer_collection_dst->properties); - MEM_SAFE_FREE(layer_collection_dst->properties); - } - - if (layer_collection_src->properties != NULL) { - layer_collection_dst->properties = IDP_CopyProperty(layer_collection_src->properties); - } - - layer_collections_sync_flags(&layer_collection_dst->layer_collections, - &layer_collection_src->layer_collections); - - layer_collection_dst = layer_collection_dst->next; - layer_collection_src = layer_collection_src->next; - } -} - - -/* recreate the LayerCollection tree */ -static void layer_collections_recreate( - ViewLayer *view_layer_dst, ListBase *lb_src, SceneCollection *mc_dst, SceneCollection *mc_src) -{ - for (LayerCollection *lc_src = lb_src->first; lc_src; lc_src = lc_src->next) { - SceneCollection *sc_dst = scene_collection_from_new_tree(lc_src->scene_collection, mc_dst, mc_src); - BLI_assert(sc_dst); - - /* instead of synchronizing both trees we simply re-create it */ - BKE_collection_link(view_layer_dst, sc_dst); - } -} - /** * Only copy internal data of Scene ID from source to already allocated/initialized destination. * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. @@ -254,11 +171,11 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons /* layers and collections */ sce_dst->collection = MEM_dupallocN(sce_src->collection); - SceneCollection *mc_src = BKE_collection_master(sce_src); - SceneCollection *mc_dst = BKE_collection_master(sce_dst); + SceneCollection *mc_src = BKE_collection_master(&sce_src->id); + SceneCollection *mc_dst = BKE_collection_master(&sce_dst->id); - /* recursively creates a new SceneCollection tree */ - scene_collection_copy(mc_dst, mc_src, flag_subdata); + /* Recursively creates a new SceneCollection tree. */ + BKE_collection_copy_data(mc_dst, mc_src, flag_subdata); IDPropertyTemplate val = {0}; BLI_duplicatelist(&sce_dst->view_layers, &sce_src->view_layers); @@ -266,39 +183,7 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons view_layer_src; view_layer_src = view_layer_src->next, view_layer_dst = view_layer_dst->next) { - if (view_layer_dst->id_properties != NULL) { - view_layer_dst->id_properties = IDP_CopyProperty_ex(view_layer_dst->id_properties, flag_subdata); - } - BKE_freestyle_config_copy(&view_layer_dst->freestyle_config, &view_layer_src->freestyle_config, flag_subdata); - - view_layer_dst->stats = NULL; - view_layer_dst->properties_evaluated = NULL; - view_layer_dst->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); - IDP_MergeGroup_ex(view_layer_dst->properties, view_layer_src->properties, true, flag_subdata); - - /* we start fresh with no overrides and no visibility flags set - * instead of syncing both trees we simply unlink and relink the scene collection */ - BLI_listbase_clear(&view_layer_dst->layer_collections); - BLI_listbase_clear(&view_layer_dst->object_bases); - BLI_listbase_clear(&view_layer_dst->drawdata); - - layer_collections_recreate(view_layer_dst, &view_layer_src->layer_collections, mc_dst, mc_src); - - /* Now we handle the syncing for visibility, selectability, ... */ - layer_collections_sync_flags(&view_layer_dst->layer_collections, &view_layer_src->layer_collections); - - Object *active_ob = OBACT(view_layer_src); - for (Base *base_src = view_layer_src->object_bases.first, *base_dst = view_layer_dst->object_bases.first; - base_src; - base_src = base_src->next, base_dst = base_dst->next) - { - base_dst->flag = base_src->flag; - base_dst->flag_legacy = base_src->flag_legacy; - - if (base_dst->object == active_ob) { - view_layer_dst->basact = base_dst; - } - } + BKE_view_layer_copy_data(view_layer_dst, view_layer_src, mc_dst, mc_src, flag_subdata); } sce_dst->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); @@ -659,7 +544,7 @@ void BKE_scene_free_ex(Scene *sce, const bool do_id_user) } /* Master Collection */ - BKE_collection_master_free(sce, do_id_user); + BKE_collection_master_free(&sce->id, do_id_user); MEM_freeN(sce->collection); sce->collection = NULL; @@ -1092,7 +977,6 @@ void BKE_scene_set_background(Main *bmain, Scene *scene) { Object *ob; Group *group; - GroupObject *go; /* check for cyclic sets, for reading old files but also for definite security (py?) */ BKE_scene_validate_setscene(bmain, scene); @@ -1107,11 +991,11 @@ void BKE_scene_set_background(Main *bmain, Scene *scene) /* group flags again */ for (group = bmain->group.first; group; group = group->id.next) { - for (go = group->gobject.first; go; go = go->next) { - if (go->ob) { - go->ob->flag |= OB_FROMGROUP; - } + FOREACH_GROUP_OBJECT(group, object) + { + object->flag |= OB_FROMGROUP; } + FOREACH_GROUP_OBJECT_END } /* copy layers and flags from bases to objects */ diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index d7d274f32b5..e3af77166a9 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -74,6 +74,7 @@ variables on the UI for now #include "BKE_curve.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_modifier.h" #include "BKE_softbody.h" #include "BKE_pointcache.h" @@ -520,29 +521,20 @@ static void ccd_build_deflector_hash(ViewLayer *view_layer, Group *group, Object if (!hash) return; + /* Explicit collision group. */ if (group) { - /* Explicit collision group */ - for (GroupObject *go = group->gobject.first; go; go = go->next) { - ob = go->ob; - - if (ob == vertexowner || ob->type != OB_MESH) - continue; - - ccd_build_deflector_hash_single(hash, ob); - } + view_layer = group->view_layer; } - else { - for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { - /*Only proceed for mesh object in same layer */ - if (base->object->type == OB_MESH) { - ob = base->object; - if ((vertexowner) && (ob == vertexowner)) { - /* if vertexowner is given we don't want to check collision with owner object */ - continue; - } - ccd_build_deflector_hash_single(hash, ob); + for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { + /* Only proceed for mesh object in same layer. */ + if (base->object->type == OB_MESH) { + ob = base->object; + if (ob == vertexowner) { + /* If vertexowner is given we don't want to check collision with owner object. */ + continue; } + ccd_build_deflector_hash_single(hash, ob); } } } @@ -566,31 +558,23 @@ static void ccd_update_deflector_hash(ViewLayer *view_layer, Group *group, Objec if ((!hash) || (!vertexowner)) return; + /* Explicit collision group. */ if (group) { - /* Explicit collision group */ - for (GroupObject *go = group->gobject.first; go; go = go->next) { - ob = go->ob; + view_layer = group->view_layer; + } - if (ob == vertexowner || ob->type != OB_MESH) + for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { + /* Only proceed for mesh object in same layer. */ + if (base->object->type == OB_MESH) { + ob = base->object; + if (ob == vertexowner) { + /* If vertexowner is given we don't want to check collision with owner object. */ continue; + } ccd_update_deflector_hash_single(hash, ob); } } - else { - for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { - /*Only proceed for mesh object in same layer */ - if (base->object->type == OB_MESH) { - ob = base->object; - if (ob == vertexowner) { - /* if vertexowner is given we don't want to check collision with owner object */ - continue; - } - - ccd_update_deflector_hash_single(hash, ob); - } - } - } } @@ -979,29 +963,21 @@ static void free_softbody_intern(SoftBody *sb) /** * \note group overrides scene when not NULL. */ -static bool are_there_deflectors(ViewLayer *view_layer, Group *group) +static bool are_there_deflectors(ViewLayer *view_layer) { - if (group) { - for (GroupObject *go = group->gobject.first; go; go = go->next) { - if (go->ob->pd && go->ob->pd->deflect) + for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { + if (base->object->pd) { + if (base->object->pd->deflect) return 1; } } - else { - for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { - if (base->object->pd) { - if (base->object->pd->deflect) - return 1; - } - } - } return 0; } static int query_external_colliders(ViewLayer *view_layer, Group *group) { - return(are_there_deflectors(view_layer, group)); + return(are_there_deflectors(group != NULL ? group->view_layer : view_layer)); } /* --- dependency information functions*/ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 323586b66b2..a91c83c68ef 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -253,6 +253,7 @@ 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); +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 short flag); /* this function ensures that reports are printed, @@ -5832,6 +5833,28 @@ static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollectio } } +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; + base->collection_properties = NULL; + } +} + static void lib_link_scene(FileData *fd, Main *main) { #ifdef USE_SETSCENE_CHECK @@ -5980,24 +6003,7 @@ static void lib_link_scene(FileData *fd, Main *main) lib_link_scene_collection(fd, sce->id.lib, sce->collection); for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) { - /* 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, sce->id.lib, fmc->script); - } - - for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) { - fls->linestyle = newlibadr_us(fd, sce->id.lib, fls->linestyle); - fls->group = newlibadr_us(fd, sce->id.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, sce->id.lib, base->object); - base->flag |= BASE_DIRTY_ENGINE_SETTINGS; - base->collection_properties = NULL; - } + lib_link_view_layer(fd, sce->id.lib, view_layer); } #ifdef USE_SETSCENE_CHECK @@ -6139,6 +6145,31 @@ static void direct_link_layer_collections(FileData *fd, ListBase *lb) } } +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); + + if (view_layer->properties != NULL) { + view_layer->properties = newdataadr(fd, view_layer->properties); + BLI_assert(view_layer->properties != NULL); + IDP_DirectLinkGroup_OrFree(&view_layer->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + BKE_view_layer_engine_settings_validate_layer(view_layer); + } + + 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)); + + view_layer->properties_evaluated = NULL; + + BLI_listbase_clear(&view_layer->drawdata); +} + /** * Workspaces store a render layer pointer which can only be read after scene is read. */ @@ -6416,27 +6447,7 @@ static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain) /* insert into global old-new map for reading without UI (link_global accesses it again) */ link_glob_list(fd, &sce->view_layers); for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) { - 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); - - if (view_layer->properties != NULL) { - view_layer->properties = newdataadr(fd, view_layer->properties); - BLI_assert(view_layer->properties != NULL); - IDP_DirectLinkGroup_OrFree(&view_layer->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - BKE_view_layer_engine_settings_validate_layer(view_layer); - } - - 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)); - - view_layer->properties_evaluated = NULL; - - BLI_listbase_clear(&view_layer->drawdata); + direct_link_view_layer(fd, view_layer); } sce->collection_properties = newdataadr(fd, sce->collection_properties); @@ -7781,30 +7792,61 @@ 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); - - bool add_us = false; - - for (GroupObject *go = group->gobject.first; go; go = go->next) { - go->ob = newlibadr_real_us(fd, group->id.lib, go->ob); - if (go->ob) { - go->ob->flag |= OB_FROMGROUP; - /* if group has an object, it increments user... */ - add_us = true; + + 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; } - if (add_us) { + + 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); } - BKE_group_object_unlink(group, NULL); /* removes NULL entries */ - - group->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -9407,6 +9449,11 @@ static void expand_group(FileData *fd, Main *mainvar, Group *group) for (go = group->gobject.first; go; go = go->next) { expand_doit(fd, mainvar, go->ob); } + + if (group->collection != NULL) { + expand_scene_collection(fd, mainvar, group->collection); + } + } static void expand_key(FileData *fd, Main *mainvar, Key *key) @@ -10233,7 +10280,7 @@ static void give_base_to_objects( scene_collection = get_scene_collection_active_or_create(scene, view_layer, FILE_ACTIVE_COLLECTION); } - BKE_collection_object_add(scene, scene_collection, ob); + BKE_collection_object_add(&scene->id, scene_collection, ob); base = BKE_view_layer_base_find(view_layer, ob); BKE_scene_object_base_flag_sync_from_base(base); @@ -10275,7 +10322,7 @@ static void give_base_to_groups( ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2); ob->type = OB_EMPTY; - BKE_collection_object_add(scene, scene_collection, ob); + BKE_collection_object_add(&scene->id, scene_collection, ob); base = BKE_view_layer_base_find(view_layer, ob); if (base->flag & BASE_SELECTABLED) { @@ -10369,7 +10416,7 @@ static SceneCollection *get_scene_collection_active_or_create(struct Scene *scen lc = BKE_layer_collection_get_active_ensure(scene, view_layer); } else { - SceneCollection *sc = BKE_collection_add(scene, NULL, NULL); + SceneCollection *sc = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL); lc = BKE_collection_link(view_layer, sc); } @@ -10388,7 +10435,7 @@ static void link_object_postprocess(ID *id, Scene *scene, ViewLayer *view_layer, ob->mode = OB_MODE_OBJECT; sc = get_scene_collection_active_or_create(scene, view_layer, flag); - BKE_collection_object_add(scene, sc, ob); + BKE_collection_object_add(&scene->id, sc, ob); base = BKE_view_layer_base_find(view_layer, ob); BKE_scene_object_base_flag_sync_from_base(base); diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 3b5e248f58b..8f2295781bf 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -39,6 +39,7 @@ #include "DNA_object_types.h" #include "DNA_camera_types.h" #include "DNA_gpu_types.h" +#include "DNA_group_types.h" #include "DNA_lamp_types.h" #include "DNA_layer_types.h" #include "DNA_material_types.h" @@ -52,6 +53,7 @@ #include "BKE_collection.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" @@ -171,7 +173,7 @@ void do_versions_after_linking_280(Main *main) 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); + SceneCollection *sc_master = BKE_collection_master(&scene->id); BLI_strncpy(sc_master->name, "Master Collection", sizeof(sc_master->name)); struct DoVersionSceneCollections { @@ -242,7 +244,7 @@ void do_versions_after_linking_280(Main *main) layer + 1, collections[DO_VERSION_COLLECTION_VISIBLE].suffix); collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer] = - BKE_collection_add(scene, sc_master, name); + BKE_collection_add(&scene->id, sc_master, COLLECTION_TYPE_NONE, name); collections[DO_VERSION_COLLECTION_VISIBLE].created |= (1 << layer); } @@ -254,12 +256,16 @@ void do_versions_after_linking_280(Main *main) "Collection %d%s", layer + 1, collections[collection_index].suffix); - collections[collection_index].collections[layer] = BKE_collection_add(scene, sc_parent, name); + collections[collection_index].collections[layer] = BKE_collection_add( + &scene->id, + sc_parent, + COLLECTION_TYPE_NONE, + name); collections[collection_index].created |= (1 << layer); } } - BKE_collection_object_add(scene, collections[collection_index].collections[layer], base->object); + BKE_collection_object_add(&scene->id, collections[collection_index].collections[layer], base->object); } if (base->flag & SELECT) { @@ -542,6 +548,43 @@ void do_versions_after_linking_280(Main *main) BLI_freelistN(&scene->r.layers); } } + + { + /* 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_VISIBLE; + } + } + + GroupObject *go; + while ((go = BLI_pophead(&group->gobject))) { + MEM_freeN(go); + } + } + } } static void do_version_layer_collections_idproperties(ListBase *lb) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 08ec2231e38..36ce277e4cf 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -168,6 +168,7 @@ #include "BKE_curve.h" #include "BKE_constraint.h" #include "BKE_global.h" // for G +#include "BKE_group.h" #include "BKE_idcode.h" #include "BKE_library.h" // for set_listbasepointers #include "BKE_library_override.h" @@ -1348,9 +1349,13 @@ static void write_particlesettings(WriteData *wd, ParticleSettings *part) if (dw->ob != NULL) { dw->index = 0; if (part->dup_group) { /* can be NULL if lining fails or set to None */ - for (GroupObject *go = part->dup_group->gobject.first; - go && go->ob != dw->ob; - go = go->next, dw->index++); + FOREACH_GROUP_OBJECT(part->dup_group, object) + { + if (object != dw->ob) { + dw->index++; + } + } + FOREACH_GROUP_OBJECT_END } } writestruct(wd, DATA, ParticleDupliWeight, 1, dw); @@ -2612,6 +2617,28 @@ static void write_layer_collections(WriteData *wd, ListBase *lb) } } +static void write_view_layer(WriteData *wd, ViewLayer *view_layer) +{ + writestruct(wd, DATA, ViewLayer, 1, view_layer); + writelist(wd, DATA, Base, &view_layer->object_bases); + if (view_layer->properties) { + IDP_WriteProperty(view_layer->properties, wd); + } + + if (view_layer->id_properties) { + IDP_WriteProperty(view_layer->id_properties, wd); + } + + for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) { + writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc); + } + + for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) { + writestruct(wd, DATA, FreestyleLineSet, 1, fls); + } + write_layer_collections(wd, &view_layer->layer_collections); +} + static void write_scene(WriteData *wd, Scene *sce) { /* write LibData */ @@ -2795,26 +2822,7 @@ static void write_scene(WriteData *wd, Scene *sce) write_scene_collection(wd, sce->collection); for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) { - writestruct(wd, DATA, ViewLayer, 1, view_layer); - writelist(wd, DATA, Base, &view_layer->object_bases); - - if (view_layer->properties) { - IDP_WriteProperty(view_layer->properties, wd); - } - - if (view_layer->id_properties) { - IDP_WriteProperty(view_layer->id_properties, wd); - } - - for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) { - writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc); - } - - for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) { - writestruct(wd, DATA, FreestyleLineSet, 1, fls); - } - - write_layer_collections(wd, &view_layer->layer_collections); + write_view_layer(wd, view_layer); } if (sce->layer_properties) { @@ -3233,10 +3241,8 @@ static void write_group(WriteData *wd, Group *group) write_iddata(wd, &group->id); write_previews(wd, group->preview); - - for (GroupObject *go = group->gobject.first; go; go = go->next) { - writestruct(wd, DATA, GroupObject, 1, go); - } + write_scene_collection(wd, group->collection); + write_view_layer(wd, group->view_layer); } } diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 8908d0e603f..d3e23f740c8 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -267,7 +267,7 @@ void DocumentImporter::finish() std::vector<Object *>::iterator it; for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) { Object *ob = *it; - BKE_collections_object_remove(G.main, sce, ob, true); + BKE_collections_object_remove(G.main, &sce->id, ob, true); } libnode_ob.clear(); diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index aa98f2ee96c..c375c09d869 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -26,6 +26,7 @@ extern "C" { #include "BLI_utildefines.h" + #include "BKE_group.h" #include "BKE_object.h" #include "BLI_listbase.h" } @@ -177,12 +178,13 @@ void SceneExporter::writeNodes(const EvaluationContext *eval_ctx, Object *ob, Sc // empty object else if (ob->type == OB_EMPTY) { // TODO: handle groups (OB_DUPLIGROUP if ((ob->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && ob->dup_group) { - GroupObject *go = NULL; - Group *gr = ob->dup_group; - /* printf("group detected '%s'\n", gr->id.name + 2); */ - for (go = (GroupObject *)(gr->gobject.first); go; go = go->next) { - printf("\t%s\n", go->ob->id.name); + Group *group = ob->dup_group; + /* printf("group detected '%s'\n", group->id.name + 2); */ + FOREACH_GROUP_OBJECT(group, object) + { + printf("\t%s\n", object->id.name); } + FOREACH_GROUP_OBJECT_END } } diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 1a6f2675cc7..6a52027fb47 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -147,7 +147,7 @@ Object *bc_add_object(Scene *scene, int type, const char *name) ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene); LayerCollection *layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer); - BKE_collection_object_add(scene, layer_collection->scene_collection, ob); + BKE_collection_object_add(&scene->id, layer_collection->scene_collection, ob); Base *base = BKE_view_layer_base_find(view_layer, ob); BKE_view_layer_base_select(view_layer, base); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 18e9c01113d..d9634b525e1 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -428,9 +428,11 @@ void DepsgraphNodeBuilder::build_group(Group *group) } group_id->tag |= LIB_TAG_DOIT; - LINKLIST_FOREACH (GroupObject *, go, &group->gobject) { - build_object(NULL, go->ob, DEG_ID_LINKED_INDIRECTLY); + LINKLIST_FOREACH(Base *, base, &group->view_layer->object_bases) { + build_object(NULL, base->object, DEG_ID_LINKED_INDIRECTLY); } + + build_view_layer_collections(&group->id, group->view_layer); } void DepsgraphNodeBuilder::build_object(Base *base, @@ -802,8 +804,8 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) /* objects - simulation participants */ if (rbw->group) { - LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) { - Object *object = go->ob; + LINKLIST_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) { + Object *object = base->object; if (!object || (object->type != OB_MESH)) continue; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 5c0a5054590..c9bdd194227 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -208,11 +208,13 @@ struct DepsgraphNodeBuilder { int index; LayerCollection *parent; }; - void build_layer_collection(LayerCollection *layer_collection, + void build_layer_collection(ID *owner_id, + LayerCollection *layer_collection, LayerCollectionState *state); - void build_layer_collections(ListBase *layer_collections, + void build_layer_collections(ID *owner_id, + ListBase *layer_collections, LayerCollectionState *state); - void build_view_layer_collections(Scene *scene, ViewLayer *view_layer); + void build_view_layer_collections(ID *owner_id, ViewLayer *view_layer); protected: struct SavedEntryTag { ID *id; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc index 4d4bf2e4ffe..b34395e8a9a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc @@ -62,6 +62,7 @@ extern "C" { namespace DEG { void DepsgraphNodeBuilder::build_layer_collection( + ID *owner_id, LayerCollection *layer_collection, LayerCollectionState *state) { @@ -69,7 +70,7 @@ void DepsgraphNodeBuilder::build_layer_collection( * Harmless but could be optimized. */ ComponentDepsNode *comp = add_component_node( - &scene_->id, + owner_id, DEG_NODE_TYPE_LAYER_COLLECTIONS); add_operation_node(comp, @@ -85,31 +86,32 @@ void DepsgraphNodeBuilder::build_layer_collection( /* Recurs into nested layer collections. */ LayerCollection *parent = state->parent; state->parent = layer_collection; - build_layer_collections(&layer_collection->layer_collections, state); + build_layer_collections(owner_id, &layer_collection->layer_collections, state); state->parent = parent; } -void DepsgraphNodeBuilder::build_layer_collections(ListBase *layer_collections, +void DepsgraphNodeBuilder::build_layer_collections(ID *owner_id, + ListBase *layer_collections, LayerCollectionState *state) { LINKLIST_FOREACH (LayerCollection *, layer_collection, layer_collections) { - build_layer_collection(layer_collection, state); + build_layer_collection(owner_id, layer_collection, state); } } void DepsgraphNodeBuilder::build_view_layer_collections( - Scene *scene, + ID *owner_id, ViewLayer *view_layer) { LayerCollectionState state; state.index = 0; ComponentDepsNode *comp = add_component_node( - &scene_->id, + owner_id, DEG_NODE_TYPE_LAYER_COLLECTIONS); add_operation_node(comp, function_bind(BKE_layer_eval_layer_collection_pre, _1, - scene, + owner_id, view_layer), DEG_OPCODE_VIEW_LAYER_INIT); add_operation_node(comp, @@ -118,7 +120,7 @@ void DepsgraphNodeBuilder::build_view_layer_collections( view_layer), DEG_OPCODE_VIEW_LAYER_DONE); state.parent = NULL; - build_layer_collections(&view_layer->layer_collections, &state); + build_layer_collections(owner_id, &view_layer->layer_collections, &state); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index cf77b859b5c..a8325d34a27 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -157,7 +157,7 @@ void DepsgraphNodeBuilder::build_view_layer( build_movieclip(clip); } /* Collections. */ - build_view_layer_collections(scene_cow, view_layer_cow); + build_view_layer_collections(&scene_cow->id, view_layer_cow); /* Parameters evaluation for scene relations mainly. */ add_operation_node(&scene->id, DEG_NODE_TYPE_PARAMETERS, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index f2805cc9a7c..1b9f27932f5 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -413,14 +413,20 @@ void DepsgraphRelationBuilder::build_group(Object *object, Group *group) OperationKey object_local_transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); - LINKLIST_FOREACH (GroupObject *, go, &group->gobject) { - if (!group_done) { - build_object(NULL, go->ob); + + if (!group_done) { + LINKLIST_FOREACH(Base *, base, &group->view_layer->object_bases) { + build_object(NULL, base->object); } - ComponentKey dupli_transform_key(&go->ob->id, DEG_NODE_TYPE_TRANSFORM); + + build_view_layer_collections(&group->id, group->view_layer); + group_id->tag |= LIB_TAG_DOIT; + } + + LINKLIST_FOREACH (Base *, base, &group->view_layer->object_bases) { + ComponentKey dupli_transform_key(&base->object->id, DEG_NODE_TYPE_TRANSFORM); add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup"); } - group_id->tag |= LIB_TAG_DOIT; } void DepsgraphRelationBuilder::build_object(Base *base, Object *object) @@ -1285,8 +1291,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* objects - simulation participants */ if (rbw->group) { - LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) { - Object *object = go->ob; + LINKLIST_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) { + Object *object = base->object; if (object == NULL || object->type != OB_MESH) { continue; } @@ -1339,8 +1345,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* constraints */ if (rbw->constraints) { - LINKLIST_FOREACH (GroupObject *, go, &rbw->constraints->gobject) { - Object *object = go->ob; + LINKLIST_FOREACH (Base *, base, &rbw->constraints->view_layer->object_bases) { + Object *object = base->object; if (object == NULL || !object->rigidbody_constraint) { continue; } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 8fe98ae9901..569383fe479 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -249,11 +249,13 @@ struct DepsgraphRelationBuilder OperationKey done_key; OperationKey prev_key; }; - void build_layer_collection(LayerCollection *layer_collection, + void build_layer_collection(ID *owner_id, + LayerCollection *layer_collection, LayerCollectionState *state); - void build_layer_collections(ListBase *layer_collections, + void build_layer_collections(ID *owner_id, + ListBase *layer_collections, LayerCollectionState *state); - void build_view_layer_collections(ViewLayer *view_layer); + void build_view_layer_collections(struct ID *owner_id, ViewLayer *view_layer); void build_copy_on_write_relations(); void build_copy_on_write_relations(IDDepsNode *id_node); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc index a7c70bfc098..0a8552ba747 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc @@ -69,10 +69,11 @@ extern "C" { namespace DEG { void DepsgraphRelationBuilder::build_layer_collection( + ID *owner_id, LayerCollection *layer_collection, LayerCollectionState *state) { - OperationKey layer_key(&scene_->id, + OperationKey layer_key(owner_id, DEG_NODE_TYPE_LAYER_COLLECTIONS, DEG_OPCODE_VIEW_LAYER_EVAL, layer_collection->scene_collection->name, @@ -83,29 +84,31 @@ void DepsgraphRelationBuilder::build_layer_collection( state->prev_key = layer_key; /* Recurs into nested layer collections. */ - build_layer_collections(&layer_collection->layer_collections, state); + build_layer_collections(owner_id, &layer_collection->layer_collections, state); } void DepsgraphRelationBuilder::build_layer_collections( + ID *owner_id, ListBase *layer_collections, LayerCollectionState *state) { LINKLIST_FOREACH (LayerCollection *, layer_collection, layer_collections) { /* Recurs into the layer. */ - build_layer_collection(layer_collection, state); + build_layer_collection(owner_id, layer_collection, state); } } void DepsgraphRelationBuilder::build_view_layer_collections( + ID *owner_id, ViewLayer *view_layer) { LayerCollectionState state; state.index = 0; - OperationKey init_key(&scene_->id, + OperationKey init_key(owner_id, DEG_NODE_TYPE_LAYER_COLLECTIONS, DEG_OPCODE_VIEW_LAYER_INIT); - OperationKey done_key(&scene_->id, + OperationKey done_key(owner_id, DEG_NODE_TYPE_LAYER_COLLECTIONS, DEG_OPCODE_VIEW_LAYER_DONE); @@ -113,7 +116,7 @@ void DepsgraphRelationBuilder::build_view_layer_collections( state.done_key = done_key; state.prev_key = init_key; - build_layer_collections(&view_layer->layer_collections, &state); + build_layer_collections(owner_id, &view_layer->layer_collections, &state); add_relation(state.prev_key, done_key, "Layer collection order"); } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index fe7ccf6a24c..1f105ee0823 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -112,7 +112,7 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la build_movieclip(clip); } /* Collections. */ - build_view_layer_collections(view_layer); + build_view_layer_collections(&scene_->id, view_layer); /* TODO(sergey): Do this flush on CoW object? */ foreach (OperationDepsNode *node, graph_->operations) { IDDepsNode *id_node = node->owner->owner; diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index d764ea47fea..d8a54642a85 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -36,6 +36,7 @@ extern "C" { #include "BLI_utildefines.h" #include "BLI_math.h" #include "BKE_anim.h" +#include "BKE_idprop.h" #include "BKE_layer.h" } /* extern "C" */ @@ -82,10 +83,10 @@ static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) *temp_dupli_object = *dob->ob; temp_dupli_object->select_color = dupli_parent->select_color; temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROMDUPLI; - temp_dupli_object->base_collection_properties = - dupli_parent->base_collection_properties; + BLI_assert(dob->collection_properties != NULL); + temp_dupli_object->base_collection_properties = dob->collection_properties; + IDP_MergeGroup(temp_dupli_object->base_collection_properties, dupli_parent->base_collection_properties, false); copy_m4_m4(data->temp_dupli_object.obmat, dob->mat); - iter->current = &data->temp_dupli_object; BLI_assert( DEG::deg_validate_copy_on_write_datablock( diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index fc3116d9bd2..1a210f071e0 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1156,7 +1156,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG */ ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info); cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE); - BKE_collection_object_add(scene, sc, ob); + BKE_collection_object_add(&scene->id, sc, ob); base_new = BKE_view_layer_base_find(view_layer, ob); cu->flag |= CU_3D; diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 649e4c7f221..e8807432328 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1221,7 +1221,7 @@ void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob) DEG_id_tag_update_ex(bmain, &ob->id, DEG_TAG_BASE_FLAGS_UPDATE); object_delete_check_glsl_update(ob); - BKE_collections_object_remove(bmain, scene, ob, true); + BKE_collections_object_remove(bmain, &scene->id, ob, true); } static int object_delete_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index fb1c7f04a95..8848b69a927 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -342,17 +342,15 @@ static int make_proxy_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Object *ob, *gob = ED_object_active_context(C); - GroupObject *go; Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); if (gob->dup_group != NULL) { - go = BLI_findlink(&gob->dup_group->gobject, RNA_enum_get(op->ptr, "object")); - ob = go->ob; + Base *base = BLI_findlink(&gob->dup_group->view_layer->object_bases, RNA_enum_get(op->ptr, "object")); + ob = base->object; } else { ob = gob; - gob = NULL; } if (ob) { @@ -397,17 +395,18 @@ static const EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA int totitem = 0; int i = 0; Object *ob = ED_object_active_context(C); - GroupObject *go; if (!ob || !ob->dup_group) return DummyRNA_DEFAULT_items; /* find the object to affect */ - for (go = ob->dup_group->gobject.first; go; go = go->next) { - item_tmp.identifier = item_tmp.name = go->ob->id.name + 2; + FOREACH_GROUP_OBJECT(ob->dup_group, object) + { + item_tmp.identifier = item_tmp.name = object->id.name + 2; item_tmp.value = i++; RNA_enum_item_add(&item, &totitem, &item_tmp); } + FOREACH_GROUP_OBJECT_END RNA_enum_item_end(&item, &totitem); *r_free = true; @@ -1368,10 +1367,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - SceneCollection *sc_to = BKE_collection_master(scene_to); + SceneCollection *sc_to = BKE_collection_master(&scene_to->id); CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - BKE_collection_object_add(scene_to, sc_to, base->object); + BKE_collection_object_add(&scene_to->id, sc_to, base->object); } CTX_DATA_END; @@ -1691,12 +1690,11 @@ static void single_object_users_scene_collection(Main *bmain, Scene *scene, Scen static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups) { Group *group, *groupn; - GroupObject *go; clear_sca_new_poins(); /* BGE logic */ /* duplicate all the objects of the scene */ - SceneCollection *msc = BKE_collection_master(scene); + SceneCollection *msc = BKE_collection_master(&scene->id); single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups); /* loop over ViewLayers and assign the pointers accordingly */ @@ -1708,22 +1706,26 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in /* duplicate groups that consist entirely of duplicated objects */ for (group = bmain->group.first; group; group = group->id.next) { - if (copy_groups && group->gobject.first) { + if (copy_groups && group->view_layer->object_bases.first) { bool all_duplicated = true; - for (go = group->gobject.first; go; go = go->next) { - if (!(go->ob && (go->ob->id.newid))) { + FOREACH_GROUP_OBJECT(group, object) + { + if (object->id.newid == NULL) { all_duplicated = false; break; } } + FOREACH_GROUP_OBJECT_END if (all_duplicated) { groupn = ID_NEW_SET(group, BKE_group_copy(bmain, group)); - for (go = groupn->gobject.first; go; go = go->next) { - go->ob = (Object *)go->ob->id.newid; + FOREACH_GROUP_BASE(groupn, base) + { + base->object = (Object *)base->object->id.newid; } + FOREACH_GROUP_BASE_END } } } @@ -2151,7 +2153,7 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene, id_us_plus(&ob->id); - BKE_collection_object_add(scene, sc, ob); + BKE_collection_object_add(&scene->id, sc, ob); base = BKE_view_layer_base_find(view_layer, ob); base->flag |= BASE_SELECTED; BKE_scene_object_base_flag_sync_from_base(base); diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 53709e4cea7..3cf833756ef 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -270,6 +270,39 @@ static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats) stats->tottri = ob->sculpt->bm->totface; } +static void stats_dupli_object_group_count(SceneCollection *scene_collection, int *count) +{ + for (LinkData *link = scene_collection->objects.first; link; link = link->next) { + (*count)++; + } + + SceneCollection *scene_collection_nested; + for (scene_collection_nested = scene_collection->scene_collections.first; + scene_collection_nested; + scene_collection_nested = scene_collection_nested->next) + { + stats_dupli_object_group_count(scene_collection_nested, count); + } +} + +static void stats_dupli_object_group_doit(SceneCollection *scene_collection, SceneStats *stats, ParticleSystem *psys, + const int totgroup, int *cur) +{ + for (LinkData *link = scene_collection->objects.first; link; link = link->next) { + int tot = count_particles_mod(psys, totgroup, *cur); + stats_object(link->data, 0, tot, stats); + (*cur)++; + } + + SceneCollection *scene_collection_nested; + for (scene_collection_nested = scene_collection->scene_collections.first; + scene_collection_nested; + scene_collection_nested = scene_collection_nested->next) + { + stats_dupli_object_group_doit(scene_collection_nested, stats, psys, totgroup, cur); + } +} + static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats) { if (base->flag & BASE_SELECTED) stats->totobjsel++; @@ -287,17 +320,11 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats) stats_object(part->dup_ob, 0, tot, stats); } else if (part->draw_as == PART_DRAW_GR && part->dup_group) { - GroupObject *go; - int tot, totgroup = 0, cur = 0; - - for (go = part->dup_group->gobject.first; go; go = go->next) - totgroup++; - - for (go = part->dup_group->gobject.first; go; go = go->next) { - tot = count_particles_mod(psys, totgroup, cur); - stats_object(go->ob, 0, tot, stats); - cur++; - } + int totgroup = 0, cur = 0; + + SceneCollection *scene_collection = part->dup_group->collection; + stats_dupli_object_group_count(scene_collection, &totgroup); + stats_dupli_object_group_doit(scene_collection, stats, psys, totgroup, &cur); } } diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index adf7e1dc5d3..a32a9c5f523 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -36,6 +36,8 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" +#include "DNA_group_types.h" + #include "ED_screen.h" #include "WM_api.h" @@ -110,7 +112,7 @@ static int collection_link_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - SceneCollection *sc_master = BKE_collection_master(scene); + SceneCollection *sc_master = BKE_collection_master(&scene->id); SceneCollection *sc; int scene_collection_index = RNA_enum_get(op->ptr, "scene_collection"); @@ -136,7 +138,9 @@ static int collection_link_exec(bContext *C, wmOperator *op) static int collection_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (BKE_collection_master(CTX_data_scene(C))->scene_collections.first == NULL) { + Scene *scene = CTX_data_scene(C); + SceneCollection *master_collection = BKE_collection_master(&scene->id); + if (master_collection->scene_collections.first == NULL) { RNA_enum_set(op->ptr, "scene_collection", 0); return collection_link_exec(C, op); } @@ -169,7 +173,7 @@ static const EnumPropertyItem *collection_scene_collection_itemf( int value = 0, totitem = 0; Scene *scene = CTX_data_scene(C); - SceneCollection *sc = BKE_collection_master(scene); + SceneCollection *sc = BKE_collection_master(&scene->id); collection_scene_collection_itemf_recursive(&tmp, &item, &totitem, &value, sc); RNA_enum_item_end(&item, &totitem); @@ -257,15 +261,18 @@ void OUTLINER_OT_collection_unlink(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/**********************************************************************************/ +/* Add new collection. */ + static int collection_new_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); + SceneCollection *scene_collection = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL); + BKE_collection_link(view_layer, scene_collection); - SceneCollection *sc = BKE_collection_add(scene, NULL, NULL); - BKE_collection_link(view_layer, sc); - - DEG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(bmain); WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); return OPERATOR_FINISHED; } @@ -275,7 +282,7 @@ void OUTLINER_OT_collection_new(wmOperatorType *ot) /* identifiers */ ot->name = "New Collection"; ot->idname = "OUTLINER_OT_collection_new"; - ot->description = "Add a new collection to the scene, and link it to the active layer"; + ot->description = "Add a new collection to the scene"; /* api callbacks */ ot->exec = collection_new_exec; @@ -284,6 +291,8 @@ void OUTLINER_OT_collection_new(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/**********************************************************************************/ + /** * Returns true is selected element is a collection */ @@ -336,12 +345,12 @@ static TreeTraversalAction collection_delete_cb(TreeElement *te, void *customdat return TRAVERSE_SKIP_CHILDS; } - if (scene_collection == BKE_collection_master(data->scene)) { + if (scene_collection == BKE_collection_master(&data->scene->id)) { /* skip - showing warning/error message might be missleading * when deleting multiple collections, so just do nothing */ } else { - BKE_collection_remove(data->scene, scene_collection); + BKE_collection_remove(&data->scene->id, scene_collection); } return TRAVERSE_CONTINUE; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 8b4ed61f148..4ac5ad6e8d2 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -250,9 +250,16 @@ static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), voi static void enablebutton_collection_flag_cb(bContext *C, void *poin, void *poin2) { Main *bmain = CTX_data_main(C); - Scene *scene = poin; + Scene *scene = CTX_data_scene(C); + ID *id = poin; LayerCollection *layer_collection = poin2; - ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection); + ViewLayer *view_layer = BKE_view_layer_find_from_collection(id, layer_collection); + + /* TODO: This breaks when you see the collections of a group. (dfelinto) */ + if (view_layer == NULL) { + WM_reportf(RPT_INFO, "Enable/disable of group collections disabled for now"); + return; + } /* We need to toggle the flag since this is called after the flag is already set. */ layer_collection->flag ^= COLLECTION_DISABLED; @@ -273,11 +280,16 @@ static void enablebutton_collection_flag_cb(bContext *C, void *poin, void *poin2 static void restrictbutton_collection_flag_cb(bContext *C, void *poin, void *UNUSED(poin2)) { - Scene *scene = poin; + ID *id = (ID *)poin; + /* hide and deselect bases that are directly influenced by this LayerCollection */ /* TODO(sergey): Use proper flag for tagging here. */ - DEG_id_tag_update(&scene->id, 0); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + DEG_id_tag_update(id, 0); + + if (GS(id->name) == ID_SCE) { + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, id); + } + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL); } @@ -595,22 +607,24 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_ENABLEX), te->ys, UI_UNIT_X, UI_UNIT_Y, &collection->flag, 0, 0, 0, 0, TIP_("Enable/Disable collection from depsgraph")); - UI_but_func_set(bt, enablebutton_collection_flag_cb, scene, collection); + UI_but_func_set(bt, enablebutton_collection_flag_cb, tselem->id, collection); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_VISIBLE, 0, ICON_RESTRICT_VIEW_OFF, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y, &collection->flag, 0, 0, 0, 0, TIP_("Restrict/Allow 3D View visibility of objects in the collection")); - UI_but_func_set(bt, restrictbutton_collection_flag_cb, scene, collection); + UI_but_func_set(bt, restrictbutton_collection_flag_cb, tselem->id, collection); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_SELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, - UI_UNIT_Y, &collection->flag, 0, 0, 0, 0, - TIP_("Restrict/Allow 3D View selection of objects in the collection")); - UI_but_func_set(bt, restrictbutton_collection_flag_cb, scene, collection); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + if (collection->scene_collection->type == COLLECTION_TYPE_NONE) { + bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_SELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, + UI_UNIT_Y, &collection->flag, 0, 0, 0, 0, + TIP_("Restrict/Allow 3D View selection of objects in the collection")); + UI_but_func_set(bt, restrictbutton_collection_flag_cb, scene, collection); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } UI_block_emboss_set(block, UI_EMBOSS); } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 4858b6cb120..8cd76179f23 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -274,7 +274,7 @@ static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, Tre BKE_report(reports, RPT_WARNING, "Cannot edit sequence name"); } else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) { - SceneCollection *master = BKE_collection_master(scene); + SceneCollection *master = BKE_collection_master(&scene->id); if ((tselem->type == TSE_SCENE_COLLECTION && te->directdata == master) || (((LayerCollection *)te->directdata)->scene_collection == master)) @@ -1940,7 +1940,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) BLI_assert(scene); RNA_string_get(op->ptr, "child", childname); ob = (Object *)BKE_libblock_find_name(ID_OB, childname); - BKE_collection_object_add(scene, sc, ob); + BKE_collection_object_add(&scene->id, sc, ob); DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); @@ -2166,13 +2166,13 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) SceneCollection *sc; if (scene != CTX_data_scene(C)) { /* when linking to an inactive scene link to the master collection */ - sc = BKE_collection_master(scene); + sc = BKE_collection_master(&scene->id); } else { sc = CTX_data_scene_collection(C); } - BKE_collection_object_add(scene, sc, ob); + BKE_collection_object_add(&scene->id, sc, ob); for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { Base *base = BKE_view_layer_base_find(view_layer, ob); diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 23e1b766891..f69eb9af1bf 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -67,9 +67,8 @@ typedef enum TreeTraversalAction { /** * Callback type for reinserting elements at a different position, used to allow user customizable element order. - * Passing scene right now, may be better to allow some custom data. */ -typedef void (*TreeElementReinsertFunc)(struct Main *bmain, const struct Scene *scene, +typedef void (*TreeElementReinsertFunc)(struct Main *bmain, struct TreeElement *insert_element, struct TreeElement *insert_handle, TreeElementInsertType action); /** @@ -77,7 +76,7 @@ typedef void (*TreeElementReinsertFunc)(struct Main *bmain, const struct Scene * * if reinserting insert_element before/after/into insert_handle would be allowed. * It's allowed to change the reinsert info here for non const pointers. */ -typedef bool (*TreeElementReinsertPollFunc)(const struct Scene *scene, const struct TreeElement *insert_element, +typedef bool (*TreeElementReinsertPollFunc)(const struct TreeElement *insert_element, struct TreeElement **io_insert_handle, TreeElementInsertType *io_action); typedef TreeTraversalAction (*TreeTraversalFunc)(struct TreeElement *te, void *customdata); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index aa6a5dba6a7..856dd022c14 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -58,7 +58,7 @@ static int outliner_item_drag_drop_poll(bContext *C) SpaceOops *soops = CTX_wm_space_outliner(C); return ED_operator_outliner_active(C) && /* Only collection display modes supported for now. Others need more design work */ - ELEM(soops->outlinevis, SO_ACT_LAYER, SO_COLLECTIONS); + ELEM(soops->outlinevis, SO_ACT_LAYER, SO_COLLECTIONS, SO_GROUPS); } static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event) @@ -138,7 +138,7 @@ static void outliner_item_drag_get_insert_data( } static void outliner_item_drag_handle( - const Scene *scene, SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged) + SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged) { TreeElement *te_insert_handle; TreeElementInsertType insert_type; @@ -156,7 +156,7 @@ static void outliner_item_drag_handle( /* nothing will happen anyway, no need to do poll check */ } else if (!te_dragged->reinsert_poll || - !te_dragged->reinsert_poll(scene, te_dragged, &te_insert_handle, &insert_type)) + !te_dragged->reinsert_poll(te_dragged, &te_insert_handle, &insert_type)) { te_insert_handle = NULL; } @@ -164,7 +164,7 @@ static void outliner_item_drag_handle( te_dragged->drag_data->insert_handle = te_insert_handle; } -static bool outliner_item_drag_drop_apply(Main *bmain, const Scene *scene, TreeElement *dragged_te) +static bool outliner_item_drag_drop_apply(Main *bmain, TreeElement *dragged_te) { TreeElement *insert_handle = dragged_te->drag_data->insert_handle; TreeElementInsertType insert_type = dragged_te->drag_data->insert_type; @@ -173,12 +173,12 @@ static bool outliner_item_drag_drop_apply(Main *bmain, const Scene *scene, TreeE /* No need to do anything */ } else if (dragged_te->reinsert) { - BLI_assert(!dragged_te->reinsert_poll || dragged_te->reinsert_poll(scene, dragged_te, &insert_handle, + BLI_assert(!dragged_te->reinsert_poll || dragged_te->reinsert_poll(dragged_te, &insert_handle, &insert_type)); /* call of assert above should not have changed insert_handle and insert_type at this point */ BLI_assert(dragged_te->drag_data->insert_handle == insert_handle && dragged_te->drag_data->insert_type == insert_type); - dragged_te->reinsert(bmain, scene, dragged_te, insert_handle, insert_type); + dragged_te->reinsert(bmain, dragged_te, insert_handle, insert_type); return true; } @@ -188,7 +188,6 @@ static bool outliner_item_drag_drop_apply(Main *bmain, const Scene *scene, TreeE static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEvent *event) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); TreeElement *te_dragged = op->customdata; @@ -199,7 +198,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv switch (event->type) { case EVT_MODAL_MAP: if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) { - if (outliner_item_drag_drop_apply(bmain, scene, te_dragged)) { + if (outliner_item_drag_drop_apply(bmain, te_dragged)) { skip_rebuild = false; } retval = OPERATOR_FINISHED; @@ -215,7 +214,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv redraw = true; break; case MOUSEMOVE: - outliner_item_drag_handle(scene, soops, ar, event, te_dragged); + outliner_item_drag_handle(soops, ar, event, te_dragged); redraw = true; break; } diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 5215efaa05c..70d01007d89 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -44,6 +44,7 @@ #include "BLI_listbase.h" #include "BKE_context.h" +#include "BKE_group.h" #include "BKE_object.h" #include "BKE_layer.h" #include "BKE_scene.h" @@ -784,9 +785,11 @@ static eOLDrawState tree_element_active_collection( LayerCollection *lc = te->directdata; const int collection_index = BKE_layer_collection_findindex(view_layer, lc); - BLI_assert(collection_index >= 0); - view_layer->active_collection = collection_index; - WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + /* If the collection is part of a group we don't change active collection. */ + if (collection_index > -1) { + view_layer->active_collection = collection_index; + WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + } } return OL_DRAWSEL_NONE; @@ -906,26 +909,30 @@ static void do_outliner_item_activate_tree_element( } else if (te->idcode == ID_GR) { Group *gr = (Group *)tselem->id; - GroupObject *gob; if (extend) { int sel = BA_SELECT; - for (gob = gr->gobject.first; gob; gob = gob->next) { - if (gob->ob->flag & SELECT) { + FOREACH_GROUP_BASE(gr, base) + { + if (base->flag & BASE_SELECTED) { sel = BA_DESELECT; break; } } + FOREACH_GROUP_BASE_END - for (gob = gr->gobject.first; gob; gob = gob->next) { - ED_object_base_select(BKE_view_layer_base_find(view_layer, gob->ob), sel); + FOREACH_GROUP_OBJECT(gr, object) + { + ED_object_base_select(BKE_view_layer_base_find(view_layer, object), sel); } + FOREACH_GROUP_OBJECT_END } else { BKE_view_layer_base_deselect_all(view_layer); - for (gob = gr->gobject.first; gob; gob = gob->next) { - Base *base = BKE_view_layer_base_find(view_layer, gob->ob); + FOREACH_GROUP_OBJECT(gr, object) + { + Base *base = BKE_view_layer_base_find(view_layer, object); /* Object may not be in this scene */ if (base != NULL) { if ((base->flag & BASE_SELECTED) == 0) { @@ -933,6 +940,7 @@ static void do_outliner_item_activate_tree_element( } } } + FOREACH_GROUP_OBJECT_END } WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 63e1a527138..203942b3c9b 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -525,20 +525,21 @@ static void group_linkobs2scene_cb( ViewLayer *view_layer = CTX_data_view_layer(C); SceneCollection *sc = CTX_data_scene_collection(C); Group *group = (Group *)tselem->id; - GroupObject *gob; Base *base; - for (gob = group->gobject.first; gob; gob = gob->next) { - base = BKE_view_layer_base_find(view_layer, gob->ob); + FOREACH_GROUP_OBJECT(group, object) + { + base = BKE_view_layer_base_find(view_layer, object); if (!base) { /* link to scene */ - BKE_collection_object_add(scene, sc, gob->ob); - base = BKE_view_layer_base_find(view_layer, gob->ob); - id_us_plus(&gob->ob->id); + BKE_collection_object_add(&scene->id, sc, object); + base = BKE_view_layer_base_find(view_layer, object); + id_us_plus(&object->id); } base->flag |= BASE_SELECTED; } + FOREACH_GROUP_OBJECT_END } static void group_instance_cb( @@ -820,12 +821,13 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel bContext *C = (bContext *)Carg; Scene *scene = CTX_data_scene(C); LayerCollection *lc = te->directdata; + ID *id = te->store_elem->id; SceneCollection *sc = lc->scene_collection; if (event == OL_COLLECTION_OP_OBJECTS_ADD) { CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { - BKE_collection_object_add(scene, sc, ob); + BKE_collection_object_add(id, sc, ob); } CTX_DATA_END; @@ -836,7 +838,7 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { - BKE_collection_object_remove(bmain, scene, sc, ob, true); + BKE_collection_object_remove(bmain, id, sc, ob, true); } CTX_DATA_END; @@ -844,7 +846,13 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel te->store_elem->flag &= ~TSE_SELECTED; } else if (event == OL_COLLECTION_OP_COLLECTION_NEW) { - BKE_collection_add(scene, sc, NULL); + if (GS(id->name) == ID_GR) { + BKE_collection_add(id, sc, COLLECTION_TYPE_GROUP_INTERNAL, NULL); + } + else { + BLI_assert(GS(id->name) == ID_SCE); + BKE_collection_add(id, sc, COLLECTION_TYPE_NONE, NULL); + } WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); } else if (event == OL_COLLECTION_OP_COLLECTION_UNLINK) { @@ -861,7 +869,7 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel } } else if (event == OL_COLLECTION_OP_COLLECTION_DEL) { - if (BKE_collection_remove(scene, sc)) { + if (BKE_collection_remove(id, sc)) { DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); } @@ -1794,15 +1802,38 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot) /* ******************** */ -static EnumPropertyItem prop_collection_op_types[] = { - {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"}, - {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"}, - {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"}, - {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"}, - {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"}, - {0, NULL, 0, NULL, NULL} +static EnumPropertyItem prop_collection_op_none_types[] = { + {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"}, + {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"}, + {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"}, + {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"}, + {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"}, + {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem prop_collection_op_group_internal_types[] = { + {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"}, + {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"}, + {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"}, + {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"}, + {0, NULL, 0, NULL, NULL} +}; + +static const EnumPropertyItem *outliner_collection_operation_type_itemf( + bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +{ + *r_free = false; + SpaceOops *soops = CTX_wm_space_outliner(C); + + switch (soops->outlinevis) { + case SO_GROUPS: + return prop_collection_op_group_internal_types; + case SO_ACT_LAYER: + return prop_collection_op_none_types; + } + return NULL; +} + static int outliner_collection_operation_exec(bContext *C, wmOperator *op) { SpaceOops *soops = CTX_wm_space_outliner(C); @@ -1823,6 +1854,8 @@ static int outliner_collection_operation_exec(bContext *C, wmOperator *op) void OUTLINER_OT_collection_operation(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Outliner Collection Operation"; ot->idname = "OUTLINER_OT_collection_operation"; @@ -1835,7 +1868,10 @@ void OUTLINER_OT_collection_operation(wmOperatorType *ot) ot->flag = 0; - ot->prop = RNA_def_enum(ot->srna, "type", prop_collection_op_types, 0, "Collection Operation", ""); + prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Collection Operation", ""); + RNA_def_enum_funcs(prop, outliner_collection_operation_type_itemf); + RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); + ot->prop = prop; } /* ******************** */ diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 1ab715d0246..a9c9ab74970 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -88,6 +88,8 @@ #endif /* prototypes */ +static void outliner_add_layer_collections_recursive( + SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten); static void outliner_make_hierarchy(ListBase *lb); /* ********************************************************* */ @@ -386,13 +388,14 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s } static void outliner_object_reorder( - Main *UNUSED(bmain), const Scene *scene, + Main *UNUSED(bmain), TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action) { TreeStoreElem *tselem_insert = TREESTORE(insert_element); Object *ob = (Object *)tselem_insert->id; SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle); SceneCollection *sc_ob_parent = NULL; + ID *id = insert_handle->store_elem->id; BLI_assert(action == TE_INSERT_INTO); UNUSED_VARS_NDEBUG(action); @@ -407,13 +410,13 @@ static void outliner_object_reorder( } } else { - sc_ob_parent = BKE_collection_master(scene); + sc_ob_parent = BKE_collection_master(id); } - BKE_collection_object_move(scene, sc, sc_ob_parent, ob); + BKE_collection_object_move(id, sc, sc_ob_parent, ob); } static bool outliner_object_reorder_poll( - const Scene *UNUSED(scene), const TreeElement *insert_element, + const TreeElement *insert_element, TreeElement **io_insert_handle, TreeElementInsertType *io_action) { TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle); @@ -861,7 +864,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i } /* exceptions */ - if (ELEM(type, TSE_ID_BASE, TSE_LAYER_COLLECTION)) { + if (type == TSE_ID_BASE) { /* pass */ } else if (id == NULL) { @@ -1199,6 +1202,11 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i te->flag |= TE_LAZY_CLOSED; } + if ((type != TSE_LAYER_COLLECTION) && GS(id->name) == ID_GR) { + Group *group = (Group *)id; + outliner_add_layer_collections_recursive(soops, &te->subtree, id, &group->view_layer->layer_collections, NULL); + } + return te; } @@ -1349,20 +1357,21 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops) } static void outliner_layer_collections_reorder( - Main *bmain, const Scene *scene, + Main *bmain, TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action) { LayerCollection *lc_insert = insert_element->directdata; LayerCollection *lc_handle = insert_handle->directdata; + ID *id = insert_element->store_elem->id; if (action == TE_INSERT_BEFORE) { - BKE_layer_collection_move_above(scene, lc_handle, lc_insert); + BKE_layer_collection_move_above(id, lc_handle, lc_insert); } else if (action == TE_INSERT_AFTER) { - BKE_layer_collection_move_below(scene, lc_handle, lc_insert); + BKE_layer_collection_move_below(id, lc_handle, lc_insert); } else if (action == TE_INSERT_INTO) { - BKE_layer_collection_move_into(scene, lc_handle, lc_insert); + BKE_layer_collection_move_into(id, lc_handle, lc_insert); } else { BLI_assert(0); @@ -1371,25 +1380,30 @@ static void outliner_layer_collections_reorder( DEG_relations_tag_update(bmain); } static bool outliner_layer_collections_reorder_poll( - const Scene *UNUSED(scene), const TreeElement *UNUSED(insert_element), + const TreeElement *insert_element, TreeElement **io_insert_handle, TreeElementInsertType *UNUSED(io_action)) { const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle); + + if (tselem_handle->id != insert_element->store_elem->id) { + return false; + } + return ELEM(tselem_handle->type, TSE_LAYER_COLLECTION); } static void outliner_add_layer_collections_recursive( - SpaceOops *soops, ListBase *tree, ListBase *layer_collections, TreeElement *parent_ten) + SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten) { for (LayerCollection *collection = layer_collections->first; collection; collection = collection->next) { - TreeElement *ten = outliner_add_element(soops, tree, collection, parent_ten, TSE_LAYER_COLLECTION, 0); + TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0); ten->name = collection->scene_collection->name; ten->directdata = collection; ten->reinsert = outliner_layer_collections_reorder; ten->reinsert_poll = outliner_layer_collections_reorder_poll; - outliner_add_layer_collections_recursive(soops, &ten->subtree, &collection->layer_collections, ten); + outliner_add_layer_collections_recursive(soops, &ten->subtree, id, &collection->layer_collections, ten); for (LinkData *link = collection->object_bases.first; link; link = link->next) { Base *base = (Base *)link->data; TreeElement *te_object = outliner_add_element(soops, &ten->subtree, base->object, ten, 0, 0); @@ -1398,27 +1412,29 @@ static void outliner_add_layer_collections_recursive( outliner_make_hierarchy(&ten->subtree); } } -static void outliner_add_collections_act_layer(SpaceOops *soops, ViewLayer *layer) +static void outliner_add_collections_act_layer(SpaceOops *soops, Scene *scene, ViewLayer *layer) { - outliner_add_layer_collections_recursive(soops, &soops->tree, &layer->layer_collections, NULL); + outliner_add_layer_collections_recursive(soops, &soops->tree, &scene->id, &layer->layer_collections, NULL); } static void outliner_scene_collections_reorder( - Main *bmain, const Scene *scene, + Main *bmain, TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action) { SceneCollection *sc_insert = insert_element->directdata; SceneCollection *sc_handle = insert_handle->directdata; + ID *id = insert_handle->store_elem->id; + BLI_assert(id == insert_element->store_elem->id); - BLI_assert((action == TE_INSERT_INTO) || (sc_handle != BKE_collection_master(scene))); + BLI_assert((action == TE_INSERT_INTO) || (sc_handle != BKE_collection_master(id))); if (action == TE_INSERT_BEFORE) { - BKE_collection_move_above(scene, sc_handle, sc_insert); + BKE_collection_move_above(id, sc_handle, sc_insert); } else if (action == TE_INSERT_AFTER) { - BKE_collection_move_below(scene, sc_handle, sc_insert); + BKE_collection_move_below(id, sc_handle, sc_insert); } else if (action == TE_INSERT_INTO) { - BKE_collection_move_into(scene, sc_handle, sc_insert); + BKE_collection_move_into(id, sc_handle, sc_insert); } else { BLI_assert(0); @@ -1427,17 +1443,23 @@ static void outliner_scene_collections_reorder( DEG_relations_tag_update(bmain); } static bool outliner_scene_collections_reorder_poll( - const Scene *scene, const TreeElement *UNUSED(insert_element), + const TreeElement *insert_element, TreeElement **io_insert_handle, TreeElementInsertType *io_action) { const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle); - SceneCollection *sc_master = BKE_collection_master(scene); - SceneCollection *sc_handle = (*io_insert_handle)->directdata; + ID *id = tselem_handle->id; + + if (id != insert_element->store_elem->id) { + return false; + } if (!ELEM(tselem_handle->type, TSE_SCENE_COLLECTION)) { return false; } + SceneCollection *sc_master = BKE_collection_master(id); + SceneCollection *sc_handle = (*io_insert_handle)->directdata; + if (sc_handle == sc_master) { /* exception: Can't insert before/after master selection, has to be one of its childs */ TreeElement *te_master = *io_insert_handle; @@ -1478,7 +1500,7 @@ static void outliner_add_scene_collections_recursive( } static void outliner_add_collections_master(SpaceOops *soops, Scene *scene) { - SceneCollection *master = BKE_collection_master(scene); + SceneCollection *master = BKE_collection_master(&scene->id); outliner_add_scene_collections_recursive(soops, &soops->tree, &master->scene_collections, NULL); outliner_add_scene_collection_objects(soops, &soops->tree, master, NULL); } @@ -1851,19 +1873,9 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa } else if (soops->outlinevis == SO_GROUPS) { Group *group; - GroupObject *go; - for (group = mainvar->group.first; group; group = group->id.next) { - if (group->gobject.first) { - te = outliner_add_element(soops, &soops->tree, group, NULL, 0, 0); - - for (go = group->gobject.first; go; go = go->next) { - outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0); - } - outliner_make_hierarchy(&te->subtree); - /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */ - for (go = group->gobject.first; go; go = go->next) go->ob->id.newid = NULL; - } + te = outliner_add_element(soops, &soops->tree, group, NULL, 0, 0); + outliner_make_hierarchy(&te->subtree); } } else if (soops->outlinevis == SO_SAME_TYPE) { @@ -1940,7 +1952,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa outliner_add_orphaned_datablocks(mainvar, soops); } else if (soops->outlinevis == SO_ACT_LAYER) { - outliner_add_collections_act_layer(soops, view_layer); + outliner_add_collections_act_layer(soops, scene, view_layer); } else if (soops->outlinevis == SO_COLLECTIONS) { outliner_add_collections_master(soops, scene); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 568343f8ec8..79fa9e14dc1 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -46,6 +46,7 @@ #include "BKE_appdir.h" #include "BKE_blender_copybuffer.h" #include "BKE_context.h" +#include "BKE_group.h" #include "BKE_main.h" #include "BKE_report.h" @@ -81,14 +82,16 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op) CTX_DATA_END; for (Group *group = bmain->group.first; group; group = group->id.next) { - for (GroupObject *go = group->gobject.first; go; go = go->next) { - if (go->ob && (go->ob->id.tag & LIB_TAG_DOIT)) { + FOREACH_GROUP_OBJECT(group, object) + { + if (object && (object->id.tag & LIB_TAG_DOIT)) { BKE_copybuffer_tag_ID(&group->id); /* don't expand out to all other objects */ group->id.tag &= ~LIB_TAG_NEED_EXPAND; break; } } + FOREACH_GROUP_OBJECT_END } BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend"); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 6122ef99964..79f17756ca6 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -945,8 +945,8 @@ Object *BlenderStrokeRenderer::NewMesh() const ob->data = BKE_mesh_add(freestyle_bmain, name); ob->lay = 1; - SceneCollection *sc_master = BKE_collection_master(freestyle_scene); - BKE_collection_object_add(freestyle_scene, sc_master, ob); + SceneCollection *sc_master = BKE_collection_master(&freestyle_scene->id); + BKE_collection_object_add(&freestyle_scene->id, sc_master, ob); DEG_graph_tag_relations_update(freestyle_depsgraph); DEG_graph_id_tag_update(freestyle_bmain, diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h index 45dd0cb9ff2..8f15aa85e97 100644 --- a/source/blender/makesdna/DNA_group_types.h +++ b/source/blender/makesdna/DNA_group_types.h @@ -60,6 +60,13 @@ typedef struct Group { * on the last used scene */ unsigned int layer; float dupli_ofs[3]; + + struct SceneCollection *collection; + struct ViewLayer *view_layer; } Group; + +#define GROUP_MASTER_COLLECTION(_group) \ + (((LayerCollection *)(_group)->view_layer->layer_collections.first)->scene_collection) + #endif /* __DNA_GROUP_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 3eac7f0aab3..c677383cb6e 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -104,7 +104,8 @@ typedef struct SceneCollection { char name[64]; /* MAX_NAME */ char filter[64]; /* MAX_NAME */ int active_object_index; /* for UI */ - int pad; + char type; + char pad[3]; ListBase objects; /* (Object *)LinkData->data */ ListBase filter_objects; /* (Object *)LinkData->data */ ListBase scene_collections; /* nested collections */ @@ -134,6 +135,11 @@ enum { VIEW_LAYER_FREESTYLE = (1 << 2), }; +/* SceneCollection->type */ +enum { + COLLECTION_TYPE_NONE = 0, + COLLECTION_TYPE_GROUP_INTERNAL = 1, +}; /* *************************************************************** */ /* Engine Settings */ diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index a706ea50ebd..78c623f6408 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -371,6 +371,7 @@ typedef struct DupliObject { struct ParticleSystem *particle_system; unsigned int random_id; unsigned int pad; + struct IDProperty *collection_properties; } DupliObject; /* **************** OBJECT ********************* */ diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index 155c82bbbc3..345c47ae1bf 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -61,6 +61,8 @@ extern const EnumPropertyItem rna_enum_object_modifier_type_items[]; extern const EnumPropertyItem rna_enum_constraint_type_items[]; extern const EnumPropertyItem rna_enum_boidrule_type_items[]; extern const EnumPropertyItem rna_enum_sequence_modifier_type_items[]; + +extern const EnumPropertyItem rna_enum_collection_type_items[]; extern const EnumPropertyItem rna_enum_layer_collection_mode_settings_type_items[]; extern const EnumPropertyItem rna_enum_modifier_triangulate_quad_method_items[]; diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c index 2a5a0011279..ec67370b14f 100644 --- a/source/blender/makesrna/intern/rna_group.c +++ b/source/blender/makesrna/intern/rna_group.c @@ -49,8 +49,9 @@ static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter) { ListBaseIterator *internal = &iter->internal.listbase; - /* we are actually iterating a GroupObject list, so override get */ - return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((GroupObject *)internal->link)->ob); + /* we are actually iterating a ObjectBase list, so override get */ + Base *base = (Base *)internal->link; + return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object); } static void rna_Group_objects_link(Group *group, ReportList *reports, Object *object) @@ -124,20 +125,17 @@ void RNA_def_group(BlenderRNA *brna) RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - prop = RNA_def_property(srna, "layers", PROP_BOOLEAN, PROP_LAYER); - RNA_def_property_boolean_sdna(prop, NULL, "layer", 1); - RNA_def_property_array(prop, 20); - RNA_def_property_ui_text(prop, "Dupli Layers", "Layers visible when this group is instanced as a dupli"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "gobject", NULL); + RNA_def_property_collection_sdna(prop, NULL, "view_layer->object_bases", NULL); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_ui_text(prop, "Objects", "A collection of this groups objects"); RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_Group_objects_get", NULL, NULL, NULL, NULL); - rna_def_group_objects(brna, prop); + prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "view_layer->layer_collections", NULL); + RNA_def_property_struct_type(prop, "LayerCollection"); + RNA_def_property_ui_text(prop, "Layer Collections", ""); } #endif diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index 2bdb3035073..df6c2188799 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -54,8 +54,15 @@ const EnumPropertyItem rna_enum_layer_collection_mode_settings_type_items[] = { {0, NULL, 0, NULL, NULL} }; +const EnumPropertyItem rna_enum_collection_type_items[] = { + {COLLECTION_TYPE_NONE, "NONE", 0, "Normal", ""}, + {COLLECTION_TYPE_GROUP_INTERNAL, "GROUP_INTERNAL", 0, "Group Internal", ""}, + {0, NULL, 0, NULL, NULL} +}; + #ifdef RNA_RUNTIME +#include "DNA_group_types.h" #include "DNA_object_types.h" #include "RNA_access.h" @@ -69,6 +76,20 @@ const EnumPropertyItem rna_enum_layer_collection_mode_settings_type_items[] = { #include "DEG_depsgraph_build.h" #include "DEG_depsgraph_query.h" +static StructRNA *rna_SceneCollection_refine(PointerRNA *ptr) +{ + SceneCollection *scene_collection = (SceneCollection *)ptr->data; + switch (scene_collection->type) { + case COLLECTION_TYPE_GROUP_INTERNAL: + case COLLECTION_TYPE_NONE: + return &RNA_SceneCollection; + default: + BLI_assert(!"Collection type not fully implemented"); + break; + } + return &RNA_SceneCollection; +} + static void rna_SceneCollection_name_set(PointerRNA *ptr, const char *value) { Scene *scene = (Scene *)ptr->id.data; @@ -96,9 +117,7 @@ static PointerRNA rna_SceneCollection_objects_get(CollectionPropertyIterator *it static int rna_SceneCollection_move_above(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst) { - Scene *scene = (Scene *)id; - - if (!BKE_collection_move_above(scene, sc_dst, sc_src)) { + if (!BKE_collection_move_above(id, sc_dst, sc_src)) { return 0; } @@ -110,9 +129,7 @@ static int rna_SceneCollection_move_above(ID *id, SceneCollection *sc_src, Main static int rna_SceneCollection_move_below(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst) { - Scene *scene = (Scene *)id; - - if (!BKE_collection_move_below(scene, sc_dst, sc_src)) { + if (!BKE_collection_move_below(id, sc_dst, sc_src)) { return 0; } @@ -124,9 +141,7 @@ static int rna_SceneCollection_move_below(ID *id, SceneCollection *sc_src, Main static int rna_SceneCollection_move_into(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst) { - Scene *scene = (Scene *)id; - - if (!BKE_collection_move_into(scene, sc_dst, sc_src)) { + if (!BKE_collection_move_into(id, sc_dst, sc_src)) { return 0; } @@ -139,8 +154,7 @@ static int rna_SceneCollection_move_into(ID *id, SceneCollection *sc_src, Main * static SceneCollection *rna_SceneCollection_new( ID *id, SceneCollection *sc_parent, Main *bmain, const char *name) { - Scene *scene = (Scene *)id; - SceneCollection *sc = BKE_collection_add(scene, sc_parent, name); + SceneCollection *sc = BKE_collection_add(id, sc_parent, COLLECTION_TYPE_NONE, name); DEG_relations_tag_update(bmain); WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); @@ -151,7 +165,6 @@ static SceneCollection *rna_SceneCollection_new( static void rna_SceneCollection_remove( ID *id, SceneCollection *sc_parent, Main *bmain, ReportList *reports, PointerRNA *sc_ptr) { - Scene *scene = (Scene *)id; SceneCollection *sc = sc_ptr->data; const int index = BLI_findindex(&sc_parent->scene_collections, sc); @@ -161,7 +174,7 @@ static void rna_SceneCollection_remove( return; } - if (!BKE_collection_remove(scene, sc)) { + if (!BKE_collection_remove(id, sc)) { BKE_reportf(reports, RPT_ERROR, "Collection '%s' could not be removed from collection '%s'", sc->name, sc_parent->name); return; @@ -203,7 +216,7 @@ void rna_SceneCollection_object_link( return; } - BKE_collection_object_add(scene, sc, ob); + BKE_collection_object_add(&scene->id, sc, ob); /* TODO(sergey): Only update relations for the current scene. */ DEG_relations_tag_update(bmain); @@ -226,7 +239,7 @@ static void rna_SceneCollection_object_unlink( return; } - BKE_collection_object_remove(bmain, scene, sc, ob, false); + BKE_collection_object_remove(bmain, &scene->id, sc, ob, false); /* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */ DEG_relations_tag_update(bmain); @@ -417,11 +430,11 @@ static void rna_ViewLayerEngineSettings_update(bContext *C, PointerRNA *UNUSED(p DEG_id_tag_update(&scene->id, 0); } -static void rna_LayerCollectionEngineSettings_update(bContext *C, PointerRNA *UNUSED(ptr)) +static void rna_LayerCollectionEngineSettings_update(bContext *UNUSED(C), PointerRNA *ptr) { - Scene *scene = CTX_data_scene(C); + ID *id = ptr->id.data; /* TODO(sergey): Use proper flag for tagging here. */ - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(id, 0); } static void rna_LayerCollectionEngineSettings_wire_update(bContext *C, PointerRNA *UNUSED(ptr)) @@ -641,9 +654,7 @@ static PointerRNA rna_LayerCollection_objects_get(CollectionPropertyIterator *it static int rna_LayerCollection_move_above(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst) { - Scene *scene = (Scene *)id; - - if (!BKE_layer_collection_move_above(scene, lc_dst, lc_src)) { + if (!BKE_layer_collection_move_above(id, lc_dst, lc_src)) { return 0; } @@ -655,9 +666,7 @@ static int rna_LayerCollection_move_above(ID *id, LayerCollection *lc_src, Main static int rna_LayerCollection_move_below(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst) { - Scene *scene = (Scene *)id; - - if (!BKE_layer_collection_move_below(scene, lc_dst, lc_src)) { + if (!BKE_layer_collection_move_below(id, lc_dst, lc_src)) { return 0; } @@ -669,9 +678,7 @@ static int rna_LayerCollection_move_below(ID *id, LayerCollection *lc_src, Main static int rna_LayerCollection_move_into(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst) { - Scene *scene = (Scene *)id; - - if (!BKE_layer_collection_move_into(scene, lc_dst, lc_src)) { + if (!BKE_layer_collection_move_into(id, lc_dst, lc_src)) { return 0; } @@ -681,19 +688,27 @@ static int rna_LayerCollection_move_into(ID *id, LayerCollection *lc_src, Main * return 1; } -static void rna_LayerCollection_flag_update(bContext *C, PointerRNA *UNUSED(ptr)) +static void rna_LayerCollection_flag_update(bContext *C, PointerRNA *ptr) { - Scene *scene = CTX_data_scene(C); + ID *id = ptr->id.data; /* TODO(sergey): Use proper flag for tagging here. */ - DEG_id_tag_update(&scene->id, 0); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + DEG_id_tag_update(id, 0); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); } static void rna_LayerCollection_enable_set( ID *id, LayerCollection *layer_collection, Main *bmain, bContext *C, ReportList *reports, int value) { - Scene *scene = (Scene *)id; - ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection); + ViewLayer *view_layer; + if (GS(id->name) == ID_SCE) { + Scene *scene = (Scene *)id; + view_layer = BKE_view_layer_find_from_collection(&scene->id, layer_collection); + } + else { + BLI_assert(GS(id->name) == ID_GR); + Group *group = (Group *)id; + view_layer = group->view_layer; + } if (layer_collection->flag & COLLECTION_DISABLED) { if (value == 1) { @@ -715,6 +730,7 @@ static void rna_LayerCollection_enable_set( } } + Scene *scene = CTX_data_scene(C); DEG_relations_tag_update(bmain); /* TODO(sergey): Use proper flag for tagging here. */ DEG_id_tag_update(&scene->id, 0); @@ -1034,6 +1050,7 @@ static void rna_def_scene_collection(BlenderRNA *brna) srna = RNA_def_struct(brna, "SceneCollection", NULL); RNA_def_struct_ui_text(srna, "Scene Collection", "Collection"); + RNA_def_struct_refine_func(srna, "rna_SceneCollection_refine"); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneCollection_name_set"); @@ -1041,6 +1058,11 @@ static void rna_def_scene_collection(BlenderRNA *brna) RNA_def_struct_name_property(srna, prop); RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL); + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_collection_type_items); + RNA_def_property_ui_text(prop, "Type", "Type of collection"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "filter", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneCollection_filter_set"); RNA_def_property_ui_text(prop, "Filter", "Filter to dynamically include objects based on their names (e.g., CHAR_*)"); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 81ed4c71b17..74de3fcded6 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -68,6 +68,7 @@ #include "BKE_displist.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_key.h" #include "BKE_image.h" #include "BKE_lattice.h" @@ -3979,28 +3980,32 @@ static bool is_object_hidden(Render *re, Object *ob) /* layflag: allows material group to ignore layerflag */ static void add_lightgroup(Render *re, Group *group, int exclusive) { - GroupObject *go, *gol; - group->id.tag &= ~LIB_TAG_DOIT; +#if 0 /* it's a bit too many loops in loops... but will survive */ /* note that 'exclusive' will remove it from the global list */ - for (go= group->gobject.first; go; go= go->next) { - go->lampren= NULL; + FOREACH_GROUP_BASE(group, base) + { + Object *object = base->object; - if (is_object_hidden(re, go->ob)) + if (is_object_hidden(re, object)) { continue; - - if (go->ob->lay & re->lay) { - if (go->ob && go->ob->type==OB_LAMP) { - for (gol= re->lights.first; gol; gol= gol->next) { - if (gol->ob==go->ob) { - go->lampren= gol->lampren; + } + + if (base->flag & BASE_VISIBLED) { + if (object && object->type == OB_LAMP) { + for (GroupObject *gol = re->lights.first; gol; gol = gol->next) { + if (gol->ob == object) { + go->lampren = gol->lampren; break; } } - if (go->lampren==NULL) - gol= add_render_lamp(re, go->ob); + + if (go->lampren == NULL) { + gol= add_render_lamp(re, object); + } + if (gol && exclusive) { BLI_remlink(&re->lights, gol); MEM_freeN(gol); @@ -4008,6 +4013,10 @@ static void add_lightgroup(Render *re, Group *group, int exclusive) } } } + FOREACH_GROUP_BASE_END +#else + UNUSED_VARS(re, exclusive); +#endif } static void set_material_lightgroups(Render *re) @@ -4899,8 +4908,6 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in { /* ugly function, but we need to set particle systems to their render * settings before calling object_duplilist, to get render level duplis */ - Group *group; - GroupObject *go; ParticleSystem *psys; DerivedMesh *dm; @@ -4932,11 +4939,13 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in } } - if (ob->dup_group==NULL) return; - group= ob->dup_group; + if (ob->dup_group == NULL) return; - for (go= group->gobject.first; go; go= go->next) - dupli_render_particle_set(re, go->ob, timeoffset, level+1, enable); + FOREACH_GROUP_OBJECT(ob->dup_group, object) + { + dupli_render_particle_set(re, object, timeoffset, level+1, enable); + } + FOREACH_GROUP_OBJECT_END } static int get_vector_viewlayers(Scene *UNUSED(sce)) @@ -4946,29 +4955,27 @@ static int get_vector_viewlayers(Scene *UNUSED(sce)) static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, int onlyselected, Object *actob, int timeoffset, int level) { - GroupObject *go; - Object *ob; - - /* simple preventing of too deep nested groups */ - if (level>MAX_DUPLI_RECUR) return; - - /* recursively go into dupligroups to find objects with OB_RENDER_DUPLI - * that were not created yet */ - for (go= group->gobject.first; go; go= go->next) { - ob= go->ob; + /* Simple preventing of too deep nested groups. */ + if (level > MAX_DUPLI_RECUR) return; + /* Recursively go into dupligroups to find objects with OB_RENDER_DUPLI + * that were not created yet. */ + FOREACH_GROUP_OBJECT(group, ob) + { if (ob->flag & OB_DONE) { if (ob->transflag & OB_RENDER_DUPLI) { if (allow_render_object(re, ob, nolamps, onlyselected, actob)) { init_render_object(re, ob, NULL, NULL, NULL, timeoffset); ob->transflag &= ~OB_RENDER_DUPLI; - if (ob->dup_group) + if (ob->dup_group) { add_group_render_dupli_obs(re, ob->dup_group, nolamps, onlyselected, actob, timeoffset, level+1); + } } } } } + FOREACH_GROUP_OBJECT_END } static void database_init_objects(Render *re, unsigned int UNUSED(renderlay), int nolamps, int onlyselected, Object *actob, int timeoffset) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index ad9855586ee..acd425e788a 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -147,6 +147,7 @@ extern "C" { #include "BKE_customdata.h" #include "BKE_cdderivedmesh.h" #include "BKE_DerivedMesh.h" +#include "BKE_group.h" #include "BKE_layer.h" #include "BKE_material.h" /* give_current_material */ #include "BKE_image.h" @@ -2052,10 +2053,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, for (git=tempglist.begin(); git!=tempglist.end(); git++) { Group* group = *git; - GroupObject* go; - for (go=(GroupObject*)group->gobject.first; go; go=(GroupObject*)go->next) + FOREACH_GROUP_OBJECT(group, blenderobject) { - Object* blenderobject = go->ob; if (converter->FindGameObject(blenderobject) == NULL) { allblobj.insert(blenderobject); @@ -2090,6 +2089,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } } } + FOREACH_GROUP_OBJECT_END } } } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index b3061087344..48b50d24975 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -105,6 +105,7 @@ #include "KX_Light.h" +#include "BKE_group.h" #include "BLI_task.h" static void *KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene) @@ -720,7 +721,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) KX_GameObject* gameobj; Object* blgroupobj = groupobj->GetBlenderObject(); Group* group; - GroupObject *go; vector<KX_GameObject*> duplilist; if (!groupobj->GetSGNode() || @@ -738,9 +738,9 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) m_groupGameObjects.clear(); group = blgroupobj->dup_group; - for (go=(GroupObject*)group->gobject.first; go; go=(GroupObject*)go->next) + FOREACH_GROUP_BASE(group, base) { - Object* blenderobj = go->ob; + Object *blenderobj = base->object; if (blgroupobj == blenderobj) // this check is also in group_duplilist() continue; @@ -755,13 +755,13 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) gameobj->SetBlenderGroupObject(blgroupobj); - if ((blenderobj->lay & group->layer)==0) - { + if ((base->flag & BASE_VISIBLED) == 0) { // object is not visible in the 3D view, will not be instantiated continue; } m_groupGameObjects.insert(gameobj); } + FOREACH_GROUP_BASE_END set<CValue*>::iterator oit; for (oit=m_groupGameObjects.begin(); oit != m_groupGameObjects.end(); oit++) |