Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2018-04-30 16:57:22 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2018-05-18 14:34:24 +0300
commit17bd5c9d4b1e9377b896c13043e24eaa7e979714 (patch)
tree60ca4e4118c01d88ccc04919d4f7ed46014875c1 /source/blender
parent70aec3732d0f03138d6477fd04c81dfd9fd21256 (diff)
Collections and groups unification
OVERVIEW * In 2.7 terminology, all layers and groups are now collection datablocks. * These collections are nestable, linkable, instanceable, overrideable, .. which opens up new ways to set up scenes and link + override data. * Viewport/render visibility and selectability are now a part of the collection and shared across all view layers and linkable. * View layers define which subset of the scene collection hierarchy is excluded for each. For many workflows one view layer can be used, these are more of an advanced feature now. OUTLINER * The outliner now has a "View Layer" display mode instead of "Collections", which can display the collections and/or objects in the view layer. * In this display mode, collections can be excluded with the right click menu. These will then be greyed out and their objects will be excluded. * To view collections not linked to any scene, the "Blender File" display mode can be used, with the new filtering option to just see Colleciton datablocks. * The outliner right click menus for collections and objects were reorganized. * Drag and drop still needs to be improved. Like before, dragging the icon or text gives different results, we'll unify this later. LINKING AND OVERRIDES * Collections can now be linked into the scene without creating an instance, with the link/append operator or from the collections view in the outliner. * Collections can get static overrides with the right click menu in the outliner, but this is rather unreliable and not clearly communicated at the moment. * We still need to improve the make override operator to turn collection instances into collections with overrides directly in the scene. PERFORMANCE * We tried to make performance not worse than before and improve it in some cases. The main thing that's still a bit slower is multiple scenes, we have to change the layer syncing to only updated affected scenes. * Collections keep a list of their parent collections for faster incremental updates in syncing and caching. * View layer bases are now in a object -> base hash to avoid quadratic time lookups internally and in API functions like visible_get(). VERSIONING * Compatibility with 2.7 files should be improved due to the new visibility controls. Of course users may not want to set up their scenes differently now to avoid having separate layers and groups. * Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero files. There's a few things which are know to be not quite compatible, like nested layer collections inside groups. * The versioning code for 2.8 files is quite complicated, and isolated behind #ifdef so it can be removed at the end of the release cycle. KNOWN ISSUES * The G-key group operators in the 3D viewport were left mostly as is, they need to be modified still to fit better. * Same for the groups panel in the object properties. This needs to be updated still, or perhaps replaced by something better. * Collections must all have a unique name. Less restrictive namespacing is to be done later, we'll have to see how important this is as all objects within the collections must also have a unique name anyway. * Full scene copy and delete scene are exactly doing the right thing yet. Differential Revision: https://developer.blender.org/D3383 https://code.blender.org/2018/05/collections-and-groups/
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc4
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc8
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_collection.h140
-rw-r--r--source/blender/blenkernel/BKE_collision.h8
-rw-r--r--source/blender/blenkernel/BKE_context.h4
-rw-r--r--source/blender/blenkernel/BKE_effect.h4
-rw-r--r--source/blender/blenkernel/BKE_freestyle.h2
-rw-r--r--source/blender/blenkernel/BKE_group.h85
-rw-r--r--source/blender/blenkernel/BKE_layer.h54
-rw-r--r--source/blender/blenkernel/BKE_main.h2
-rw-r--r--source/blender/blenkernel/BKE_object.h4
-rw-r--r--source/blender/blenkernel/BKE_scene.h4
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/blender_copybuffer.c4
-rw-r--r--source/blender/blenkernel/intern/collection.c1275
-rw-r--r--source/blender/blenkernel/intern/collision.c38
-rw-r--r--source/blender/blenkernel/intern/context.c15
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c18
-rw-r--r--source/blender/blenkernel/intern/effect.c23
-rw-r--r--source/blender/blenkernel/intern/freestyle.c2
-rw-r--r--source/blender/blenkernel/intern/group.c389
-rw-r--r--source/blender/blenkernel/intern/icons.c2
-rw-r--r--source/blender/blenkernel/intern/idcode.c2
-rw-r--r--source/blender/blenkernel/intern/layer.c1272
-rw-r--r--source/blender/blenkernel/intern/library.c14
-rw-r--r--source/blender/blenkernel/intern/library_query.c39
-rw-r--r--source/blender/blenkernel/intern/library_remap.c95
-rw-r--r--source/blender/blenkernel/intern/object.c57
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c127
-rw-r--r--source/blender/blenkernel/intern/particle.c18
-rw-r--r--source/blender/blenkernel/intern/pointcache.c5
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c40
-rw-r--r--source/blender/blenkernel/intern/scene.c59
-rw-r--r--source/blender/blenkernel/intern/softbody.c36
-rw-r--r--source/blender/blenloader/BLO_readfile.h5
-rw-r--r--source/blender/blenloader/intern/readfile.c603
-rw-r--r--source/blender/blenloader/intern/versioning_260.c1
-rw-r--r--source/blender/blenloader/intern/versioning_280.c824
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c10
-rw-r--r--source/blender/blenloader/intern/writefile.c65
-rw-r--r--source/blender/blentranslation/BLT_translation.h4
-rw-r--r--source/blender/collada/DocumentImporter.cpp4
-rw-r--r--source/blender/collada/SceneExporter.cpp12
-rw-r--r--source/blender/collada/collada_utils.cpp4
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h4
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc41
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h5
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc11
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc34
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h7
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc11
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc10
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc4
-rw-r--r--source/blender/depsgraph/intern/depsgraph_intern.h2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c18
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h2
-rw-r--r--source/blender/editors/animation/anim_filter.c10
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c5
-rw-r--r--source/blender/editors/object/object_add.c83
-rw-r--r--source/blender/editors/object/object_edit.c107
-rw-r--r--source/blender/editors/object/object_group.c272
-rw-r--r--source/blender/editors/object/object_intern.h24
-rw-r--r--source/blender/editors/object/object_ops.c34
-rw-r--r--source/blender/editors/object/object_relations.c200
-rw-r--r--source/blender/editors/object/object_select.c166
-rw-r--r--source/blender/editors/object/object_transform.c4
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c8
-rw-r--r--source/blender/editors/physics/rigidbody_object.c8
-rw-r--r--source/blender/editors/render/render_preview.c29
-rw-r--r--source/blender/editors/space_action/space_action.c2
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c41
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c2
-rw-r--r--source/blender/editors/space_graph/space_graph.c2
-rw-r--r--source/blender/editors/space_info/info_stats.c37
-rw-r--r--source/blender/editors/space_nla/space_nla.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c1056
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c123
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c148
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h47
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c78
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c81
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c404
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c360
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c23
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c20
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c14
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp13
-rw-r--r--source/blender/gpu/intern/gpu_material.c1
-rw-r--r--source/blender/makesdna/DNA_action_types.h4
-rw-r--r--source/blender/makesdna/DNA_cloth_types.h2
-rw-r--r--source/blender/makesdna/DNA_dynamicpaint_types.h2
-rw-r--r--source/blender/makesdna/DNA_effect_types.h4
-rw-r--r--source/blender/makesdna/DNA_freestyle_types.h4
-rw-r--r--source/blender/makesdna/DNA_group_types.h53
-rw-r--r--source/blender/makesdna/DNA_layer_types.h59
-rw-r--r--source/blender/makesdna/DNA_lightprobe_types.h2
-rw-r--r--source/blender/makesdna/DNA_object_force_types.h4
-rw-r--r--source/blender/makesdna/DNA_object_types.h8
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h4
-rw-r--r--source/blender/makesdna/DNA_particle_types.h6
-rw-r--r--source/blender/makesdna/DNA_rigidbody_types.h6
-rw-r--r--source/blender/makesdna/DNA_scene_types.h7
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h6
-rw-r--r--source/blender/makesdna/DNA_space_types.h26
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c13
-rw-r--r--source/blender/makesrna/RNA_access.h4
-rw-r--r--source/blender/makesrna/RNA_enum_types.h7
-rw-r--r--source/blender/makesrna/intern/makesrna.c30
-rw-r--r--source/blender/makesrna/intern/rna_ID.c6
-rw-r--r--source/blender/makesrna/intern/rna_action.c12
-rw-r--r--source/blender/makesrna/intern/rna_context.c11
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c4
-rw-r--r--source/blender/makesrna/intern/rna_group.c208
-rw-r--r--source/blender/makesrna/intern/rna_internal.h4
-rw-r--r--source/blender/makesrna/intern/rna_layer.c600
-rw-r--r--source/blender/makesrna/intern/rna_lightprobe.c3
-rw-r--r--source/blender/makesrna/intern/rna_main.c6
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c40
-rw-r--r--source/blender/makesrna/intern/rna_object.c19
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c6
-rw-r--r--source/blender/makesrna/intern/rna_particle.c7
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c10
-rw-r--r--source/blender/makesrna/intern/rna_scene.c22
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c12
-rw-r--r--source/blender/makesrna/intern/rna_space.c33
-rw-r--r--source/blender/python/intern/bpy_library_load.c2
-rw-r--r--source/blender/render/intern/source/pipeline.c26
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c10
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c10
132 files changed, 4223 insertions, 6027 deletions
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index f06959762d5..093c4de085e 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -409,7 +409,7 @@ void AbcExporter::exploreTransform(Depsgraph *depsgraph, Base *ob_base, Object *
continue;
}
- if (link->type == OB_DUPLIGROUP) {
+ if (link->type == OB_DUPLICOLLECTION) {
dupli_ob = link->ob;
dupli_parent = (dupli_ob->parent) ? dupli_ob->parent : ob;
@@ -522,7 +522,7 @@ void AbcExporter::exploreObject(Depsgraph *depsgraph, Base *ob_base, Object *dup
if (m_settings.renderable_only && link->no_draw) {
continue;
}
- if (link->type == OB_DUPLIGROUP) {
+ if (link->type == OB_DUPLICOLLECTION) {
fake_base.object = link->ob;
exploreObject(depsgraph, &fake_base, ob);
}
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index 35877f9f5a8..1a6990a1de8 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -840,18 +840,12 @@ static void import_endjob(void *user_data)
BKE_view_layer_base_deselect_all(view_layer);
lc = BKE_layer_collection_get_active(view_layer);
- if (lc == NULL) {
- BLI_assert(BLI_listbase_count_at_most(&view_layer->layer_collections, 1) == 0);
- /* when there is no collection linked to this ViewLayer, create one */
- SceneCollection *sc = BKE_collection_add(&data->scene->id, NULL, COLLECTION_TYPE_NONE, NULL);
- lc = BKE_collection_link(view_layer, sc);
- }
for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
Object *ob = (*iter)->object();
ob->lay = data->scene->lay;
- BKE_collection_object_add(&data->scene->id, lc->scene_collection, ob);
+ BKE_collection_object_add(data->bmain, lc->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_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index a49753d331f..0352346c7ac 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -28,7 +28,7 @@
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 280
-#define BLENDER_SUBVERSION 13
+#define BLENDER_SUBVERSION 14
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 6
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index d3a4d2b8d5b..edc24d9649e 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -27,6 +27,7 @@
* \ingroup bke
*/
+#include "BLI_compiler_compat.h"
#include "BLI_ghash.h"
#include "BLI_iterator.h"
#include "DNA_listBase.h"
@@ -35,53 +36,132 @@
extern "C" {
#endif
+/* Structs */
+
struct Base;
struct BLI_Iterator;
-struct Group;
+struct Collection;
+struct Depsgraph;
struct ID;
-struct LayerCollection;
struct Main;
struct Object;
struct Scene;
-struct SceneCollection;
struct ViewLayer;
-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_duplicate(struct ID *owner_id, struct SceneCollection *scene_collection);
-struct SceneCollection *BKE_collection_master(const struct ID *owner_id);
-void BKE_collection_rename(const struct ID *owner_id, struct SceneCollection *sc, const char *name);
-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);
-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);
-bool BKE_collection_object_exists(struct SceneCollection *scene_collection, struct Object *ob);
-struct SceneCollection *BKE_collection_from_index(struct Scene *scene, const int index);
+typedef struct CollectionParent {
+ struct CollectionParent *next, *prev;
+ struct Collection *collection;
+} CollectionParent;
+
+/* Collections */
+
+struct Collection *BKE_collection_add(struct Main *bmain, struct Collection *parent, const char *name);
+void BKE_collection_free(struct Collection *collection);
+bool BKE_collection_delete(struct Main *bmain, struct Collection *collection, bool hierarchy);
+
+struct Collection *BKE_collection_copy(struct Main *bmain, struct Collection *parent, struct Collection *collection);
+struct Collection *BKE_collection_copy_master(struct Main *bmain, struct Collection *collection, const int flag);
+void BKE_collection_copy_data(struct Main *bmain, struct Collection *collection_dst, const struct Collection *collection_src, const int flag);
+void BKE_collection_copy_full(struct Main *bmain, struct Collection *collection);
+void BKE_collection_make_local(struct Main *bmain, struct Collection *collection, const bool lib_local);
+
+/* Master Collection for Scene */
+
+struct Collection *BKE_collection_master(const struct Scene *scene);
+struct Collection *BKE_collection_master_add(void);
+
+/* Collection Objects */
+
+bool BKE_collection_has_object(struct Collection *collection, struct Object *ob);
+bool BKE_collection_has_object_recursive(struct Collection *collection, struct Object *ob);
+struct Collection *BKE_collection_object_find(struct Main *bmain, struct Collection *collection, struct Object *ob);
+
+bool BKE_collection_object_add(struct Main *bmain, struct Collection *collection, struct Object *ob);
+void BKE_collection_object_add_from(struct Main *bmain, struct Scene *scene, struct Object *ob_src, struct Object *ob_dst);
+bool BKE_collection_object_remove(struct Main *bmain, struct Collection *collection, struct Object *object, const bool free_us);
+void BKE_collection_object_move(struct Main *bmain, struct Scene *scene, struct Collection *collection_dst, struct Collection *collection_src, struct Object *ob);
+
+bool BKE_scene_collections_object_remove(struct Main *bmain, struct Scene *scene, struct Object *object, const bool free_us);
+void BKE_collections_object_remove_nulls(struct Main *bmain);
+void BKE_collections_child_remove_nulls(struct Main *bmain, struct Collection *old_collection);
+
+/* Dependencies. */
+
+bool BKE_collection_is_in_scene(struct Collection *collection);
+void BKE_collections_after_lib_link(struct Main *bmain);
+bool BKE_collection_object_cyclic_check(struct Main *bmain, struct Object *object, struct Collection *collection);
+bool BKE_collection_is_animated(struct Collection *collection, struct Object *parent);
+void BKE_collection_handle_recalc_and_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *parent, struct Collection *collection);
+
+/* Object list cache. */
-void BKE_collection_new_name_get(struct ID *owner_id, struct SceneCollection *sc_parent, char *rname);
+struct ListBase BKE_collection_object_cache_get(struct Collection *collection);
+void BKE_collection_object_cache_free(struct Collection *collection);
-bool BKE_collection_objects_select(struct ViewLayer *view_layer, struct SceneCollection *scene_collection);
+struct Base *BKE_collection_or_layer_objects(struct Depsgraph *depsgraph,
+ const struct Scene *scene,
+ const struct ViewLayer *view_layer,
+ struct Collection *collection);
-struct Group *BKE_collection_group_create(struct Main *bmain, struct Scene *scene, struct LayerCollection *lc);
+/* Editing. */
-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);
+struct Collection *BKE_collection_from_index(struct Scene *scene, const int index);
+void BKE_collection_new_name_get(struct Collection *collection_parent, char *rname);
+bool BKE_collection_objects_select(struct ViewLayer *view_layer, struct Collection *collection, bool deselect);
-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);
+/* Collection children */
+
+bool BKE_collection_child_add(struct Main *bmain,
+ struct Collection *parent,
+ struct Collection *child);
+
+bool BKE_collection_child_remove(struct Main *bmain,
+ struct Collection *parent,
+ struct Collection *child);
+
+bool BKE_collection_move(struct Main *bmain,
+ struct Collection *to_parent,
+ struct Collection *from_parent,
+ struct Collection *relative,
+ bool relative_after,
+ struct Collection *collection);
+
+bool BKE_collection_find_cycle(struct Collection *new_ancestor,
+ struct Collection *collection);
+
+
+/* Iteration callbacks. */
typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
-typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data);
+typedef void (*BKE_scene_collections_Cb)(struct Collection *ob, void *data);
void BKE_scene_collections_callback(struct Scene *scene, BKE_scene_collections_Cb callback, void *data);
void BKE_scene_objects_callback(struct Scene *scene, BKE_scene_objects_Cb callback, void *data);
-/* iterators */
+/* Iteratorion over objects in collection. */
+
+#define FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(_collection, _base) \
+ for (Base *_base = (Base*)BKE_collection_object_cache_get(_collection).first; \
+ _base; \
+ _base = _base->next) \
+ {
+
+#define FOREACH_COLLECTION_BASE_RECURSIVE_END \
+ }
+
+#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object) \
+ for (Base *_base = (Base*)BKE_collection_object_cache_get(_collection).first; \
+ _base; \
+ _base = _base->next) \
+ { \
+ Object *_object = _base->object; \
+ BLI_assert(_object != NULL);
+
+#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END \
+ } ((void)0)
+
+/* Iteration over collections in scene. */
+
void BKE_scene_collections_iterator_begin(struct BLI_Iterator *iter, void *data_in);
void BKE_scene_collections_iterator_next(struct BLI_Iterator *iter);
void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter);
@@ -90,11 +170,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_BEGIN(_id, _instance) \
+#define FOREACH_SCENE_COLLECTION_BEGIN(scene, _instance) \
ITER_BEGIN(BKE_scene_collections_iterator_begin, \
BKE_scene_collections_iterator_next, \
BKE_scene_collections_iterator_end, \
- _id, SceneCollection *, _instance)
+ scene, Collection *, _instance)
#define FOREACH_SCENE_COLLECTION_END \
ITER_END
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index 0bf7f657f70..2392c92bd84 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -44,7 +44,7 @@
#include "BLI_kdopbvh.h"
struct CollisionModifierData;
-struct Group;
+struct Collection;
struct MFace;
struct MVert;
struct Object;
@@ -148,9 +148,9 @@ void collision_get_collider_velocity(float vel_old[3], float vel_new[3], struct
/////////////////////////////////////////////////
/* explicit control over layer mask and dupli recursion */
-struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj, unsigned int modifier_type, bool dupli);
+struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Collection *collection, unsigned int *numcollobj, unsigned int modifier_type, bool dupli);
-struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj, unsigned int modifier_type);
+struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Collection *collection, unsigned int *numcollobj, unsigned int modifier_type);
typedef struct ColliderCache {
struct ColliderCache *next, *prev;
@@ -158,7 +158,7 @@ typedef struct ColliderCache {
struct CollisionModifierData *collmd;
} ColliderCache;
-struct ListBase *get_collider_cache(struct Scene *scene, struct Object *self, struct Group *group);
+struct ListBase *get_collider_cache(struct Scene *scene, struct Object *self, struct Collection *collection);
void free_collider_cache(struct ListBase **colliders);
/////////////////////////////////////////////////
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 12525fe9a50..e224863a27f 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -40,6 +40,7 @@ extern "C" {
struct ARegion;
struct bScreen;
struct CacheFile;
+struct Collection;
struct Depsgraph;
struct LayerCollection;
struct ListBase;
@@ -49,7 +50,6 @@ struct Base;
struct PointerRNA;
struct ReportList;
struct Scene;
-struct SceneCollection;
struct ViewLayer;
struct ScrArea;
struct SpaceLink;
@@ -257,7 +257,7 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas
struct Main *CTX_data_main(const bContext *C);
struct Scene *CTX_data_scene(const bContext *C);
struct LayerCollection *CTX_data_layer_collection(const bContext *C);
-struct SceneCollection *CTX_data_scene_collection(const bContext *C);
+struct Collection *CTX_data_collection(const bContext *C);
struct ViewLayer *CTX_data_view_layer(const bContext *C);
struct RenderEngineType *CTX_data_engine_type(const bContext *C);
struct ToolSettings *CTX_data_tool_settings(const bContext *C);
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index 914dd650493..d45ecf9e3d8 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -40,13 +40,13 @@
struct Object;
struct Scene;
struct ListBase;
-struct Group;
+struct Collection;
struct ParticleSimulationData;
struct ParticleData;
struct ParticleKey;
struct Depsgraph;
-struct EffectorWeights *BKE_add_effector_weights(struct Group *group);
+struct EffectorWeights *BKE_add_effector_weights(struct Collection *collection);
struct PartDeflect *object_add_collision_fields(int type);
/* Input to effector code */
diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h
index f7368683d93..073a56e98fc 100644
--- a/source/blender/blenkernel/BKE_freestyle.h
+++ b/source/blender/blenkernel/BKE_freestyle.h
@@ -50,7 +50,7 @@ typedef struct FreestyleModuleSettings FreestyleModuleSettings;
/* FreestyleConfig */
void BKE_freestyle_config_init(FreestyleConfig *config);
void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user);
-void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config, const int flag);
+void BKE_freestyle_config_copy(FreestyleConfig *new_config, const FreestyleConfig *config, const int flag);
/* FreestyleConfig.modules */
FreestyleModuleConfig *BKE_freestyle_module_add(FreestyleConfig *config);
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
deleted file mode 100644
index 0195d1f1243..00000000000
--- a/source/blender/blenkernel/BKE_group.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-#ifndef __BKE_GROUP_H__
-#define __BKE_GROUP_H__
-
-/** \file BKE_group.h
- * \ingroup bke
- * \since March 2001
- * \author nzc
- */
-
-struct Base;
-struct Depsgraph;
-struct Group;
-struct Main;
-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);
-void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local);
-bool BKE_group_object_add(struct Group *group, struct Object *ob);
-bool BKE_group_object_unlink(struct Group *group, struct Object *ob);
-struct Group *BKE_group_object_find(struct Group *group, struct Object *ob);
-bool BKE_group_object_exists(struct Group *group, struct Object *ob);
-bool BKE_group_object_cyclic_check(struct Main *bmain, struct Object *object, struct Group *group);
-bool BKE_group_is_animated(struct Group *group, struct Object *parent);
-
-void BKE_group_handle_recalc_and_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *parent, struct Group *group);
-
-/* Dependency graph evaluation. */
-
-void BKE_group_eval_view_layers(struct Depsgraph *depsgraph,
- struct Group *group);
-
-/* Helper macros. */
-
-#define FOREACH_GROUP_BASE_BEGIN(_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_BEGIN(_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 \
- } ((void)0)
-
-#endif /* __BKE_GROUP_H__ */
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 00154f3e68e..25130f43b73 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -29,6 +29,7 @@
#include "BKE_collection.h"
+#include "DNA_listBase.h"
#include "DNA_scene_types.h"
#ifdef __cplusplus
@@ -42,8 +43,8 @@ extern "C" {
#define ROOT_PROP "root"
struct Base;
+struct Collection;
struct Depsgraph;
-struct Group;
struct ID;
struct IDProperty;
struct LayerCollection;
@@ -52,7 +53,6 @@ struct Main;
struct Object;
struct RenderEngine;
struct Scene;
-struct SceneCollection;
struct ViewLayer;
struct WorkSpace;
@@ -60,7 +60,6 @@ struct ViewLayer *BKE_view_layer_default_view(const struct Scene *scene);
struct ViewLayer *BKE_view_layer_default_render(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);
@@ -71,57 +70,36 @@ void BKE_view_layer_free_ex(struct ViewLayer *view_layer, const bool do_id_user)
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_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 ViewLayer *BKE_view_layer_find_from_collection(const struct Scene *scene, struct LayerCollection *lc);
struct Base *BKE_view_layer_base_find(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_layer_collection_sync_flags(
- struct ID *owner_id,
- struct SceneCollection *scene_collection_dst,
- struct SceneCollection *scene_collection_src);
-
void BKE_view_layer_copy_data(
- struct ViewLayer *view_layer_dst, struct ViewLayer *view_layer_src,
- struct SceneCollection *mc_dst, struct SceneCollection *mc_src,
+ struct Scene *scene_dst, const struct Scene *scene_src,
+ struct ViewLayer *view_layer_dst, const struct ViewLayer *view_layer_src,
const int flag);
-struct LayerCollection *BKE_layer_collection_duplicate(struct ID *owner_id, struct LayerCollection *layer_collection);
-
-void BKE_layer_collection_free(struct ViewLayer *view_layer, struct LayerCollection *lc);
-
struct LayerCollection *BKE_layer_collection_get_active(struct ViewLayer *view_layer);
-struct LayerCollection *BKE_layer_collection_get_active_ensure(struct Scene *scene, struct ViewLayer *view_layer);
+bool BKE_layer_collection_activate(struct ViewLayer *view_layer, struct LayerCollection *lc);
+struct LayerCollection *BKE_layer_collection_activate_parent(struct ViewLayer *view_layer, struct LayerCollection *lc);
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 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 ID *owner_id, const struct SceneCollection *sc);
+void BKE_main_collection_sync(const struct Main *bmain);
+void BKE_scene_collection_sync(const struct Scene *scene);
+void BKE_layer_collection_sync(const struct Scene *scene, struct ViewLayer *view_layer);
-struct LayerCollection *BKE_collection_link(struct ViewLayer *view_layer, struct SceneCollection *sc);
+void BKE_main_collection_sync_remap(const struct Main *bmain);
-void BKE_collection_unlink(struct ViewLayer *view_layer, struct LayerCollection *lc);
-
-void BKE_collection_enable(struct ViewLayer *view_layer, struct LayerCollection *lc);
-
-struct LayerCollection *BKE_layer_collection_first_from_scene_collection(struct ViewLayer *view_layer, const struct SceneCollection *scene_collection);
-bool BKE_view_layer_has_collection(struct ViewLayer *view_layer, const struct SceneCollection *sc);
+struct LayerCollection *BKE_layer_collection_first_from_scene_collection(struct ViewLayer *view_layer, const struct Collection *collection);
+bool BKE_view_layer_has_collection(struct ViewLayer *view_layer, const struct Collection *collection);
bool BKE_scene_has_object(struct Scene *scene, struct Object *ob);
-void BKE_layer_collection_objects_select(struct LayerCollection *layer_collection);
-
-/* syncing */
-
-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);
+bool BKE_layer_collection_objects_select(struct ViewLayer *view_layer, struct LayerCollection *lc, bool deselect);
/* override */
@@ -134,12 +112,12 @@ void BKE_override_layer_collection_boolean_add(struct LayerCollection *layer_col
void BKE_layer_eval_view_layer(
struct Depsgraph *depsgraph,
- struct ID *owner_id,
+ struct Scene *scene,
struct ViewLayer *view_layer);
void BKE_layer_eval_view_layer_indexed(
struct Depsgraph *depsgraph,
- struct ID *owner_id,
+ struct Scene *scene,
int view_layer_index);
/* iterators */
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 647af88d980..efcff9a9382 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -112,7 +112,7 @@ typedef struct Main {
ListBase speaker;
ListBase lightprobe;
ListBase sound;
- ListBase group;
+ ListBase collection;
ListBase armature;
ListBase action;
ListBase nodetree;
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 1d28d7f52c7..99e40c5a975 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -308,8 +308,8 @@ typedef enum eObjectSet {
struct LinkNode *BKE_object_relational_superset(
struct ViewLayer *view_layer, eObjectSet objectSet, eObRelationTypes includeFilter);
-struct LinkNode *BKE_object_groups(struct Object *ob);
-void BKE_object_groups_clear(struct Object *object);
+struct LinkNode *BKE_object_groups(struct Main *bmain, struct Object *ob);
+void BKE_object_groups_clear(struct Main *bmain, struct Object *object);
struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 44aa1b04569..0606108a23b 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -38,12 +38,12 @@ extern "C" {
#endif
struct AviCodecData;
+struct Collection;
struct Depsgraph;
struct Main;
struct Object;
struct RenderData;
struct Scene;
-struct SceneCollection;
struct ViewLayer;
struct UnitSettings;
struct ViewRender;
@@ -120,7 +120,7 @@ void BKE_scene_groups_relink(struct Scene *sce);
void BKE_scene_make_local(struct Main *bmain, struct Scene *sce, const bool lib_local);
-struct Scene *BKE_scene_find_from_collection(const struct Main *bmain, const struct SceneCollection *scene_collection);
+struct Scene *BKE_scene_find_from_collection(const struct Main *bmain, const struct Collection *collection);
#ifdef DURIAN_CAMERA_SWITCH
struct Object *BKE_scene_camera_switch_find(struct Scene *scene); // DURIAN_CAMERA_SWITCH
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index d5ce6f2f94d..867b5884114 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -114,7 +114,6 @@ set(SRC
intern/font.c
intern/freestyle.c
intern/gpencil.c
- intern/group.c
intern/icons.c
intern/icons_rasterize.c
intern/idcode.c
@@ -253,7 +252,6 @@ set(SRC
BKE_freestyle.h
BKE_global.h
BKE_gpencil.h
- BKE_group.h
BKE_icons.h
BKE_idcode.h
BKE_idprop.h
diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c
index b0c571bf159..7b149761952 100644
--- a/source/blender/blenkernel/intern/blender_copybuffer.c
+++ b/source/blender/blenkernel/intern/blender_copybuffer.c
@@ -98,7 +98,7 @@ bool BKE_copybuffer_read(Main *bmain_dst, const char *libname, ReportList *repor
/* Here appending/linking starts. */
Main *mainl = BLO_library_link_begin(bmain_dst, &bh, libname);
BLO_library_link_copypaste(mainl, bh);
- BLO_library_link_end(mainl, &bh, 0, NULL, NULL);
+ BLO_library_link_end(mainl, &bh, 0, NULL, NULL, NULL);
/* Mark all library linked objects to be updated. */
BKE_main_lib_objects_recalc_all(bmain_dst);
IMB_colormanagement_check_file_config(bmain_dst);
@@ -145,7 +145,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
BLO_library_link_copypaste(mainl, bh);
- BLO_library_link_end(mainl, &bh, flag, scene, view_layer);
+ BLO_library_link_end(mainl, &bh, flag, bmain, scene, view_layer);
/* mark all library linked objects to be updated */
BKE_main_lib_objects_recalc_all(bmain);
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 4303f7d9150..5ba4a1196b8 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -31,15 +31,17 @@
#include "BLI_iterator.h"
#include "BLI_listbase.h"
#include "BLI_math_base.h"
+#include "BLI_threads.h"
#include "BLT_translation.h"
#include "BLI_string_utils.h"
#include "BKE_collection.h"
-#include "BKE_group.h"
+#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_object.h"
#include "BKE_scene.h"
#include "DNA_group_types.h"
@@ -48,412 +50,573 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "MEM_guardedalloc.h"
-/* Prototypes. */
-static SceneCollection *find_collection_parent(const struct SceneCollection *sc_child, struct SceneCollection *sc_parent);
-static bool is_collection_in_tree(const struct SceneCollection *sc_reference, struct SceneCollection *sc_parent);
+/******************************** Prototypes ********************************/
-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;
- }
-}
+static bool collection_child_add(Collection *parent, Collection *collection, int flag, const bool add_us);
+static bool collection_child_remove(Collection *parent, Collection *collection);
+static bool collection_object_add(Collection *collection, Object *ob, int flag, const bool add_us);
+static bool collection_object_remove(Main *bmain, Collection *collection, Object *ob, const bool free_us);
-/**
- * The automatic/fallback name of a new collection.
- */
-void BKE_collection_new_name_get(ID *owner_id, SceneCollection *sc_parent, char *rname)
-{
- SceneCollection *sc_master = collection_master_from_id(owner_id);
- char *name;
+static CollectionChild *collection_find_child(Collection *parent, Collection *collection);
+static CollectionParent *collection_find_parent(Collection *child, Collection *collection);
- if (sc_parent == sc_master) {
- name = BLI_sprintfN("Collection %d", BLI_listbase_count(&sc_master->scene_collections) + 1);
- }
- else {
- const int number = BLI_listbase_count(&sc_parent->scene_collections) + 1;
- const int digits = integer_digits_i(number);
- const int max_len = sizeof(sc_parent->name) - 1 /* NULL terminator */ - (1 + digits) /* " %d" */;
- name = BLI_sprintfN("%.*s %d", max_len, sc_parent->name, number);
- }
+static bool collection_find_child_recursive(Collection *parent, Collection *collection);
- BLI_strncpy(rname, name, MAX_NAME);
- MEM_freeN(name);
-}
+/***************************** Add Collection *******************************/
-/**
- * Add a new collection, but don't handle syncing with layer collections
- */
-static SceneCollection *collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom)
+/* Add new collection, without view layer syncing. */
+static Collection *collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
{
- SceneCollection *sc_master = collection_master_from_id(owner_id);
- SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection");
- sc->type = type;
+ /* Determine new collection name. */
char name[MAX_NAME];
- if (!sc_parent) {
- sc_parent = sc_master;
- }
-
- if (name_custom != NULL) {
- BLI_strncpy(name, name_custom, MAX_NAME);
+ if (name_custom) {
+ STRNCPY(name, name_custom);
}
else {
- BKE_collection_new_name_get(owner_id, sc_parent, name);
+ BKE_collection_new_name_get(collection_parent, name);
}
- BLI_addtail(&sc_parent->scene_collections, sc);
- BKE_collection_rename(owner_id, sc, name);
+ /* Create new collection. */
+ Collection *collection = BKE_libblock_alloc(bmain, ID_GR, name, 0);
+
+ /* We increase collection user count when linking to Collections. */
+ id_us_min(&collection->id);
+
+ /* Optionally add to parent collection. */
+ if (collection_parent) {
+ collection_child_add(collection_parent, collection, 0, true);
+ }
- return sc;
+ return collection;
}
/**
* 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(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom)
+Collection *BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
{
- if (sc_parent == NULL) {
- sc_parent = BKE_collection_master(owner_id);
- }
+ Collection *collection = collection_add(bmain, collection_parent, name_custom);
+ BKE_main_collection_sync(bmain);
+ return collection;
+}
- SceneCollection *scene_collection = collection_add(owner_id, sc_parent, type, name_custom);
- BKE_layer_sync_new_scene_collection(owner_id, sc_parent, scene_collection);
- return scene_collection;
+/*********************** Free and Delete Collection ****************************/
+
+/** Free (or release) any data used by this collection (does not free the collection itself). */
+void BKE_collection_free(Collection *collection)
+{
+ /* No animdata here. */
+ BKE_previewimg_free(&collection->preview);
+
+ BLI_freelistN(&collection->gobject);
+ BLI_freelistN(&collection->children);
+ BLI_freelistN(&collection->parents);
+
+ BKE_collection_object_cache_free(collection);
}
/**
- * Free the collection items recursively
+ * Remove a collection, optionally removing its child objects or moving
+ * them to parent collections.
*/
-static void collection_free(SceneCollection *sc, const bool do_id_user)
+bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
{
- if (do_id_user) {
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- id_us_min(link->data);
+ /* Master collection is not real datablock, can't be removed. */
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ BLI_assert("!Scene master collection can't be deleted");
+ return false;
+ }
+
+ if (hierarchy) {
+ /* Remove child objects. */
+ CollectionObject *cob = collection->gobject.first;
+ while (cob != NULL) {
+ collection_object_remove(bmain, collection, cob->ob, true);
+ cob = collection->gobject.first;
+ }
+
+ /* Delete all child collections recursively. */
+ CollectionChild *child = collection->children.first;
+ while (child != NULL) {
+ BKE_collection_delete(bmain, child->collection, hierarchy);
+ child = collection->children.first;
}
}
+ else {
+ /* Link child collections into parent collection. */
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ Collection *parent = cparent->collection;
+ collection_child_add(parent, child->collection, 0, true);
+ }
+ }
- BLI_freelistN(&sc->objects);
+ CollectionObject *cob = collection->gobject.first;
+ while (cob != NULL) {
+ /* Link child object into parent collections. */
+ for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ Collection *parent = cparent->collection;
+ collection_object_add(parent, cob->ob, 0, true);
+ }
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- collection_free(nsc, do_id_user);
+ /* Remove child object. */
+ collection_object_remove(bmain, collection, cob->ob, true);
+ cob = collection->gobject.first;
+ }
}
- BLI_freelistN(&sc->scene_collections);
+
+ BKE_libblock_delete(bmain, collection);
+
+ BKE_main_collection_sync(bmain);
+
+ return true;
}
+/***************************** Collection Copy *******************************/
+
/**
- * Unlink the collection recursively
- * \return true if unlinked.
+ * Only copy internal data of Collection 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.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
*/
-static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_gone)
+void BKE_collection_copy_data(Main *UNUSED(bmain), Collection *collection_dst, const Collection *collection_src, const int flag)
{
- for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next) {
- if (sc == sc_gone) {
- BLI_remlink(&sc_parent->scene_collections, sc_gone);
- return true;
- }
+ /* Do not copy collection's preview (same behavior as for objects). */
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
+ BKE_previewimg_id_copy(&collection_dst->id, &collection_src->id);
+ }
+ else {
+ collection_dst->preview = NULL;
+ }
- if (collection_remlink(sc, sc_gone)) {
- return true;
- }
+ collection_dst->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
+ BLI_listbase_clear(&collection_dst->object_cache);
+
+ BLI_listbase_clear(&collection_dst->gobject);
+ BLI_listbase_clear(&collection_dst->children);
+ BLI_listbase_clear(&collection_dst->parents);
+
+ for (CollectionChild *child = collection_src->children.first; child; child = child->next) {
+ collection_child_add(collection_dst, child->collection, flag, false);
+ }
+ for (CollectionObject *cob = collection_src->gobject.first; cob; cob = cob->next) {
+ collection_object_add(collection_dst, cob->ob, flag, false);
}
- return false;
}
/**
- * Recursively remove any instance of this SceneCollection
+ * Makes a shallow copy of a Collection
+ *
+ * Add a new collection in the same level as the old one, copy any nested collections
+ * but link the objects to the new collection (as oppose to copy them).
*/
-static void layer_collection_remove(ViewLayer *view_layer, ListBase *lb, const SceneCollection *sc)
-{
- LayerCollection *lc = lb->first;
- while (lc) {
- if (lc->scene_collection == sc) {
- BKE_layer_collection_free(view_layer, lc);
- BLI_remlink(lb, lc);
-
- LayerCollection *lc_next = lc->next;
- MEM_freeN(lc);
- lc = lc_next;
-
- /* only the "top-level" layer collections may have the
- * same SceneCollection in a sibling tree.
- */
- if (lb != &view_layer->layer_collections) {
- return;
- }
- }
+Collection *BKE_collection_copy(Main *bmain, Collection *parent, Collection *collection)
+{
+ /* It's not allowed to copy the master collection. */
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ BLI_assert("!Master collection can't be copied");
+ return NULL;
+ }
- else {
- layer_collection_remove(view_layer, &lc->layer_collections, sc);
- lc = lc->next;
+ Collection *collection_new;
+ BKE_id_copy_ex(bmain, &collection->id, (ID **)&collection_new, 0, false);
+
+ /* Optionally add to parent. */
+ if (parent) {
+ if (collection_child_add(parent, collection_new, 0, true)) {
+ /* Put collection right after existing one. */
+ CollectionChild *child = collection_find_child(parent, collection);
+ CollectionChild *child_new = collection_find_child(parent, collection_new);
+
+ if (child && child_new) {
+ BLI_remlink(&parent->children, child_new);
+ BLI_insertlinkafter(&parent->children, child, child_new);
+ }
}
}
+
+ BKE_main_collection_sync(bmain);
+
+ return collection_new;
}
+Collection *BKE_collection_copy_master(Main *bmain, Collection *collection, const int flag)
+{
+ BLI_assert(collection->flag & COLLECTION_IS_MASTER);
+
+ Collection *collection_dst = MEM_dupallocN(collection);
+ BKE_collection_copy_data(bmain, collection_dst, collection, flag);
+ return collection_dst;
+}
+
+void BKE_collection_copy_full(Main *UNUSED(bmain), Collection *UNUSED(collection))
+{
+ // TODO: implement full scene copy
+}
+
+void BKE_collection_make_local(Main *bmain, Collection *collection, const bool lib_local)
+{
+ BKE_id_make_local_generic(bmain, &collection->id, true, lib_local);
+}
+
+/********************************* Naming *******************************/
+
/**
- * Remove a collection from the scene, and syncronize all render layers
- *
- * If an object is in any other collection, link the object to the master collection.
+ * The automatic/fallback name of a new collection.
*/
-bool BKE_collection_remove(ID *owner_id, SceneCollection *sc)
+void BKE_collection_new_name_get(Collection *collection_parent, char *rname)
{
- SceneCollection *sc_master = collection_master_from_id(owner_id);
+ char *name;
- /* The master collection cannot be removed. */
- if (sc == sc_master) {
- return false;
+ if (!collection_parent) {
+ name = BLI_sprintfN("Collection");
}
-
- /* We need to do bottom up removal, otherwise we get a crash when we remove a collection that
- * has one of its nested collections linked to a view layer. */
- SceneCollection *scene_collection_nested = sc->scene_collections.first;
- while (scene_collection_nested != NULL) {
- SceneCollection *scene_collection_next = scene_collection_nested->next;
- BKE_collection_remove(owner_id, scene_collection_nested);
- scene_collection_nested = scene_collection_next;
+ else if (collection_parent->flag & COLLECTION_IS_MASTER) {
+ name = BLI_sprintfN("Collection %d", BLI_listbase_count(&collection_parent->children) + 1);
}
-
- /* Unlink from the respective collection tree. */
- if (!collection_remlink(sc_master, sc)) {
- BLI_assert(false);
+ else {
+ const int number = BLI_listbase_count(&collection_parent->children) + 1;
+ const int digits = integer_digits_i(number);
+ const int max_len = sizeof(collection_parent->id.name) - 1 /* NULL terminator */ - (1 + digits) /* " %d" */ - 2 /* ID */;
+ name = BLI_sprintfN("%.*s %d", max_len, collection_parent->id.name + 2, number);
}
- /* If an object is no longer in any collection, we add it to the master collection. */
- ListBase collection_objects;
- BLI_duplicatelist(&collection_objects, &sc->objects);
+ BLI_strncpy(rname, name, MAX_NAME);
+ MEM_freeN(name);
+}
- FOREACH_SCENE_COLLECTION_BEGIN(owner_id, scene_collection_iter)
+/************************* Dependencies ****************************/
+
+bool BKE_collection_is_animated(Collection *collection, Object *UNUSED(parent))
+{
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
- if (scene_collection_iter == sc) {
- continue;
+ if (object->proxy) {
+ return true;
}
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ return false;
+}
- LinkData *link_next, *link = collection_objects.first;
- while (link) {
- link_next = link->next;
+/* puts all collection members in local timing system, after this call
+ * you can draw everything, leaves tags in objects to signal it needs further updating */
- if (BLI_findptr(&scene_collection_iter->objects, link->data, offsetof(LinkData, data))) {
- BLI_remlink(&collection_objects, link);
- MEM_freeN(link);
- }
-
- link = link_next;
+/* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */
+void BKE_collection_handle_recalc_and_update(struct Depsgraph *depsgraph, Scene *scene, Object *UNUSED(parent), Collection *collection)
+{
+ /* only do existing tags, as set by regular depsgraph */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
+ {
+ if (object->id.recalc & ID_RECALC_ALL) {
+ BKE_object_handle_update(depsgraph, scene, object);
}
}
- FOREACH_SCENE_COLLECTION_END;
-
- for (LinkData *link = collection_objects.first; link; link = link->next) {
- BKE_collection_object_add(owner_id, sc_master, link->data);
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
- BLI_freelistN(&collection_objects);
+/* **************** Object List Cache *******************/
+
+static void collection_object_cache_fill(ListBase *lb, Collection *collection, int parent_restrict)
+{
+ int child_restrict = collection->flag | parent_restrict;
+
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Base *base = BLI_findptr(lb, cob->ob, offsetof(Base, object));
+
+ if (base == NULL) {
+ base = MEM_callocN(sizeof(Base), "Object Base");
+ base->object = cob->ob;
- /* Clear the collection items. */
- collection_free(sc, true);
+ if ((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) {
+ base->flag |= BASE_VISIBLED | BASE_VISIBLE_VIEWPORT;
- /* check all layers that use this collection and clear them */
- 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;
+ if ((child_restrict & COLLECTION_RESTRICT_SELECT) == 0) {
+ base->flag |= BASE_SELECTABLED;
+ }
+ }
+
+ if ((child_restrict & COLLECTION_RESTRICT_RENDER) == 0) {
+ base->flag |= BASE_VISIBLE_RENDER;
+ }
+
+ BLI_addtail(lb, base);
+ }
}
- MEM_freeN(sc);
- return true;
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ collection_object_cache_fill(lb, child->collection, child_restrict);
+ }
}
-/**
- * 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)
+ListBase BKE_collection_object_cache_get(Collection *collection)
{
- 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);
+ if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE)) {
+ static ThreadMutex cache_lock = BLI_MUTEX_INITIALIZER;
+
+ if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE)) {
+ BLI_mutex_lock(&cache_lock);
+ collection_object_cache_fill(&collection->object_cache, collection, 0);
+ collection->flag |= COLLECTION_HAS_OBJECT_CACHE;
+ BLI_mutex_unlock(&cache_lock);
}
}
- 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);
- }
+ return collection->object_cache;
}
-/**
- * Makes a shallow copy of a SceneCollection
- *
- * Add a new collection in the same level as the old one, copy any nested collections
- * but link the objects to the new collection (as oppose to copy them).
- */
-SceneCollection *BKE_collection_duplicate(ID *owner_id, SceneCollection *scene_collection)
+static void collection_object_cache_free(Collection *collection)
{
- SceneCollection *scene_collection_master = BKE_collection_master(owner_id);
- SceneCollection *scene_collection_parent = find_collection_parent(scene_collection, scene_collection_master);
+ /* Clear own cache an for all parents, since those are affected by changes as well. */
+ collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
+ BLI_freelistN(&collection->object_cache);
- /* It's not allowed to copy the master collection. */
- if (scene_collection_master == scene_collection) {
- return NULL;
+ for (CollectionParent *parent = collection->parents.first; parent; parent = parent->next) {
+ collection_object_cache_free(parent->collection);
}
+}
+
+void BKE_collection_object_cache_free(Collection *collection)
+{
+ collection_object_cache_free(collection);
+}
+
+Base *BKE_collection_or_layer_objects(Depsgraph *depsgraph,
+ const Scene *scene,
+ const ViewLayer *view_layer,
+ Collection *collection)
+{
+ // TODO: this is used by physics to get objects from a collection, but the
+ // the physics systems are not all using the depsgraph correctly which means
+ // we try different things. Instead we should explicitly get evaluated or
+ // non-evaluated data and always have the depsgraph available when needed
- SceneCollection *scene_collection_new = collection_add(
- owner_id,
- scene_collection_parent,
- scene_collection->type,
- scene_collection->name);
+ if (collection) {
+ return BKE_collection_object_cache_get(collection).first;
+ }
+ else if (depsgraph) {
+ view_layer = DEG_get_evaluated_view_layer(depsgraph);
- if (scene_collection_new != scene_collection->next) {
- BLI_remlink(&scene_collection_parent->scene_collections, scene_collection_new);
- BLI_insertlinkafter(&scene_collection_parent->scene_collections, scene_collection, scene_collection_new);
+ if (view_layer) {
+ return FIRSTBASE(view_layer);
+ }
+ else {
+ view_layer = DEG_get_input_view_layer(depsgraph);
+ return FIRSTBASE(view_layer);
+ }
+ }
+ else if (view_layer) {
+ return FIRSTBASE(view_layer);
+ }
+ else {
+ /* depsgraph is NULL during deg build */
+ return FIRSTBASE(BKE_view_layer_context_active_PLACEHOLDER(scene));
}
+}
- BKE_collection_copy_data(scene_collection_new, scene_collection, 0);
- BKE_layer_sync_new_scene_collection(owner_id, scene_collection_parent, scene_collection_new);
+/*********************** Scene Master Collection ***************/
- /* Make sure every linked instance of the new collection has the same values (flags, overrides, ...) as the
- * corresponding original collection. */
- BKE_layer_collection_sync_flags(owner_id, scene_collection_new, scene_collection);
+Collection *BKE_collection_master_add()
+{
+ /* Not an actual datablock, but owned by scene. */
+ Collection *master_collection = MEM_callocN(sizeof(Collection), "Master Collection");
+ STRNCPY(master_collection->id.name, "GRMaster Collection");
+ master_collection->flag |= COLLECTION_IS_MASTER;
+ return master_collection;
+}
- return scene_collection_new;
+Collection *BKE_collection_master(const Scene *scene)
+{
+ return scene->master_collection;
}
-static SceneCollection *master_collection_from_id(const ID *owner_id)
+/*********************** Cyclic Checks ************************/
+
+static bool collection_object_cyclic_check_internal(Object *object, Collection *collection)
{
- 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;
+ if (object->dup_group) {
+ Collection *dup_collection = object->dup_group;
+ if ((dup_collection->id.tag & LIB_TAG_DOIT) == 0) {
+ /* Cycle already exists in collections, let's prevent further crappyness */
+ return true;
+ }
+ /* flag the object to identify cyclic dependencies in further dupli collections */
+ dup_collection->id.tag &= ~LIB_TAG_DOIT;
+
+ if (dup_collection == collection) {
+ return true;
+ }
+ else {
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(dup_collection, collection_object)
+ {
+ if (collection_object_cyclic_check_internal(collection_object, dup_collection)) {
+ return true;
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
+
+ /* un-flag the object, it's allowed to have the same collection multiple times in parallel */
+ dup_collection->id.tag |= LIB_TAG_DOIT;
}
+
+ return false;
}
-/**
- * Returns the master collection of the scene or group
- */
-SceneCollection *BKE_collection_master(const ID *owner_id)
+bool BKE_collection_object_cyclic_check(Main *bmain, Object *object, Collection *collection)
{
- return master_collection_from_id(owner_id);
+ /* first flag all collections */
+ BKE_main_id_tag_listbase(&bmain->collection, LIB_TAG_DOIT, true);
+
+ return collection_object_cyclic_check_internal(object, collection);
}
-static void collection_rename(const ID *owner_id, SceneCollection *sc, const char *name)
+/******************* Collection Object Membership *******************/
+
+bool BKE_collection_has_object(Collection *collection, Object *ob)
{
- SceneCollection *sc_parent = find_collection_parent(sc, collection_master_from_id(owner_id));
- BLI_strncpy(sc->name, name, sizeof(sc->name));
- BLI_uniquename(&sc_parent->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
+ if (ELEM(NULL, collection, ob)) {
+ return false;
+ }
+
+ return (BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob)));
}
-void BKE_collection_rename(const ID *owner_id, SceneCollection *sc, const char *name)
+bool BKE_collection_has_object_recursive(Collection *collection, Object *ob)
{
- collection_rename(owner_id, sc, name);
+ if (ELEM(NULL, collection, ob)) {
+ return false;
+ }
+
+ const ListBase objects = BKE_collection_object_cache_get(collection);
+ return (BLI_findptr(&objects, ob, offsetof(Base, object)));
}
-/**
- * Make sure the collection name is still unique within its siblings.
- */
-static void collection_name_check(const ID *owner_id, SceneCollection *sc)
+Collection *BKE_collection_object_find(Main *bmain, Collection *collection, Object *ob)
{
- /* It's a bit of a hack, we simply try to make sure the collection name is valid. */
- collection_rename(owner_id, sc, sc->name);
+ if (collection)
+ collection = collection->id.next;
+ else
+ collection = bmain->collection.first;
+
+ while (collection) {
+ if (BKE_collection_has_object(collection, ob))
+ return collection;
+ collection = collection->id.next;
+ }
+ return NULL;
}
-/**
- * Free (or release) any data used by the master collection (does not free the master collection itself).
- * 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(ID *owner_id, const bool do_id_user)
+/********************** Collection Objects *********************/
+
+static bool collection_object_add(Collection *collection, Object *ob, int flag, const bool add_us)
{
- collection_free(BKE_collection_master(owner_id), do_id_user);
+ if (ob->dup_group) {
+ /* Cyclic dependency check. */
+ if (collection_find_child_recursive(collection, ob->dup_group)) {
+ return false;
+ }
+ }
+
+ CollectionObject *cob = BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob));
+ if (cob) {
+ return false;
+ }
+
+ cob = MEM_callocN(sizeof(CollectionObject), __func__);
+ cob->ob = ob;
+ BLI_addtail(&collection->gobject, cob);
+ BKE_collection_object_cache_free(collection);
+
+ if (add_us && (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus(&ob->id);
+ }
+
+ return true;
}
-static void collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob)
+static bool collection_object_remove(Main *bmain, Collection *collection, Object *ob, const bool free_us)
{
- BLI_addtail(&sc->objects, BLI_genericNodeN(ob));
+ CollectionObject *cob = BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob));
+ if (cob == NULL) {
+ return false;
+ }
+
+ BLI_freelinkN(&collection->gobject, cob);
+ BKE_collection_object_cache_free(collection);
- if (GS(owner_id->name) == ID_SCE) {
- id_us_plus((ID *)ob);
+ if (free_us) {
+ BKE_libblock_free_us(bmain, ob);
}
else {
- BLI_assert(GS(owner_id->name) == ID_GR);
- if ((ob->flag & OB_FROMGROUP) == 0) {
- ob->flag |= OB_FROMGROUP;
- }
+ id_us_min(&ob->id);
}
- BKE_layer_sync_object_link(owner_id, sc, ob);
+ return true;
}
/**
* Add object to collection
*/
-bool BKE_collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob)
+bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
{
- if (BKE_collection_object_exists(sc, ob)) {
- /* don't add the same object twice */
+ if (ELEM(NULL, collection, ob)) {
return false;
}
- collection_object_add(owner_id, sc, ob);
+ if (!collection_object_add(collection, ob, 0, true)) {
+ return false;
+ }
+
+ if (BKE_collection_is_in_scene(collection)) {
+ BKE_main_collection_sync(bmain);
+ }
+
return true;
}
/**
- * Add object to all collections that reference objects is in
+ * Add object to all scene collections that reference objects is in
* (used to copy objects)
*/
-void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst)
+void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
{
- FOREACH_SCENE_COLLECTION_BEGIN(scene, sc)
+ FOREACH_SCENE_COLLECTION_BEGIN(scene, collection)
{
- if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) {
- collection_object_add(&scene->id, sc, ob_dst);
+ if (BKE_collection_has_object(collection, ob_src)) {
+ collection_object_add(collection, ob_dst, 0, true);
}
}
FOREACH_SCENE_COLLECTION_END;
+
+ BKE_main_collection_sync(bmain);
}
/**
* Remove object from collection.
- * \param bmain: Can be NULL if free_us is false.
*/
-bool BKE_collection_object_remove(Main *bmain, ID *owner_id, SceneCollection *sc, Object *ob, const bool free_us)
+bool BKE_collection_object_remove(Main *bmain, Collection *collection, Object *ob, const bool free_us)
{
- LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data));
-
- if (link == NULL) {
+ if (ELEM(NULL, collection, ob)) {
return false;
}
- BLI_remlink(&sc->objects, link);
- MEM_freeN(link);
-
- BKE_layer_sync_object_unlink(owner_id, sc, ob);
-
- if (GS(owner_id->name) == ID_SCE) {
- if (free_us) {
- BKE_libblock_free_us(bmain, ob);
- }
- else {
- id_us_min(&ob->id);
- }
+ if (collection_object_remove(bmain, collection, ob, free_us)) {
+ return false;
}
- else {
- BLI_assert(GS(owner_id->name) == ID_GR);
+
+ if (BKE_collection_is_in_scene(collection)) {
+ BKE_main_collection_sync(bmain);
}
return true;
@@ -463,408 +626,436 @@ bool BKE_collection_object_remove(Main *bmain, ID *owner_id, SceneCollection *sc
* Remove object from all collections of scene
* \param scene_collection_skip: Don't remove base from this collection.
*/
-static bool collections_object_remove_ex(Main *bmain, ID *owner_id, Object *ob, const bool free_us,
- SceneCollection *scene_collection_skip)
+static bool scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us,
+ Collection *collection_skip)
{
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_BEGIN(owner_id, sc)
+ BKE_scene_remove_rigidbody_object(scene, ob);
+
+ FOREACH_SCENE_COLLECTION_BEGIN(scene, collection)
{
- if (sc != scene_collection_skip) {
- removed |= BKE_collection_object_remove(bmain, owner_id, sc, ob, free_us);
+ if (collection != collection_skip) {
+ removed |= collection_object_remove(bmain, collection, ob, free_us);
}
}
FOREACH_SCENE_COLLECTION_END;
+
+ BKE_main_collection_sync(bmain);
+
return removed;
}
/**
* Remove object from all collections of scene
*/
-bool BKE_collections_object_remove(Main *bmain, ID *owner_id, Object *ob, const bool free_us)
+bool BKE_scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us)
{
- return collections_object_remove_ex(bmain, owner_id, ob, free_us, NULL);
+ return scene_collections_object_remove(bmain, scene, ob, free_us, NULL);
}
-/**
- * Move object from a collection into another
- *
- * If source collection is NULL move it from all the existing collections.
+/*
+ * Remove all NULL objects from non-scene collections.
+ * This is used for library remapping, where these pointers have been set to NULL.
+ * Otherwise this should never happen.
*/
-void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob)
+void BKE_collections_object_remove_nulls(Main *bmain)
{
- /* In both cases we first add the object, then remove it from the other collections.
- * Otherwise we lose the original base and whether it was active and selected. */
- if (sc_src != NULL) {
- if (BKE_collection_object_add(owner_id, sc_dst, ob)) {
- BKE_collection_object_remove(NULL, owner_id, sc_src, ob, false);
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (!BKE_collection_is_in_scene(collection)) {
+ bool changed = false;
+
+ for (CollectionObject *cob = collection->gobject.first, *cob_next = NULL; cob; cob = cob_next) {
+ cob_next = cob->next;
+
+ if (cob->ob == NULL) {
+ BLI_freelinkN(&collection->gobject, cob);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ BKE_collection_object_cache_free(collection);
+ }
}
}
- else {
- /* Adding will fail if object is already in collection.
- * However we still need to remove it from the other collections. */
- BKE_collection_object_add(owner_id, sc_dst, ob);
- collections_object_remove_ex(NULL, owner_id, ob, false, sc_dst);
- }
}
-/**
- * Whether the object is directly inside the collection.
+/*
+ * Remove all NULL children from parent objects of changed old_collection.
+ * This is used for library remapping, where these pointers have been set to NULL.
+ * Otherwise this should never happen.
*/
-bool BKE_collection_object_exists(struct SceneCollection *scene_collection, struct Object *ob)
+void BKE_collections_child_remove_nulls(Main *bmain, Collection *old_collection)
{
- if (BLI_findptr(&scene_collection->objects, ob, offsetof(LinkData, data))) {
- return true;
- }
- return false;
-}
+ bool changed = false;
-static SceneCollection *scene_collection_from_index_recursive(SceneCollection *scene_collection, const int index, int *index_current)
-{
- if (index == (*index_current)) {
- return scene_collection;
+ for (CollectionChild *child = old_collection->children.first; child; child = child->next) {
+ CollectionParent *cparent = collection_find_parent(child->collection, old_collection);
+ if (cparent) {
+ BLI_freelinkN(&child->collection->parents, cparent);
+ }
}
- (*index_current)++;
+ for (CollectionParent *cparent = old_collection->parents.first; cparent; cparent = cparent->next) {
+ Collection *parent = cparent->collection;
- for (SceneCollection *scene_collection_iter = scene_collection->scene_collections.first;
- scene_collection_iter != NULL;
- scene_collection_iter = scene_collection_iter->next)
- {
- SceneCollection *nested = scene_collection_from_index_recursive(scene_collection_iter, index, index_current);
- if (nested != NULL) {
- return nested;
+ for (CollectionChild *child = parent->children.first, *child_next = NULL; child; child = child_next) {
+ child_next = child->next;
+
+ if (child->collection == NULL) {
+ BLI_freelinkN(&parent->children, child);
+ changed = true;
+ }
}
}
- return NULL;
-}
-/**
- * Return Scene Collection for a given index.
- *
- * The index is calculated from top to bottom counting the children before the siblings.
- */
-SceneCollection *BKE_collection_from_index(Scene *scene, const int index)
-{
- int index_current = 0;
- SceneCollection *master_collection = BKE_collection_master(&scene->id);
- return scene_collection_from_index_recursive(master_collection, index, &index_current);
-}
+ BLI_freelistN(&old_collection->parents);
-static void layer_collection_sync(LayerCollection *lc_dst, LayerCollection *lc_src)
-{
- lc_dst->flag = lc_src->flag;
-
- /* Continue recursively. */
- LayerCollection *lc_dst_nested, *lc_src_nested;
- lc_src_nested = lc_src->layer_collections.first;
- for (lc_dst_nested = lc_dst->layer_collections.first;
- lc_dst_nested && lc_src_nested;
- lc_dst_nested = lc_dst_nested->next, lc_src_nested = lc_src_nested->next)
- {
- layer_collection_sync(lc_dst_nested, lc_src_nested);
+ if (changed) {
+ BKE_main_collection_sync(bmain);
}
}
/**
- * Select all the objects in this SceneCollection (and its nested collections) for this ViewLayer.
- * Return true if any object was selected.
+ * Move object from a collection into another
+ *
+ * If source collection is NULL move it from all the existing collections.
*/
-bool BKE_collection_objects_select(ViewLayer *view_layer, SceneCollection *scene_collection)
+void BKE_collection_object_move(Main *bmain, Scene *scene, Collection *collection_dst, Collection *collection_src, Object *ob)
{
- LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(view_layer, scene_collection);
- if (layer_collection != NULL) {
- BKE_layer_collection_objects_select(layer_collection);
- return true;
+ /* In both cases we first add the object, then remove it from the other collections.
+ * Otherwise we lose the original base and whether it was active and selected. */
+ if (collection_src != NULL) {
+ if (BKE_collection_object_add(bmain, collection_dst, ob)) {
+ BKE_collection_object_remove(bmain, collection_src, ob, false);
+ }
}
else {
- /* Slower approach, we need to iterate over all the objects and for each one we see if there is a base. */
- bool changed = false;
- for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
- Base *base = BKE_view_layer_base_find(view_layer, link->data);
- if (base != NULL) {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- base->flag |= BASE_SELECTED;
- changed = true;
- }
- }
- }
- return changed;
+ /* Adding will fail if object is already in collection.
+ * However we still need to remove it from the other collections. */
+ BKE_collection_object_add(bmain, collection_dst, ob);
+ scene_collections_object_remove(bmain, scene, ob, false, collection_dst);
}
}
-/**
- * Leave only the master collection in, remove everything else.
- * @param group
- */
-static void collection_group_cleanup(Group *group)
+/***************** Collection Scene Membership ****************/
+
+bool BKE_collection_is_in_scene(Collection *collection)
{
- /* Unlink all the LayerCollections. */
- while (group->view_layer->layer_collections.last != NULL) {
- BKE_collection_unlink(group->view_layer, group->view_layer->layer_collections.last);
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ return true;
+ }
+
+ for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ if (BKE_collection_is_in_scene(cparent->collection)) {
+ return true;
+ }
}
- /* Remove all the SceneCollections but the master. */
- collection_free(group->collection, false);
+ return false;
}
-/**
- * Create a group from a collection
- *
- * Any ViewLayer that may have this the related SceneCollection linked is converted
- * to a Group Collection.
- */
-Group *BKE_collection_group_create(Main *bmain, Scene *scene, LayerCollection *lc_src)
+void BKE_collections_after_lib_link(Main *bmain)
{
- SceneCollection *sc_dst, *sc_src = lc_src->scene_collection;
- LayerCollection *lc_dst;
+ /* Update view layer collections to match any changes in linked
+ * collections after file load. */
+ BKE_main_collection_sync(bmain);
+}
- /* The master collection can't be converted. */
- if (sc_src == BKE_collection_master(&scene->id)) {
- return NULL;
- }
+/********************** Collection Children *******************/
- /* If a sub-collection of sc_dst is directly linked into a ViewLayer we can't convert. */
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
- for (LayerCollection *lc_child = view_layer->layer_collections.first; lc_child; lc_child = lc_child->next) {
- if (is_collection_in_tree(lc_child->scene_collection, sc_src)) {
- return NULL;
- }
- }
+bool BKE_collection_find_cycle(Collection *new_ancestor, Collection *collection)
+{
+ if (collection == new_ancestor) {
+ return true;
}
- /* Create new group with the same data as the original collection. */
- Group *group = BKE_group_add(bmain, sc_src->name);
- collection_group_cleanup(group);
-
- sc_dst = BKE_collection_add(&group->id, NULL, COLLECTION_TYPE_GROUP_INTERNAL, sc_src->name);
- BKE_collection_copy_data(sc_dst, sc_src, 0);
- FOREACH_SCENE_COLLECTION_BEGIN(&group->id, sc_group)
- {
- sc_group->type = COLLECTION_TYPE_GROUP_INTERNAL;
+ for (CollectionParent *parent = new_ancestor->parents.first; parent; parent = parent->next) {
+ if (BKE_collection_find_cycle(parent->collection, collection)) {
+ return true;
+ }
}
- FOREACH_SCENE_COLLECTION_END;
- lc_dst = BKE_collection_link(group->view_layer, sc_dst);
- layer_collection_sync(lc_dst, lc_src);
-
- return group;
+ return false;
}
-/* ---------------------------------------------------------------------- */
-/* Outliner drag and drop */
+static CollectionChild *collection_find_child(Collection *parent, Collection *collection)
+{
+ return BLI_findptr(&parent->children, collection, offsetof(CollectionChild, collection));
+}
-/**
- * Find and return the SceneCollection that has \a sc_child as one of its directly
- * nested SceneCollection.
- *
- * \param sc_parent Initial SceneCollection to look into recursively, usually the master collection
- */
-static SceneCollection *find_collection_parent(const SceneCollection *sc_child, SceneCollection *sc_parent)
+static bool collection_find_child_recursive(Collection *parent, Collection *collection)
{
- for (SceneCollection *sc_nested = sc_parent->scene_collections.first; sc_nested; sc_nested = sc_nested->next) {
- if (sc_nested == sc_child) {
- return sc_parent;
+ for (CollectionChild *child = parent->children.first; child; child = child->next) {
+ if (child->collection == collection) {
+ return true;
}
- SceneCollection *found = find_collection_parent(sc_child, sc_nested);
- if (found) {
- return found;
+ if (collection_find_child_recursive(child->collection, collection)) {
+ return true;
}
}
- return NULL;
+ return false;
}
-/**
- * Check if \a sc_reference is nested to \a sc_parent SceneCollection
- */
-static bool is_collection_in_tree(const SceneCollection *sc_reference, SceneCollection *sc_parent)
+static CollectionParent *collection_find_parent(Collection *child, Collection *collection)
{
- return find_collection_parent(sc_reference, sc_parent) != NULL;
+ return BLI_findptr(&child->parents, collection, offsetof(CollectionParent, collection));
}
-bool BKE_collection_move_above(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src)
+static bool collection_child_add(Collection *parent, Collection *collection, const int flag, const bool add_us)
{
- /* Find the SceneCollection the sc_src belongs to */
- SceneCollection *sc_master = master_collection_from_id(owner_id);
-
- /* Master Layer can't be moved around*/
- if (ELEM(sc_master, sc_src, sc_dst)) {
+ CollectionChild *child = collection_find_child(parent, collection);
+ if (child) {
return false;
}
-
- /* collection is already where we wanted it to be */
- if (sc_dst->prev == sc_src) {
+ if (BKE_collection_find_cycle(parent, collection)) {
return false;
}
- /* We can't move a collection fs the destiny collection
- * is nested to the source collection */
- if (is_collection_in_tree(sc_dst, sc_src)) {
- return false;
+ child = MEM_callocN(sizeof(CollectionChild), "CollectionChild");
+ child->collection = collection;
+ BLI_addtail(&parent->children, child);
+
+ /* Don't add parent links for depsgraph datablocks, these are not kept in sync. */
+ if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
+ CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), "CollectionParent");
+ cparent->collection = parent;
+ BLI_addtail(&collection->parents, cparent);
}
- SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
- SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master);
- BLI_assert(sc_src_parent);
- BLI_assert(sc_dst_parent);
+ if (add_us) {
+ id_us_plus(&collection->id);
+ }
- /* Remove sc_src from its parent */
- BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+ BKE_collection_object_cache_free(parent);
- /* Re-insert it where it belongs */
- BLI_insertlinkbefore(&sc_dst_parent->scene_collections, sc_dst, sc_src);
+ return true;
+}
+
+static bool collection_child_remove(Collection *parent, Collection *collection)
+{
+ CollectionChild *child = collection_find_child(parent, collection);
+ if (child == NULL) {
+ return false;
+ }
- /* Update the tree */
- BKE_layer_collection_resync(owner_id, sc_src_parent);
- BKE_layer_collection_resync(owner_id, sc_dst_parent);
+ CollectionParent *cparent = collection_find_parent(collection, parent);
+ BLI_freelinkN(&collection->parents, cparent);
+ BLI_freelinkN(&parent->children, child);
- /* Keep names unique. */
- collection_name_check(owner_id, sc_src);
+ id_us_min(&collection->id);
+
+ BKE_collection_object_cache_free(parent);
return true;
}
-bool BKE_collection_move_below(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src)
+bool BKE_collection_child_add(Main *bmain, Collection *parent, Collection *child)
{
- /* Find the SceneCollection the sc_src belongs to */
- SceneCollection *sc_master = master_collection_from_id(owner_id);
-
- /* Master Layer can't be moved around*/
- if (ELEM(sc_master, sc_src, sc_dst)) {
+ if (!collection_child_add(parent, child, 0, true)) {
return false;
}
- /* Collection is already where we wanted it to be */
- if (sc_dst->next == sc_src) {
- return false;
- }
+ BKE_main_collection_sync(bmain);
+ return true;
+}
- /* We can't move a collection if the destiny collection
- * is nested to the source collection */
- if (is_collection_in_tree(sc_dst, sc_src)) {
+bool BKE_collection_child_remove(Main *bmain, Collection *parent, Collection *child)
+{
+ if (!collection_child_remove(parent, child)) {
return false;
}
- SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
- SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master);
- BLI_assert(sc_src_parent);
- BLI_assert(sc_dst_parent);
+ BKE_main_collection_sync(bmain);
+ return true;
+}
- /* Remove sc_src from its parent */
- BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+/********************** Collection index *********************/
- /* Re-insert it where it belongs */
- BLI_insertlinkafter(&sc_dst_parent->scene_collections, sc_dst, sc_src);
+static Collection *collection_from_index_recursive(Collection *collection, const int index, int *index_current)
+{
+ if (index == (*index_current)) {
+ return collection;
+ }
- /* Update the tree */
- BKE_layer_collection_resync(owner_id, sc_src_parent);
- BKE_layer_collection_resync(owner_id, sc_dst_parent);
+ (*index_current)++;
- /* Keep names unique. */
- collection_name_check(owner_id, sc_src);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ Collection *nested = collection_from_index_recursive(child->collection, index, index_current);
+ if (nested != NULL) {
+ return nested;
+ }
+ }
+ return NULL;
+}
- return true;
+/**
+ * Return Scene Collection for a given index.
+ *
+ * The index is calculated from top to bottom counting the children before the siblings.
+ */
+Collection *BKE_collection_from_index(Scene *scene, const int index)
+{
+ int index_current = 0;
+ Collection *master_collection = BKE_collection_master(scene);
+ return collection_from_index_recursive(master_collection, index, &index_current);
}
-bool BKE_collection_move_into(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src)
+static bool collection_objects_select(ViewLayer *view_layer, Collection *collection, bool deselect)
{
- /* Find the SceneCollection the sc_src belongs to */
- SceneCollection *sc_master = master_collection_from_id(owner_id);
- if (sc_src == sc_master) {
+ bool changed = false;
+
+ if (collection->flag & COLLECTION_RESTRICT_SELECT) {
return false;
}
- /* We can't move a collection if the destiny collection
- * is nested to the source collection */
- if (is_collection_in_tree(sc_dst, sc_src)) {
- return false;
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Base *base = BKE_view_layer_base_find(view_layer, cob->ob);
+
+ if (base) {
+ if (deselect) {
+ if (base->flag & BASE_SELECTED) {
+ base->flag &= ~BASE_SELECTED;
+ changed = true;
+ }
+ }
+ else {
+ if ((base->flag & BASE_SELECTABLED) && !(base->flag & BASE_SELECTED)) {
+ base->flag |= BASE_SELECTED;
+ changed = true;
+ }
+ }
+ }
+ }
+
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ if (collection_objects_select(view_layer, collection, deselect)) {
+ changed = true;
+ }
}
- SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
- BLI_assert(sc_src_parent);
+ return changed;
+}
- /* collection is already where we wanted it to be */
- if (sc_dst->scene_collections.last == sc_src) {
+/**
+ * Select all the objects in this Collection (and its nested collections) for this ViewLayer.
+ * Return true if any object was selected.
+ */
+bool BKE_collection_objects_select(ViewLayer *view_layer, Collection *collection, bool deselect)
+{
+ LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(view_layer, collection);
+
+ if (layer_collection != NULL) {
+ return BKE_layer_collection_objects_select(view_layer, layer_collection, deselect);
+ }
+ else {
+ return collection_objects_select(view_layer, collection, deselect);
+ }
+}
+
+/***************** Collection move (outliner drag & drop) *********************/
+
+bool BKE_collection_move(Main *bmain,
+ Collection *to_parent,
+ Collection *from_parent,
+ Collection *relative,
+ bool relative_after,
+ Collection *collection)
+{
+ if (collection->flag & COLLECTION_IS_MASTER) {
return false;
}
+ if (BKE_collection_find_cycle(to_parent, collection)) {
+ return false;
+ }
+
+ /* Move to new parent collection */
+ if (from_parent) {
+ collection_child_remove(from_parent, collection);
+ }
+
+ collection_child_add(to_parent, collection, 0, true);
+
+ /* Move to specified location under parent. */
+ if (relative) {
+ CollectionChild *child = collection_find_child(to_parent, collection);
+ CollectionChild *relative_child = collection_find_child(to_parent, relative);
- /* Remove sc_src from it */
- BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+ if (relative_child) {
+ BLI_remlink(&to_parent->children, child);
- /* Insert sc_src into sc_dst */
- BLI_addtail(&sc_dst->scene_collections, sc_src);
+ if (relative_after) {
+ BLI_insertlinkafter(&to_parent->children, relative_child, child);
+ }
+ else {
+ BLI_insertlinkbefore(&to_parent->children, relative_child, child);
+ }
- /* Update the tree */
- BKE_layer_collection_resync(owner_id, sc_src_parent);
- BKE_layer_collection_resync(owner_id, sc_dst);
+ BKE_collection_object_cache_free(to_parent);
+ }
+ }
- /* Keep names unique. */
- collection_name_check(owner_id, sc_src);
+ BKE_main_collection_sync(bmain);
return true;
}
-/* ---------------------------------------------------------------------- */
-/* Iteractors */
+/**************************** Iterators ******************************/
+
/* scene collection iteractor */
-typedef struct SceneCollectionsIteratorData {
- ID *owner_id;
+typedef struct CollectionsIteratorData {
+ Scene *scene;
void **array;
int tot, cur;
-} SceneCollectionsIteratorData;
+} CollectionsIteratorData;
-static void scene_collection_callback(SceneCollection *sc, BKE_scene_collections_Cb callback, void *data)
+static void scene_collection_callback(Collection *collection, BKE_scene_collections_Cb callback, void *data)
{
- callback(sc, data);
+ callback(collection, data);
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- scene_collection_callback(nsc, callback, data);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ scene_collection_callback(child->collection, callback, data);
}
}
-static void scene_collections_count(SceneCollection *UNUSED(sc), void *data)
+static void scene_collections_count(Collection *UNUSED(collection), void *data)
{
int *tot = data;
(*tot)++;
}
-static void scene_collections_build_array(SceneCollection *sc, void *data)
+static void scene_collections_build_array(Collection *collection, void *data)
{
- SceneCollection ***array = data;
- **array = sc;
+ Collection ***array = data;
+ **array = collection;
(*array)++;
}
-static void scene_collections_array(ID *owner_id, SceneCollection ***collections_array, int *tot)
+static void scene_collections_array(Scene *scene, Collection ***collections_array, int *tot)
{
- SceneCollection *sc;
- SceneCollection **array;
+ Collection *collection;
+ Collection **array;
*collections_array = NULL;
*tot = 0;
- if (owner_id == NULL) {
+ if (scene == NULL) {
return;
}
- sc = master_collection_from_id(owner_id);
- BLI_assert(sc != NULL);
- scene_collection_callback(sc, scene_collections_count, tot);
+ collection = BKE_collection_master(scene);
+ BLI_assert(collection != NULL);
+ scene_collection_callback(collection, scene_collections_count, tot);
if (*tot == 0)
return;
- *collections_array = array = MEM_mallocN(sizeof(SceneCollection *) * (*tot), "SceneCollectionArray");
- scene_collection_callback(sc, scene_collections_build_array, &array);
+ *collections_array = array = MEM_mallocN(sizeof(Collection *) * (*tot), "CollectionArray");
+ scene_collection_callback(collection, scene_collections_build_array, &array);
}
/**
@@ -873,14 +1064,14 @@ static void scene_collections_array(ID *owner_id, SceneCollection ***collections
*/
void BKE_scene_collections_iterator_begin(BLI_Iterator *iter, void *data_in)
{
- ID *owner_id = data_in;
- SceneCollectionsIteratorData *data = MEM_callocN(sizeof(SceneCollectionsIteratorData), __func__);
+ Scene *scene = data_in;
+ CollectionsIteratorData *data = MEM_callocN(sizeof(CollectionsIteratorData), __func__);
- data->owner_id = owner_id;
+ data->scene = scene;
iter->data = data;
iter->valid = true;
- scene_collections_array(owner_id, (SceneCollection ***)&data->array, &data->tot);
+ scene_collections_array(scene, (Collection ***)&data->array, &data->tot);
BLI_assert(data->tot != 0);
data->cur = 0;
@@ -889,7 +1080,7 @@ void BKE_scene_collections_iterator_begin(BLI_Iterator *iter, void *data_in)
void BKE_scene_collections_iterator_next(struct BLI_Iterator *iter)
{
- SceneCollectionsIteratorData *data = iter->data;
+ CollectionsIteratorData *data = iter->data;
if (++data->cur < data->tot) {
iter->current = data->array[data->cur];
@@ -901,7 +1092,7 @@ void BKE_scene_collections_iterator_next(struct BLI_Iterator *iter)
void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter)
{
- SceneCollectionsIteratorData *data = iter->data;
+ CollectionsIteratorData *data = iter->data;
if (data) {
if (data->array) {
@@ -917,7 +1108,7 @@ void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter)
typedef struct SceneObjectsIteratorData {
GSet *visited;
- LinkData *link_next;
+ CollectionObject *cob_next;
BLI_Iterator scene_collection_iter;
} SceneObjectsIteratorData;
@@ -933,9 +1124,9 @@ void BKE_scene_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
/* we wrap the scenecollection iterator here to go over the scene collections */
BKE_scene_collections_iterator_begin(&data->scene_collection_iter, scene);
- SceneCollection *sc = data->scene_collection_iter.current;
- if (sc->objects.first != NULL) {
- iter->current = ((LinkData *)sc->objects.first)->data;
+ Collection *collection = data->scene_collection_iter.current;
+ if (collection->gobject.first != NULL) {
+ iter->current = ((CollectionObject *)collection->gobject.first)->ob;
}
else {
BKE_scene_objects_iterator_next(iter);
@@ -945,14 +1136,14 @@ void BKE_scene_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
/**
* Gets the first unique object in the sequence
*/
-static LinkData *object_base_unique(GSet *gs, LinkData *link)
+static CollectionObject *object_base_unique(GSet *gs, CollectionObject *cob)
{
- for (; link != NULL; link = link->next) {
- Object *ob = link->data;
+ for (; cob != NULL; cob = cob->next) {
+ Object *ob = cob->ob;
void **ob_key_p;
if (!BLI_gset_ensure_p_ex(gs, ob, &ob_key_p)) {
*ob_key_p = ob;
- return link;
+ return cob;
}
}
return NULL;
@@ -961,23 +1152,23 @@ static LinkData *object_base_unique(GSet *gs, LinkData *link)
void BKE_scene_objects_iterator_next(BLI_Iterator *iter)
{
SceneObjectsIteratorData *data = iter->data;
- LinkData *link = data->link_next ? object_base_unique(data->visited, data->link_next) : NULL;
+ CollectionObject *cob = data->cob_next ? object_base_unique(data->visited, data->cob_next) : NULL;
- if (link) {
- data->link_next = link->next;
- iter->current = link->data;
+ if (cob) {
+ data->cob_next = cob->next;
+ iter->current = cob->ob;
}
else {
- /* if this is the last object of this ListBase look at the next SceneCollection */
- SceneCollection *sc;
+ /* if this is the last object of this ListBase look at the next Collection */
+ Collection *collection;
BKE_scene_collections_iterator_next(&data->scene_collection_iter);
do {
- sc = data->scene_collection_iter.current;
+ collection = data->scene_collection_iter.current;
/* get the first unique object of this collection */
- LinkData *new_link = object_base_unique(data->visited, sc->objects.first);
- if (new_link) {
- data->link_next = new_link->next;
- iter->current = new_link->data;
+ CollectionObject *new_cob = object_base_unique(data->visited, collection->gobject.first);
+ if (new_cob) {
+ data->cob_next = new_cob->next;
+ iter->current = new_cob->ob;
return;
}
BKE_scene_collections_iterator_next(&data->scene_collection_iter);
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index ee3c38b9282..b23b1b2dbed 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -46,8 +46,8 @@
#include "BLI_edgehash.h"
#include "BKE_cloth.h"
+#include "BKE_collection.h"
#include "BKE_effect.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_modifier.h"
#include "BKE_scene.h"
@@ -503,20 +503,20 @@ 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) {
- Group *group= ob->dup_group;
+ Collection *collection= ob->dup_group;
/* add objects */
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collision_object(objs, numobj, maxobj, object, self, level+1, modifier_type);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
// return all collision objects in scene
// collision object will exclude self
-Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
+Object **get_collisionobjects_ext(Scene *scene, Object *self, Collection *collection, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
{
Object **objs;
unsigned int numobj= 0, maxobj= 100;
@@ -525,13 +525,13 @@ Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsi
objs= MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray");
/* gather all collision objects */
- if (group) {
- /* use specified group */
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
+ if (collection) {
+ /* use specified collection */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collision_object(&objs, &numobj, &maxobj, object, self, level, modifier_type);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
else {
Scene *sce_iter;
@@ -549,11 +549,11 @@ Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsi
return objs;
}
-Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type)
+Object **get_collisionobjects(Scene *scene, Object *self, Collection *collection, unsigned int *numcollobj, unsigned int modifier_type)
{
/* Need to check for active layers, too.
Otherwise this check fails if the objects are not on the same layer - DG */
- return get_collisionobjects_ext(scene, self, group, numcollobj, modifier_type, true);
+ return get_collisionobjects_ext(scene, self, collection, numcollobj, modifier_type, true);
}
static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, int level)
@@ -579,30 +579,30 @@ static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self,
BLI_addtail(*objs, col);
}
- /* objects in dupli groups, one level only for now */
+ /* objects in dupli collection, one level only for now */
if (ob->dup_group && level == 0) {
- Group *group= ob->dup_group;
+ Collection *collection= ob->dup_group;
/* add objects */
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collider_cache_object(objs, object, self, level+1);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
-ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
+ListBase *get_collider_cache(Scene *scene, Object *self, Collection *collection)
{
ListBase *objs= NULL;
/* add object in same layer in scene */
- if (group) {
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
+ if (collection) {
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collider_cache_object(&objs, object, self, 0);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
else {
Scene *sce_iter;
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index f420fd974cd..6314486d809 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -30,6 +30,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_group_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -949,7 +950,7 @@ LayerCollection *CTX_data_layer_collection(const bContext *C)
LayerCollection *layer_collection;
if (ctx_data_pointer_verify(C, "layer_collection", (void *)&layer_collection)) {
- if (BKE_view_layer_has_collection(view_layer, layer_collection->scene_collection)) {
+ if (BKE_view_layer_has_collection(view_layer, layer_collection->collection)) {
return layer_collection;
}
}
@@ -958,21 +959,21 @@ LayerCollection *CTX_data_layer_collection(const bContext *C)
return BKE_layer_collection_get_active(view_layer);
}
-SceneCollection *CTX_data_scene_collection(const bContext *C)
+Collection *CTX_data_collection(const bContext *C)
{
- SceneCollection *scene_collection;
- if (ctx_data_pointer_verify(C, "scene_collection", (void *)&scene_collection)) {
- return scene_collection;
+ Collection *collection;
+ if (ctx_data_pointer_verify(C, "collection", (void *)&collection)) {
+ return collection;
}
LayerCollection *layer_collection = CTX_data_layer_collection(C);
if (layer_collection) {
- return layer_collection->scene_collection;
+ return layer_collection->collection;
}
/* fallback */
Scene *scene = CTX_data_scene(C);
- return BKE_collection_master(&scene->id);
+ return BKE_collection_master(scene);
}
int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob, const eObjectMode object_mode)
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 848e5fbe5f8..ee2ece48325 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -43,7 +43,7 @@
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_dynamicpaint_types.h"
-#include "DNA_group_types.h" /*GroupObject*/
+#include "DNA_group_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -55,6 +55,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_bvhutils.h" /* bvh tree */
+#include "BKE_collection.h"
#include "BKE_colorband.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_constraint.h"
@@ -491,17 +492,12 @@ static void scene_setSubframe(Scene *scene, float subframe)
static int surface_getBrushFlags(DynamicPaintSurface *surface, const ViewLayer *view_layer)
{
- Base *base = NULL;
+ Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, surface->brush_group);
Object *brushObj = NULL;
ModifierData *md = NULL;
int flags = 0;
- if (surface->brush_group)
- base = FIRSTBASE(surface->brush_group->view_layer);
- else
- base = FIRSTBASE(view_layer);
-
while (base) {
brushObj = NULL;
@@ -5911,21 +5907,15 @@ static int dynamicPaint_doStep(struct Depsgraph *depsgraph, Scene *scene, Object
* Loop through surface's target paint objects and do painting
*/
{
- Base *base = NULL;
Object *brushObj = NULL;
ModifierData *md = NULL;
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, surface->brush_group);
/* backup current scene frame */
int scene_frame = scene->r.cfra;
float scene_subframe = scene->r.subframe;
- /* either from group or from all objects */
- if (surface->brush_group)
- base = FIRSTBASE(surface->brush_group->view_layer);
- else
- base = FIRSTBASE(view_layer);
-
while (base) {
brushObj = NULL;
/* select object */
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 8bdc74edffd..00c1c82bae8 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -57,6 +57,7 @@
#include "PIL_time.h"
#include "BKE_anim.h" /* needed for where_on_path */
+#include "BKE_collection.h"
#include "BKE_collision.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
@@ -64,7 +65,6 @@
#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"
@@ -86,7 +86,7 @@
#include <string.h>
#endif // WITH_MOD_FLUID
-EffectorWeights *BKE_add_effector_weights(Group *group)
+EffectorWeights *BKE_add_effector_weights(Collection *collection)
{
EffectorWeights *weights = MEM_callocN(sizeof(EffectorWeights), "EffectorWeights");
int i;
@@ -96,7 +96,7 @@ EffectorWeights *BKE_add_effector_weights(Group *group)
weights->global_gravity = 1.0f;
- weights->group = group;
+ weights->group = collection;
return weights;
}
@@ -215,23 +215,10 @@ ListBase *pdInitEffectors(
struct Depsgraph *depsgraph, Scene *scene, Object *ob_src, ParticleSystem *psys_src,
EffectorWeights *weights, bool for_simulation)
{
- ViewLayer *view_layer;
- Base *base;
+ Base *base = BKE_collection_or_layer_objects(depsgraph, scene, NULL, weights->group);
ListBase *effectors = NULL;
- if (weights->group) {
- view_layer = weights->group->view_layer;
- }
- /* TODO(mai): the check for view_layer shouldnt be needed, remove when render engine api is updated for this */
- else if (depsgraph && DEG_get_evaluated_view_layer(depsgraph)) {
- view_layer = DEG_get_evaluated_view_layer(depsgraph);
- }
- else {
- /* depsgraph is NULL during deg build */
- view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
- }
-
- for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ for (; base; base = base->next) {
if ((base->flag & BASE_VISIBLED) == 0) {
continue;
}
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index b656d2cf7c0..d439b5e7a6e 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -83,7 +83,7 @@ void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user)
BLI_freelistN(&config->modules);
}
-void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config, const int flag)
+void BKE_freestyle_config_copy(FreestyleConfig *new_config, const FreestyleConfig *config, const int flag)
{
FreestyleLineSet *lineset, *new_lineset;
FreestyleModuleConfig *module, *new_module;
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
deleted file mode 100644
index f2c9bfdd974..00000000000
--- a/source/blender/blenkernel/intern/group.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/group.c
- * \ingroup bke
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_group_types.h"
-#include "DNA_material_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_particle_types.h"
-
-#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"
-
-#include "DEG_depsgraph.h"
-
-/** Free (or release) any data used by this group (does not free the group itself). */
-void BKE_group_free(Group *group)
-{
- /* No animdata here. */
- BKE_previewimg_free(&group->preview);
-
- if (group->view_layer != NULL) {
- BKE_view_layer_free(group->view_layer);
- group->view_layer = NULL;
- }
-
- 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 = 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, NULL);
- BKE_collection_link(group->view_layer, defaut_collection);
-}
-
-Group *BKE_group_add(Main *bmain, const char *name)
-{
- Group *group;
-
- group = BKE_libblock_alloc(bmain, ID_GR, name, 0);
- id_us_min(&group->id);
- id_us_ensure_real(&group->id);
- group->layer = (1 << 20) - 1;
-
- group->preview = NULL;
- BKE_group_init(group);
- return group;
-}
-
-/**
- * Only copy internal data of Group 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.
- *
- * WARNING! This function will not handle ID user count!
- *
- * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
- */
-void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *group_src, const int flag)
-{
- /* 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 */
- BKE_previewimg_id_copy(&group_dst->id, &group_src->id);
- }
- 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);
-
- group_dst->view_layer = MEM_dupallocN(group_src->view_layer);
- 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)
-{
- Group *group_copy;
- BKE_id_copy_ex(bmain, &group->id, (ID **)&group_copy, 0, false);
- return group_copy;
-}
-
-void BKE_group_make_local(Main *bmain, Group *group, const bool lib_local)
-{
- BKE_id_make_local_generic(bmain, &group->id, true, lib_local);
-}
-
-/* external */
-static bool group_object_add_internal(Group *group, Object *ob)
-{
- if (group == NULL || ob == NULL) {
- return false;
- }
-
- /* 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;
- }
-
- id_us_ensure_real(&ob->id);
- return true;
-}
-
-bool BKE_group_object_add(Group *group, Object *object)
-{
- if (group_object_add_internal(group, object)) {
- if ((object->flag & OB_FROMGROUP) == 0) {
- object->flag |= OB_FROMGROUP;
- }
- return true;
- }
- else {
- return false;
- }
-}
-
-/* also used for (ob == NULL) */
-static bool group_object_unlink_internal(Group *group, Object *ob)
-{
- if (group == NULL) {
- return false;
- }
-
- 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)
-{
- if (object->dup_group) {
- Group *dup_group = object->dup_group;
- if ((dup_group->id.tag & LIB_TAG_DOIT) == 0) {
- /* Cycle already exists in groups, let's prevent further crappyness */
- return true;
- }
- /* flag the object to identify cyclic dependencies in further dupli groups */
- dup_group->id.tag &= ~LIB_TAG_DOIT;
-
- if (dup_group == group)
- return true;
- else {
- FOREACH_GROUP_OBJECT_BEGIN(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 */
- dup_group->id.tag |= LIB_TAG_DOIT;
- }
-
- return false;
-}
-
-bool BKE_group_object_cyclic_check(Main *bmain, Object *object, Group *group)
-{
- /* first flag all groups */
- BKE_main_id_tag_listbase(&bmain->group, LIB_TAG_DOIT, true);
-
- return group_object_cyclic_check_internal(object, group);
-}
-
-bool BKE_group_object_unlink(Group *group, Object *object)
-{
- if (group_object_unlink_internal(group, object)) {
- /* object can be NULL */
- if (object && BKE_group_object_find(NULL, object) == NULL) {
- object->flag &= ~OB_FROMGROUP;
- }
- return true;
- }
- else {
- return false;
- }
-}
-
-bool BKE_group_object_exists(Group *group, Object *ob)
-{
- if (group == NULL || ob == NULL) {
- return false;
- }
- else {
- return (BLI_findptr(&group->view_layer->object_bases, ob, offsetof(Base, object)));
- }
-}
-
-Group *BKE_group_object_find(Group *group, Object *ob)
-{
- if (group)
- group = group->id.next;
- else
- group = G.main->group.first;
-
- while (group) {
- if (BKE_group_object_exists(group, ob))
- return group;
- group = group->id.next;
- }
- return NULL;
-}
-
-bool BKE_group_is_animated(Group *group, Object *UNUSED(parent))
-{
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- if (object->proxy) {
- return true;
- }
- }
- FOREACH_GROUP_OBJECT_END;
- return false;
-}
-
-#if 0 // add back when timeoffset & animsys work again
-/* only replaces object strips or action when parent nla instructs it */
-/* keep checking nla.c though, in case internal structure of strip changes */
-static void group_replaces_nla(Object *parent, Object *target, char mode)
-{
- static ListBase nlastrips = {NULL, NULL};
- static bAction *action = NULL;
- static bool done = false;
- bActionStrip *strip, *nstrip;
-
- if (mode == 's') {
-
- for (strip = parent->nlastrips.first; strip; strip = strip->next) {
- if (strip->object == target) {
- if (done == 0) {
- /* clear nla & action from object */
- nlastrips = target->nlastrips;
- BLI_listbase_clear(&target->nlastrips);
- action = target->action;
- target->action = NULL;
- target->nlaflag |= OB_NLA_OVERRIDE;
- done = true;
- }
- nstrip = MEM_dupallocN(strip);
- BLI_addtail(&target->nlastrips, nstrip);
- }
- }
- }
- else if (mode == 'e') {
- if (done) {
- BLI_freelistN(&target->nlastrips);
- target->nlastrips = nlastrips;
- target->action = action;
-
- BLI_listbase_clear(&nlastrips); /* not needed, but yah... :) */
- action = NULL;
- done = false;
- }
- }
-}
-#endif
-
-/* puts all group members in local timing system, after this call
- * you can draw everything, leaves tags in objects to signal it needs further updating */
-
-/* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */
-void BKE_group_handle_recalc_and_update(struct Depsgraph *depsgraph, Scene *scene, Object *UNUSED(parent), Group *group)
-{
-#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
- * but when its enabled at some point it will need to be changed so as not to update so much - campbell */
-
- /* if animated group... */
- if (parent->nlastrips.first) {
- int cfrao;
-
- /* switch to local time */
- cfrao = scene->r.cfra;
-
- /* we need a DAG per group... */
- for (go = group->gobject.first; go; go = go->next) {
- if (go->ob && go->recalc) {
- go->ob->recalc = go->recalc;
-
- group_replaces_nla(parent, go->ob, 's');
- BKE_object_handle_update(depsgraph, scene, go->ob);
- group_replaces_nla(parent, go->ob, 'e');
-
- /* leave recalc tags in case group members are in normal scene */
- go->ob->recalc = go->recalc;
- }
- }
-
- /* restore */
- scene->r.cfra = cfrao;
- }
- else
-#endif
- {
- /* only do existing tags, as set by regular depsgraph */
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- if (object->id.recalc & ID_RECALC_ALL) {
- BKE_object_handle_update(depsgraph, scene, object);
- }
- }
- FOREACH_GROUP_OBJECT_END;
- }
-}
-
-/* ******** Dependency graph evaluation ******** */
-
-void BKE_group_eval_view_layers(struct Depsgraph *depsgraph,
- Group *group)
-{
- DEG_debug_print_eval(depsgraph, __func__, group->id.name, group);
- BKE_layer_eval_view_layer(depsgraph, &group->id, group->view_layer);
-}
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 61c05c2500d..8476bb6b66d 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -322,7 +322,7 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id)
ID_PRV_CASE(ID_IM, Image);
ID_PRV_CASE(ID_BR, Brush);
ID_PRV_CASE(ID_OB, Object);
- ID_PRV_CASE(ID_GR, Group);
+ ID_PRV_CASE(ID_GR, Collection);
ID_PRV_CASE(ID_SCE, Scene);
ID_PRV_CASE(ID_SCR, bScreen);
#undef ID_PRV_CASE
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index 487635f06ad..4860f5a896d 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -61,9 +61,9 @@ static IDType idtypes[] = {
{ ID_BR, "Brush", "brushes", BLT_I18NCONTEXT_ID_BRUSH, IDTYPE_FLAGS_ISLINKABLE },
{ ID_CA, "Camera", "cameras", BLT_I18NCONTEXT_ID_CAMERA, IDTYPE_FLAGS_ISLINKABLE },
{ ID_CF, "CacheFile", "cache_files", BLT_I18NCONTEXT_ID_CACHEFILE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_GR, "Collection", "collections", BLT_I18NCONTEXT_ID_COLLECTION, IDTYPE_FLAGS_ISLINKABLE },
{ ID_CU, "Curve", "curves", BLT_I18NCONTEXT_ID_CURVE, IDTYPE_FLAGS_ISLINKABLE },
{ ID_GD, "GPencil", "grease_pencil", BLT_I18NCONTEXT_ID_GPENCIL, IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */
- { ID_GR, "Group", "groups", BLT_I18NCONTEXT_ID_GROUP, IDTYPE_FLAGS_ISLINKABLE },
{ ID_IM, "Image", "images", BLT_I18NCONTEXT_ID_IMAGE, IDTYPE_FLAGS_ISLINKABLE },
{ ID_IP, "Ipo", "ipos", "", IDTYPE_FLAGS_ISLINKABLE }, /* deprecated */
{ ID_KE, "Key", "shape_keys", BLT_I18NCONTEXT_ID_SHAPEKEY, 0 },
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index da068802586..685c007da6b 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -31,12 +31,12 @@
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_string_utils.h"
+#include "BLI_threads.h"
#include "BLT_translation.h"
#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"
@@ -61,24 +61,51 @@
#include "MEM_guardedalloc.h"
+
/* prototype */
-struct EngineSettingsCB_Type;
-static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src);
-static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc);
-static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects);
-static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc);
-static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc);
static void object_bases_iterator_next(BLI_Iterator *iter, const int flag);
+
+/*********************** Layer Collections and bases *************************/
+
+static LayerCollection *layer_collection_add(ListBase *lb_parent, Collection *collection)
+{
+ LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
+ lc->collection = collection;
+ BLI_addtail(lb_parent, lc);
+
+ return lc;
+}
+
+static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc)
+{
+ if (lc == view_layer->active_collection) {
+ view_layer->active_collection = view_layer->layer_collections.first;
+ }
+
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ layer_collection_free(view_layer, nlc);
+ }
+
+ BLI_freelistN(&lc->layer_collections);
+}
+
+static Base *object_base_new(Object *ob)
+{
+ Base *base = MEM_callocN(sizeof(Base), "Object Base");
+ base->object = ob;
+ return base;
+}
+
+/********************************* View Layer ********************************/
+
+
/* RenderLayer */
/* Returns the default view layer to view in workspaces if there is
* none linked to the workspace yet. */
ViewLayer *BKE_view_layer_default_view(const Scene *scene)
{
- /* TODO: it makes more sense to have the Viewport layer as the default,
- * but this breaks view layer tests so change it later. */
-#if 0
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
if (!(view_layer->flag & VIEW_LAYER_RENDER)) {
return view_layer;
@@ -87,9 +114,6 @@ ViewLayer *BKE_view_layer_default_view(const Scene *scene)
BLI_assert(scene->view_layers.first);
return scene->view_layers.first;
-#else
- return BKE_view_layer_default_render(scene);
-#endif
}
/* Returns the default view layer to render if we need to render just one. */
@@ -123,7 +147,7 @@ ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const Scene *scene)
return scene->view_layers.first;
}
-static ViewLayer *view_layer_add(const char *name, SceneCollection *master_scene_collection)
+static ViewLayer *view_layer_add(const char *name)
{
if (!name) {
name = DATA_("View Layer");
@@ -134,9 +158,6 @@ static ViewLayer *view_layer_add(const char *name, SceneCollection *master_scene
BLI_strncpy_utf8(view_layer->name, name, sizeof(view_layer->name));
- /* 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 */
view_layer->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
@@ -152,8 +173,7 @@ static ViewLayer *view_layer_add(const char *name, SceneCollection *master_scene
*/
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);
+ ViewLayer *view_layer = view_layer_add(name);
BLI_addtail(&scene->view_layers, view_layer);
@@ -162,18 +182,8 @@ ViewLayer *BKE_view_layer_add(Scene *scene, const char *name)
&scene->view_layers, view_layer, DATA_("ViewLayer"), '.',
offsetof(ViewLayer, name), sizeof(view_layer->name));
- return view_layer;
-}
+ BKE_layer_collection_sync(scene, 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;
}
@@ -191,8 +201,12 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
BLI_freelistN(&view_layer->object_bases);
+ if (view_layer->object_bases_hash) {
+ BLI_ghash_free(view_layer->object_bases_hash, NULL, NULL);
+ }
+
for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- layer_collection_free(NULL, lc);
+ layer_collection_free(view_layer, lc);
}
BLI_freelistN(&view_layer->layer_collections);
@@ -235,22 +249,6 @@ 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) {
@@ -285,32 +283,43 @@ Object *BKE_view_layer_camera_find(ViewLayer *view_layer)
/**
* Find the ViewLayer a LayerCollection belongs to
*/
-ViewLayer *BKE_view_layer_find_from_collection(const ID *owner_id, LayerCollection *lc)
+ViewLayer *BKE_view_layer_find_from_collection(const Scene *scene, 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;
+ 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;
}
- default:
- BLI_assert(!"ID doesn't support scene layers");
- return NULL;
}
+
+ return NULL;
}
/* Base */
+static void view_layer_bases_hash_create(ViewLayer *view_layer)
+{
+ static ThreadMutex hash_lock = BLI_MUTEX_INITIALIZER;
+
+ if (!view_layer->object_bases_hash) {
+ BLI_mutex_lock(&hash_lock);
+
+ view_layer->object_bases_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ BLI_ghash_insert(view_layer->object_bases_hash, base->object, base);
+ }
+
+ BLI_mutex_unlock(&hash_lock);
+ }
+}
+
Base *BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
{
- return BLI_findptr(&view_layer->object_bases, ob, offsetof(Base, object));
+ if (!view_layer->object_bases_hash) {
+ view_layer_bases_hash_create(view_layer);
+ }
+
+ return BLI_ghash_lookup(view_layer->object_bases_hash, ob);
}
void BKE_view_layer_base_deselect_all(ViewLayer *view_layer)
@@ -330,134 +339,32 @@ void BKE_view_layer_base_select(struct ViewLayer *view_layer, Base *selbase)
}
}
-/****************************************************************************/
-/* Copying functions for datablocks that use ViewLayer/SceneCollection */
+/**************************** Copy View Layer and Layer Collections ***********************/
-/* Find the equivalent SceneCollection in the new tree */
-static SceneCollection *scene_collection_from_new_tree(
- SceneCollection *sc_reference, SceneCollection *sc_dst, SceneCollection *sc_src)
+static void layer_collections_copy_data(ListBase *layer_collections_dst, const ListBase *layer_collections_src)
{
- if (sc_src == sc_reference) {
- return sc_dst;
- }
+ BLI_duplicatelist(layer_collections_dst, layer_collections_src);
- 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_collection_sync_flags(
- LayerCollection *layer_collection_dst,
- const LayerCollection *layer_collection_src)
-{
- layer_collection_dst->flag = layer_collection_src->flag;
-
- layer_collections_sync_flags(&layer_collection_dst->layer_collections,
- &layer_collection_src->layer_collections);
-}
+ LayerCollection *layer_collection_dst = layer_collections_dst->first;
+ const LayerCollection *layer_collection_src = layer_collections_src->first;
-static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src)
-{
- BLI_assert(BLI_listbase_count(layer_collections_dst) == BLI_listbase_count(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_sync_flags(layer_collection_dst, layer_collection_src);
+ layer_collections_copy_data(&layer_collection_dst->layer_collections,
+ &layer_collection_src->layer_collections);
+
layer_collection_dst = layer_collection_dst->next;
layer_collection_src = layer_collection_src->next;
}
}
-static bool layer_collection_sync_if_match(
- ListBase *lb,
- const SceneCollection *scene_collection_dst,
- const SceneCollection *scene_collection_src)
-{
- for (LayerCollection *layer_collection = lb->first;
- layer_collection;
- layer_collection = layer_collection->next)
- {
- if (layer_collection->scene_collection == scene_collection_src) {
- LayerCollection *layer_collection_dst =
- BLI_findptr(
- lb,
- scene_collection_dst,
- offsetof(LayerCollection, scene_collection));
-
- if (layer_collection_dst != NULL) {
- layer_collection_sync_flags(layer_collection_dst, layer_collection);
- }
- return true;
- }
- else {
- if (layer_collection_sync_if_match(
- &layer_collection->layer_collections,
- scene_collection_dst,
- scene_collection_src))
- {
- return true;
- }
- }
- }
- return false;
-}
-
-/**
- * Sync sibling collections across all view layers
- *
- * Make sure every linked instance of \a scene_collection_dst has the same values
- * (flags, overrides, ...) as the corresponding scene_collection_src.
- *
- * \note expect scene_collection_dst to be scene_collection_src->next, and it also
- * expects both collections to have the same ammount of sub-collections.
- */
-void BKE_layer_collection_sync_flags(
- ID *owner_id,
- SceneCollection *scene_collection_dst,
- SceneCollection *scene_collection_src)
-{
- for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
- for (LayerCollection *layer_collection = view_layer->layer_collections.first;
- layer_collection;
- layer_collection = layer_collection->next)
- {
- layer_collection_sync_if_match(
- &layer_collection->layer_collections,
- scene_collection_dst,
- scene_collection_src);
- }
- }
-}
-
-/* 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,
+ Scene *UNUSED(scene_dst), const Scene *UNUSED(scene_src),
+ ViewLayer *view_layer_dst, const ViewLayer *view_layer_src,
const int flag)
{
if (view_layer_dst->id_properties != NULL) {
@@ -467,176 +374,16 @@ void BKE_view_layer_copy_data(
view_layer_dst->stats = NULL;
- /* 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);
+ /* Clear temporary data. */
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;
- }
- }
-
view_layer_dst->object_bases_array = NULL;
-}
-
-/**
- * Find and return the ListBase of LayerCollection that has \a lc_child as one of its directly
- * nested LayerCollection.
- *
- * \param lb_parent Initial ListBase of LayerCollection to look into recursively
- * usually the view layer's collection list
- */
-static ListBase *find_layer_collection_parent_list_base(ListBase *lb_parent, const LayerCollection *lc_child)
-{
- for (LayerCollection *lc_nested = lb_parent->first; lc_nested; lc_nested = lc_nested->next) {
- if (lc_nested == lc_child) {
- return lb_parent;
- }
+ view_layer_dst->object_bases_hash = NULL;
- ListBase *found = find_layer_collection_parent_list_base(&lc_nested->layer_collections, lc_child);
- if (found != NULL) {
- return found;
- }
- }
+ /* Copy layer collections and object bases. */
+ BLI_duplicatelist(&view_layer_dst->object_bases, &view_layer_src->object_bases);
+ layer_collections_copy_data(&view_layer_dst->layer_collections, &view_layer_src->layer_collections);
- return NULL;
-}
-
-/**
- * Makes a shallow copy of a LayerCollection
- *
- * Add a new collection in the same level as the old one (linking if necessary),
- * and copy all the collection data across them.
- */
-struct LayerCollection *BKE_layer_collection_duplicate(struct ID *owner_id, struct LayerCollection *layer_collection)
-{
- SceneCollection *scene_collection, *scene_collection_new;
-
- scene_collection = layer_collection->scene_collection;
- scene_collection_new = BKE_collection_duplicate(owner_id, scene_collection);
-
- LayerCollection *layer_collection_new = NULL;
-
- /* If the original layer_collection was directly linked to the view layer
- we need to link the new scene collection here as well. */
- for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
- if (BLI_findindex(&view_layer->layer_collections, layer_collection) != -1) {
- layer_collection_new = BKE_collection_link(view_layer, scene_collection_new);
- layer_collection_sync_flags(layer_collection_new, layer_collection);
-
- if (layer_collection_new != layer_collection->next) {
- BLI_remlink(&view_layer->layer_collections, layer_collection_new);
- BLI_insertlinkafter(&view_layer->layer_collections, layer_collection, layer_collection_new);
- }
- break;
- }
- }
-
- /* Otherwise just try to find the corresponding layer collection to return it back. */
- if (layer_collection_new == NULL) {
- for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
- ListBase *layer_collections_parent;
- layer_collections_parent = find_layer_collection_parent_list_base(
- &view_layer->layer_collections,
- layer_collection);
- if (layer_collections_parent != NULL) {
- layer_collection_new = BLI_findptr(
- layer_collections_parent,
- scene_collection_new,
- offsetof(LayerCollection, scene_collection));
- break;
- }
- }
- }
- return layer_collection_new;
-}
-
-static void view_layer_object_base_unref(ViewLayer *view_layer, Base *base)
-{
- base->refcount--;
-
- /* It only exists in the RenderLayer */
- if (base->refcount == 0) {
- if (view_layer->basact == base) {
- view_layer->basact = NULL;
- }
-
- BLI_remlink(&view_layer->object_bases, base);
- MEM_freeN(base);
- }
-}
-
-/**
- * Return the base if existent, or create it if necessary
- * Always bump the refcount
- */
-static Base *object_base_add(ViewLayer *view_layer, Object *ob)
-{
- Base *base;
- base = BKE_view_layer_base_find(view_layer, ob);
-
- if (base == NULL) {
- base = MEM_callocN(sizeof(Base), "Object Base");
-
- /* Do not bump user count, leave it for SceneCollections. */
- base->object = ob;
- BLI_addtail(&view_layer->object_bases, base);
- }
-
- base->refcount++;
- return base;
-}
-
-/* LayerCollection */
-
-static void layer_collection_objects_unpopulate(ViewLayer *view_layer, LayerCollection *lc)
-{
- if (view_layer) {
- for (LinkData *link = lc->object_bases.first; link; link = link->next) {
- view_layer_object_base_unref(view_layer, link->data);
- }
- }
-
- BLI_freelistN(&lc->object_bases);
-}
-
-/**
- * When freeing the entire ViewLayer at once we don't bother with unref
- * otherwise ViewLayer is passed to keep the syncing of the LayerCollection tree
- */
-static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc)
-{
- layer_collection_objects_unpopulate(view_layer, lc);
-
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- layer_collection_free(view_layer, nlc);
- }
-
- BLI_freelistN(&lc->layer_collections);
-}
-
-/**
- * Free (or release) LayerCollection from ViewLayer
- * (does not free the LayerCollection itself).
- */
-void BKE_layer_collection_free(ViewLayer *view_layer, LayerCollection *lc)
-{
- layer_collection_free(view_layer, lc);
+ // TODO: not always safe to free BKE_layer_collection_sync(scene_dst, view_layer_dst);
}
/* LayerCollection */
@@ -675,28 +422,46 @@ LayerCollection *BKE_layer_collection_from_index(ViewLayer *view_layer, const in
*/
LayerCollection *BKE_layer_collection_get_active(ViewLayer *view_layer)
{
- int i = 0;
- return collection_from_index(&view_layer->layer_collections, view_layer->active_collection, &i);
+ return view_layer->active_collection;
}
+/*
+ * Activate collection
+ */
+bool BKE_layer_collection_activate(ViewLayer *view_layer, LayerCollection *lc)
+{
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ return false;
+ }
+
+ view_layer->active_collection = lc;
+ return true;
+}
/**
- * Return layer collection to add new object(s).
- * Create one if none exists.
+ * Activate first parent collection
*/
-LayerCollection *BKE_layer_collection_get_active_ensure(Scene *scene, ViewLayer *view_layer)
+LayerCollection *BKE_layer_collection_activate_parent(ViewLayer *view_layer, LayerCollection *lc)
{
- LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
+ CollectionParent *parent = lc->collection->parents.first;
+
+ if (parent) {
+ lc = BKE_layer_collection_first_from_scene_collection(view_layer, parent->collection);
+ }
+ else {
+ lc = NULL;
+ }
+
+ if (lc && (lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ /* Don't activate excluded collections. */
+ return BKE_layer_collection_activate_parent(view_layer, lc);
+ }
- 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->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));
+ if (!lc) {
+ lc = view_layer->layer_collections.first;
}
+ view_layer->active_collection = lc;
return lc;
}
@@ -750,348 +515,208 @@ int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection
return index_from_collection(&view_layer->layer_collections, lc, &i);
}
-/**
- * Lookup the listbase that contains \a lc.
- */
-static ListBase *layer_collection_listbase_find(ListBase *lb, LayerCollection *lc)
-{
- for (LayerCollection *lc_iter = lb->first; lc_iter; lc_iter = lc_iter->next) {
- if (lc_iter == lc) {
- return lb;
+/*********************************** Syncing *********************************
+ *
+ * The layer collection tree mirrors the scene collection tree. Whenever that
+ * changes we need to synchronize them so that there is a corresponding layer
+ * collection for each collection. Note that the scene collection tree can
+ * contain link or override collections, and so this is also called on .blend
+ * file load to ensure any new or removed collections are synced.
+ *
+ * The view layer also contains a list of bases for each object that exists
+ * in at least one layer collection. That list is also synchronized here, and
+ * stores state like selection. */
+
+static void layer_collection_sync(ViewLayer *view_layer,
+ const ListBase *lb_scene,
+ ListBase *lb_layer,
+ ListBase *new_object_bases,
+ int parent_exclude,
+ int parent_restrict)
+{
+ /* TODO: support recovery after removal of intermediate collections, reordering, ..
+ * For local edits we can make editing operating do the appropriate thing, but for
+ * linking we can only sync after the fact. */
+
+ /* Remove layer collections that no longer have a corresponding scene collection. */
+ for (LayerCollection *lc = lb_layer->first; lc;) {
+ /* Note ID remap can set lc->collection to NULL when deleting collections. */
+ LayerCollection *lc_next = lc->next;
+ Collection *collection = (lc->collection) ? BLI_findptr(lb_scene, lc->collection, offsetof(CollectionChild, collection)) : NULL;
+
+ if (!collection) {
+ /* Free recursively. */
+ layer_collection_free(view_layer, lc);
+ BLI_freelinkN(lb_layer, lc);
}
- ListBase *lb_child_result;
- if ((lb_child_result = layer_collection_listbase_find(&lc_iter->layer_collections, lc))) {
- return lb_child_result;
- }
+ lc = lc_next;
}
- return NULL;
-}
+ /* Add layer collections for any new scene collections, and ensure order is the same. */
+ ListBase new_lb_layer = {NULL, NULL};
-#if 0
-/**
- * Lookup the listbase that contains \a sc.
- */
-static ListBase *scene_collection_listbase_find(ListBase *lb, SceneCollection *sc)
-{
- for (SceneCollection *sc_iter = lb->first; sc_iter; sc_iter = sc_iter->next) {
- if (sc_iter == sc) {
- return lb;
+ for (const CollectionChild *child = lb_scene->first; child; child = child->next) {
+ Collection *collection = child->collection;
+ LayerCollection *lc = BLI_findptr(lb_layer, collection, offsetof(LayerCollection, collection));
+
+ if (lc) {
+ BLI_remlink(lb_layer, lc);
+ BLI_addtail(&new_lb_layer, lc);
+ }
+ else {
+ lc = layer_collection_add(&new_lb_layer, collection);
+ lc->flag = parent_exclude;
}
- ListBase *lb_child_result;
- if ((lb_child_result = scene_collection_listbase_find(&sc_iter->scene_collections, sc))) {
- return lb_child_result;
+ /* Collection restrict is inherited. */
+ int child_restrict = parent_restrict;
+ if (!(collection->flag & COLLECTION_IS_MASTER)) {
+ child_restrict |= collection->flag;
}
- }
- return NULL;
-}
-#endif
+ /* Sync child collections. */
+ layer_collection_sync(view_layer, &collection->children, &lc->layer_collections, new_object_bases, lc->flag, child_restrict);
-/* ---------------------------------------------------------------------- */
-/* Outliner drag and drop */
+ /* Layer collection exclude is not inherited. */
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ continue;
+ }
-/**
- * Nest a LayerCollection into another one
- * Both collections must be from the same ViewLayer, return true if succeded.
- *
- * The LayerCollection will effectively be moved into the
- * new (nested) position. So all the settings, overrides, ... go with it, and
- * if the collection was directly linked to the ViewLayer it's then unlinked.
- *
- * For the other ViewLayers we simply resync the tree, without changing directly
- * linked collections (even if they link to the same SceneCollection)
- *
- * \param lc_src LayerCollection to nest into \a lc_dst
- * \param lc_dst LayerCollection to have \a lc_src inserted into
- */
+ /* Sync objects, except if collection was excluded. */
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Base *base = BLI_ghash_lookup(view_layer->object_bases_hash, cob->ob);
+
+ if (base) {
+ /* Move from old base list to new base list. Base might have already
+ * been moved to the new base list and the first/last test ensure that
+ * case also works. */
+ if (!ELEM(base, new_object_bases->first, new_object_bases->last)) {
+ BLI_remlink(&view_layer->object_bases, base);
+ BLI_addtail(new_object_bases, base);
+ }
+ }
+ else {
+ /* Create new base. */
+ base = object_base_new(cob->ob);
+ BLI_addtail(new_object_bases, base);
+ BLI_ghash_insert(view_layer->object_bases_hash, base->object, base);
+ }
-static void layer_collection_swap(
- ViewLayer *view_layer, ListBase *lb_a, ListBase *lb_b,
- LayerCollection *lc_a, LayerCollection *lc_b)
-{
- if (lb_a == NULL) {
- lb_a = layer_collection_listbase_find(&view_layer->layer_collections, lc_a);
- }
+ if ((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) {
+ base->flag |= BASE_VISIBLED | BASE_VISIBLE_VIEWPORT;
- if (lb_b == NULL) {
- lb_b = layer_collection_listbase_find(&view_layer->layer_collections, lc_b);
+ if ((child_restrict & COLLECTION_RESTRICT_SELECT) == 0) {
+ base->flag |= BASE_SELECTABLED;
+ }
+ }
+ if ((child_restrict & COLLECTION_RESTRICT_RENDER) == 0) {
+ base->flag |= BASE_VISIBLE_RENDER;
+ }
+ }
}
- BLI_assert(lb_a);
- BLI_assert(lb_b);
-
- BLI_listbases_swaplinks(lb_a, lb_b, lc_a, lc_b);
+ /* Replace layer collection list with new one. */
+ *lb_layer = new_lb_layer;
+ BLI_assert(BLI_listbase_count(lb_scene) == BLI_listbase_count(lb_layer));
}
/**
- * 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
+ * Update view layer collection tree from collections used in the scene.
+ * This is used when collections are removed or added, both while editing
+ * and on file loaded in case linked data changed or went missing.
*/
-bool BKE_layer_collection_move_into(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src)
+void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
{
- 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(owner_id, lc_dst))) {
- return false;
- }
-
- /* We can't nest the collection into itself */
- if (lc_src->scene_collection == lc_dst->scene_collection) {
- return false;
- }
-
- /* Collection is already where we wanted it to be */
- if (lc_dst->layer_collections.last == lc_src) {
- return false;
+ if (!scene->master_collection) {
+ /* Happens for old files that don't have versioning applied yet. */
+ return;
}
- /* Collection is already where we want it to be in the scene tree
- * but we want to swap it in the layer tree still */
- if (lc_dst->scene_collection->scene_collections.last == lc_src->scene_collection) {
- LayerCollection *lc_swap = lc_dst->layer_collections.last;
- layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_dst->layer_collections.last, lc_src);
-
- if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) {
- BKE_collection_unlink(view_layer, lc_swap);
- }
- return true;
- }
- else {
- LayerCollection *lc_temp;
- is_directly_linked = BLI_findindex(&view_layer->layer_collections, lc_src) != -1;
-
- if (!is_directly_linked) {
- /* lc_src will be invalid after BKE_collection_move_into!
- * so we swap it with lc_temp to preserve its settings */
- lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection);
- layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src);
- }
+ /* Free cache. */
+ MEM_SAFE_FREE(view_layer->object_bases_array);
- 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);
- BKE_collection_unlink(view_layer, lc_temp);
- }
- return false;
- }
+ /* Create object to base hash if it does not exist yet. */
+ if (!view_layer->object_bases_hash) {
+ view_layer_bases_hash_create(view_layer);
}
- LayerCollection *lc_new = BLI_findptr(
- &lc_dst->layer_collections, lc_src->scene_collection, offsetof(LayerCollection, scene_collection));
- BLI_assert(lc_new);
- layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_new, lc_src);
-
- /* If it's directly linked, unlink it after the swap */
- if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) {
- BKE_collection_unlink(view_layer, lc_new);
+ /* Clear visible and selectable flags to be reset. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ base->flag &= ~(BASE_VISIBLED | BASE_SELECTABLED | BASE_VISIBLE_VIEWPORT | BASE_VISIBLE_RENDER);
}
- return true;
-}
+ /* Generate new layer connections and object bases when collections changed. */
+ CollectionChild child = {NULL, NULL, scene->master_collection};
+ const ListBase collections = {&child, &child};
+ ListBase new_object_bases = {NULL, NULL};
-/**
- * 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 ID *owner_id, LayerCollection *lc_dst, LayerCollection *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;
+ const int parent_exclude = 0, parent_restrict = 0;
+ layer_collection_sync(view_layer, &collections, &view_layer->layer_collections, &new_object_bases, parent_exclude, parent_restrict);
- if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) {
- return false;
- }
+ /* Any remaning object bases are to be removed. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (view_layer->basact == base) {
+ view_layer->basact = NULL;
+ }
- /* Collection is already where we wanted it to be */
- if (lc_dst->prev == lc_src) {
- return false;
+ BLI_ghash_remove(view_layer->object_bases_hash, base->object, NULL, NULL);
}
- /* Collection is already where we want it to be in the scene tree
- * but we want to swap it in the layer tree still */
- if (lc_dst->prev && lc_dst->prev->scene_collection == lc_src->scene_collection) {
- LayerCollection *lc_swap = lc_dst->prev;
- layer_collection_swap(view_layer, NULL, NULL, lc_dst->prev, lc_src);
-
- if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) {
- BKE_collection_unlink(view_layer, lc_swap);
- }
- return true;
- }
- /* We don't allow to move above/below a directly linked collection
- * unless the source collection is also directly linked */
- else if (is_directly_linked_dst) {
- /* Both directly linked to the ViewLayer, just need to swap */
- if (is_directly_linked_src) {
- BLI_remlink(&view_layer->layer_collections, lc_src);
- BLI_insertlinkbefore(&view_layer->layer_collections, lc_dst, lc_src);
- return true;
- }
- else {
- return false;
- }
- }
- else {
- LayerCollection *lc_temp;
+ BLI_freelistN(&view_layer->object_bases);
+ view_layer->object_bases = new_object_bases;
- if (!is_directly_linked_src) {
- /* lc_src will be invalid after BKE_collection_move_into!
- * so we swap it with lc_temp to preserve its settings */
- lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection);
- layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src);
- }
+ /* Always set a valid active collection. */
+ LayerCollection *active = view_layer->active_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);
- BKE_collection_unlink(view_layer, lc_temp);
- }
- return false;
- }
+ if (active && (active->flag & LAYER_COLLECTION_EXCLUDE)) {
+ BKE_layer_collection_activate_parent(view_layer, active);
}
-
- LayerCollection *lc_new = lc_dst->prev;
- BLI_assert(lc_new);
- layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src);
-
- /* If it's directly linked, unlink it after the swap */
- if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) {
- BKE_collection_unlink(view_layer, lc_new);
+ else if (active == NULL) {
+ view_layer->active_collection = view_layer->layer_collections.first;
}
-
- return true;
}
-/**
- * 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 ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src)
+void BKE_scene_collection_sync(const Scene *scene)
{
- 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(owner_id, lc_dst))) {
- return false;
- }
-
- /* Collection is already where we wanted it to be */
- if (lc_dst->next == lc_src) {
- return false;
- }
-
- /* Collection is already where we want it to be in the scene tree
- * but we want to swap it in the layer tree still */
- if (lc_dst->next && lc_dst->next->scene_collection == lc_src->scene_collection) {
- LayerCollection *lc_swap = lc_dst->next;
- layer_collection_swap(view_layer, NULL, NULL, lc_dst->next, lc_src);
-
- if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) {
- BKE_collection_unlink(view_layer, lc_swap);
- }
- return true;
- }
- /* We don't allow to move above/below a directly linked collection
- * unless the source collection is also directly linked */
- else if (is_directly_linked_dst) {
- /* Both directly linked to the ViewLayer, just need to swap */
- if (is_directly_linked_src) {
- BLI_remlink(&view_layer->layer_collections, lc_src);
- BLI_insertlinkafter(&view_layer->layer_collections, lc_dst, lc_src);
- return true;
- }
- else {
- return false;
- }
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ BKE_layer_collection_sync(scene, view_layer);
}
- else {
- LayerCollection *lc_temp;
-
- if (!is_directly_linked_src) {
- /* lc_src will be invalid after BKE_collection_move_into!
- * so we swap it with lc_temp to preserve its settings */
- lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection);
- layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src);
- }
+}
- 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);
- BKE_collection_unlink(view_layer, lc_temp);
- }
- return false;
- }
- }
+void BKE_main_collection_sync(const Main *bmain)
+{
+ /* TODO: if a single collection changed, figure out which
+ * scenes it belongs to and only update those. */
- LayerCollection *lc_new = lc_dst->next;
- BLI_assert(lc_new);
- layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src);
+ /* TODO: optimize for file load so only linked collections get checked? */
- /* If it's directly linked, unlink it after the swap */
- if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) {
- BKE_collection_unlink(view_layer, lc_new);
+ for (const Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ BKE_scene_collection_sync(scene);
}
-
- return true;
}
-static bool layer_collection_resync(ViewLayer *view_layer, LayerCollection *lc, const SceneCollection *sc)
+void BKE_main_collection_sync_remap(const Main *bmain)
{
- if (lc->scene_collection == sc) {
- ListBase collections = {NULL};
- BLI_movelisttolist(&collections, &lc->layer_collections);
+ /* On remapping of object or collection pointers free caches. */
+ /* TODO: try to make this faster */
- for (SceneCollection *sc_nested = sc->scene_collections.first; sc_nested; sc_nested = sc_nested->next) {
- LayerCollection *lc_nested = BLI_findptr(&collections, sc_nested, offsetof(LayerCollection, scene_collection));
- if (lc_nested) {
- BLI_remlink(&collections, lc_nested);
- BLI_addtail(&lc->layer_collections, lc_nested);
- }
- else {
- layer_collection_add(view_layer, lc, sc_nested);
- }
- }
+ for (const Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ MEM_SAFE_FREE(view_layer->object_bases_array);
- for (LayerCollection *lc_nested = collections.first; lc_nested; lc_nested = lc_nested->next) {
- layer_collection_free(view_layer, lc_nested);
+ if (view_layer->object_bases_hash) {
+ BLI_ghash_free(view_layer->object_bases_hash, NULL, NULL);
+ view_layer->object_bases_hash = NULL;
+ }
}
- BLI_freelistN(&collections);
-
- BLI_assert(BLI_listbase_count(&lc->layer_collections) ==
- BLI_listbase_count(&sc->scene_collections));
-
- return true;
}
- for (LayerCollection *lc_nested = lc->layer_collections.first; lc_nested; lc_nested = lc_nested->next) {
- if (layer_collection_resync(view_layer, lc_nested, sc)) {
- return true;
- }
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ BKE_collection_object_cache_free(collection);
}
- return false;
-}
-
-/**
- * Update the scene layers so that any LayerCollection that points
- * to \a sc is re-synced again
- */
-void BKE_layer_collection_resync(const ID *owner_id, const SceneCollection *sc)
-{
- 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);
- }
- }
+ BKE_main_collection_sync(bmain);
}
/* ---------------------------------------------------------------------- */
@@ -1102,161 +727,69 @@ void BKE_layer_collection_resync(const ID *owner_id, const SceneCollection *sc)
* It also select the objects that are in nested collections.
* \note Recursive
*/
-void BKE_layer_collection_objects_select(struct LayerCollection *layer_collection)
+bool BKE_layer_collection_objects_select(ViewLayer *view_layer, LayerCollection *lc, bool deselect)
{
- if ((layer_collection->flag & COLLECTION_DISABLED) ||
- ((layer_collection->flag & COLLECTION_SELECTABLE) == 0))
- {
- return;
- }
-
- for (LinkData *link = layer_collection->object_bases.first; link; link = link->next) {
- Base *base = link->data;
- if (base->flag & BASE_SELECTABLED) {
- base->flag |= BASE_SELECTED;
- }
- }
-
- for (LayerCollection *iter = layer_collection->layer_collections.first; iter; iter = iter->next) {
- BKE_layer_collection_objects_select(iter);
- }
-}
-
-/* ---------------------------------------------------------------------- */
-
-/**
- * Link a collection to a renderlayer
- * The collection needs to be created separately
- */
-LayerCollection *BKE_collection_link(ViewLayer *view_layer, SceneCollection *sc)
-{
- LayerCollection *lc = layer_collection_add(view_layer, NULL, sc);
- view_layer->active_collection = BKE_layer_collection_findindex(view_layer, lc);
- return lc;
-}
-
-/**
- * Unlink a collection base from a renderlayer
- * The corresponding collection is not removed from the master collection
- */
-void BKE_collection_unlink(ViewLayer *view_layer, LayerCollection *lc)
-{
- BKE_layer_collection_free(view_layer, lc);
- BLI_remlink(&view_layer->layer_collections, lc);
- MEM_freeN(lc);
- view_layer->active_collection = 0;
-}
-
-/**
- * Recursively enable nested collections
- */
-static void layer_collection_enable(ViewLayer *view_layer, LayerCollection *lc)
-{
- layer_collection_objects_populate(view_layer, lc, &lc->scene_collection->objects);
-
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- layer_collection_enable(view_layer, nlc);
- }
-}
-
-/**
- * Enable collection
- * Add its objects bases to ViewLayer
- *
- * Only around for doversion.
- */
-void BKE_collection_enable(ViewLayer *view_layer, LayerCollection *lc)
-{
- if ((lc->flag & COLLECTION_DISABLED) == 0) {
- return;
+ if (lc->collection->flag & COLLECTION_RESTRICT_SELECT) {
+ return false;
}
- lc->flag &= ~COLLECTION_DISABLED;
- layer_collection_enable(view_layer, lc);
-}
-
-static void layer_collection_object_add(ViewLayer *view_layer, LayerCollection *lc, Object *ob)
-{
- Base *base = object_base_add(view_layer, ob);
-
- /* Only add an object once. */
- if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data))) {
- return;
- }
+ bool changed = false;
- bool is_visible = ((lc->flag & COLLECTION_VIEWPORT) != 0) && ((lc->flag & COLLECTION_DISABLED) == 0);
- bool is_selectable = is_visible && ((lc->flag & COLLECTION_SELECTABLE) != 0);
+ if (!(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ for (CollectionObject *cob = lc->collection->gobject.first; cob; cob = cob->next) {
+ Base *base = BKE_view_layer_base_find(view_layer, cob->ob);
- if (is_visible) {
- base->flag |= BASE_VISIBLED;
+ if (base) {
+ if (deselect) {
+ if (base->flag & BASE_SELECTED) {
+ base->flag &= ~BASE_SELECTED;
+ changed = true;
+ }
+ }
+ else {
+ if ((base->flag & BASE_SELECTABLED) && !(base->flag & BASE_SELECTED)) {
+ base->flag |= BASE_SELECTED;
+ changed = true;
+ }
+ }
+ }
+ }
}
- if (is_selectable) {
- base->flag |= BASE_SELECTABLED;
+ for (LayerCollection *iter = lc->layer_collections.first; iter; iter = iter->next) {
+ changed |= BKE_layer_collection_objects_select(view_layer, iter, deselect);
}
- BLI_addtail(&lc->object_bases, BLI_genericNodeN(base));
+ return changed;
}
-static void layer_collection_object_remove(ViewLayer *view_layer, LayerCollection *lc, Object *ob)
-{
- Base *base;
- base = BKE_view_layer_base_find(view_layer, ob);
-
- LinkData *link = BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data));
- BLI_remlink(&lc->object_bases, link);
- MEM_freeN(link);
-
- view_layer_object_base_unref(view_layer, base);
-}
+/* ---------------------------------------------------------------------- */
-static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects)
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const Collection *collection)
{
- for (LinkData *link = objects->first; link; link = link->next) {
- layer_collection_object_add(view_layer, lc, link->data);
+ if (lc->collection == collection) {
+ return lc;
}
-}
-static void layer_collection_populate(ViewLayer *view_layer, LayerCollection *lc, SceneCollection *sc)
-{
- layer_collection_objects_populate(view_layer, lc, &sc->objects);
-
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- layer_collection_add(view_layer, lc, nsc);
- }
-}
-
-static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc)
-{
- LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
-
- lc->scene_collection = sc;
- lc->flag = COLLECTION_SELECTABLE | COLLECTION_VIEWPORT | COLLECTION_RENDER;
-
- if (parent != NULL) {
- BLI_addtail(&parent->layer_collections, lc);
- }
- else {
- BLI_addtail(&view_layer->layer_collections, lc);
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(nlc, collection);
+ if (found) {
+ return found;
+ }
}
-
- layer_collection_populate(view_layer, lc, sc);
-
- return lc;
+ return NULL;
}
-/* ---------------------------------------------------------------------- */
-
/**
- * Return the first matching LayerCollection in the ViewLayer for the SceneCollection.
+ * Return the first matching LayerCollection in the ViewLayer for the Collection.
*/
-LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *view_layer, const SceneCollection *scene_collection)
+LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *view_layer, const Collection *collection)
{
for (LayerCollection *layer_collection = view_layer->layer_collections.first;
layer_collection != NULL;
layer_collection = layer_collection->next)
{
- LayerCollection *found = find_layer_collection_by_scene_collection(layer_collection, scene_collection);
+ LayerCollection *found = find_layer_collection_by_scene_collection(layer_collection, collection);
if (found != NULL) {
return found;
@@ -1268,9 +801,9 @@ LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *vie
/**
* See if view layer has the scene collection linked directly, or indirectly (nested)
*/
-bool BKE_view_layer_has_collection(ViewLayer *view_layer, const SceneCollection *scene_collection)
+bool BKE_view_layer_has_collection(ViewLayer *view_layer, const Collection *collection)
{
- return BKE_layer_collection_first_from_scene_collection(view_layer, scene_collection) != NULL;
+ return BKE_layer_collection_first_from_scene_collection(view_layer, collection) != NULL;
}
/**
@@ -1287,70 +820,6 @@ bool BKE_scene_has_object(Scene *scene, Object *ob)
return false;
}
-
-/* ---------------------------------------------------------------------- */
-/* Syncing */
-
-static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc)
-{
- if (lc->scene_collection == sc) {
- return lc;
- }
-
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- LayerCollection *found = find_layer_collection_by_scene_collection(nlc, sc);
- if (found) {
- return found;
- }
- }
- return NULL;
-}
-
-/**
- * Add a new LayerCollection for all the ViewLayers that have sc_parent
- */
-void BKE_layer_sync_new_scene_collection(ID *owner_id, const SceneCollection *sc_parent, SceneCollection *sc)
-{
- 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) {
- layer_collection_add(view_layer, lc_parent, sc);
- }
- }
- }
-}
-
-/**
- * Add a corresponding ObjectBase to all the equivalent LayerCollection
- */
-void BKE_layer_sync_object_link(const ID *owner_id, SceneCollection *sc, Object *ob)
-{
- 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) {
- layer_collection_object_add(view_layer, found, ob);
- }
- }
- }
-}
-
-/**
- * Remove the equivalent object base to all layers that have this collection
- */
-void BKE_layer_sync_object_unlink(const ID *owner_id, SceneCollection *sc, Object *ob)
-{
- 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) {
- layer_collection_object_remove(view_layer, found, ob);
- }
- }
- }
-}
-
/* ---------------------------------------------------------------------- */
/* Override */
@@ -1677,93 +1146,28 @@ void BKE_view_layer_bases_in_mode_iterator_end(BLI_Iterator *UNUSED(iter))
/* Evaluation */
-static void layer_eval_layer_collection_pre(Depsgraph *depsgraph, ID *UNUSED(owner_id), ViewLayer *view_layer)
+void BKE_layer_eval_view_layer(struct Depsgraph *depsgraph,
+ struct Scene *UNUSED(scene),
+ ViewLayer *view_layer)
{
DEG_debug_print_eval(depsgraph, __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);
- }
+ /* Set visibility based on depsgraph mode. */
+ const eEvaluationMode mode = DEG_get_mode(depsgraph);
+ const int base_flag = (mode == DAG_EVAL_VIEWPORT) ? BASE_VISIBLE_VIEWPORT : BASE_VISIBLE_RENDER;
- /* 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 */
-};
-
-/**
- * \note We can't use layer_collection->flag because of 3 level nesting (where parent is visible, but not grand-parent)
- * So layer_collection->flag_evaluated is expected to be up to date with layer_collection->flag.
- */
-static bool layer_collection_visible_get(Depsgraph *depsgraph, LayerCollection *layer_collection)
-{
- if (layer_collection->flag_evaluated & COLLECTION_DISABLED) {
- return false;
- }
-
- if (DEG_get_mode(depsgraph) == DAG_EVAL_VIEWPORT) {
- return (layer_collection->flag_evaluated & COLLECTION_VIEWPORT) != 0;
- }
- else {
- return (layer_collection->flag_evaluated & COLLECTION_RENDER) != 0;
- }
-}
-
-static void layer_eval_layer_collection(Depsgraph *depsgraph,
- LayerCollection *layer_collection,
- LayerCollection *parent_layer_collection)
-{
- DEG_debug_print_eval_parent_typed(
- depsgraph,
- __func__,
- layer_collection->scene_collection->name,
- layer_collection->scene_collection,
- collection_type_lookup[layer_collection->scene_collection->type],
- "parent",
- (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) ? collection_type_lookup[parent_layer_collection->scene_collection->type] : "");
- BLI_assert(layer_collection != parent_layer_collection);
-
- /* visibility */
- layer_collection->flag_evaluated = layer_collection->flag;
-
- if (parent_layer_collection != NULL) {
- if (layer_collection_visible_get(depsgraph, parent_layer_collection) == false) {
- layer_collection->flag_evaluated |= COLLECTION_DISABLED;
- }
-
- if ((parent_layer_collection->flag_evaluated & COLLECTION_DISABLED) ||
- (parent_layer_collection->flag_evaluated & COLLECTION_SELECTABLE) == 0)
- {
- layer_collection->flag_evaluated &= ~COLLECTION_SELECTABLE;
- }
- }
-
- const bool is_visible = layer_collection_visible_get(depsgraph, layer_collection);
- const bool is_selectable = is_visible && ((layer_collection->flag_evaluated & COLLECTION_SELECTABLE) != 0);
-
- for (LinkData *link = layer_collection->object_bases.first; link != NULL; link = link->next) {
- Base *base = link->data;
-
- if (is_visible) {
+ for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
+ if (base->flag & base_flag) {
base->flag |= BASE_VISIBLED;
}
-
- if (is_selectable) {
- base->flag |= BASE_SELECTABLED;
+ else {
+ base->flag &= ~BASE_VISIBLED;
}
}
-}
-static void layer_eval_layer_collection_post(Depsgraph *depsgraph, ViewLayer *view_layer)
-{
- DEG_debug_print_eval(depsgraph, __func__, view_layer->name, view_layer);
+ /* TODO(sergey): Is it always required? */
+ view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY;
+
/* Create array of bases, for fast index-based lookup. */
const int num_object_bases = BLI_listbase_count(&view_layer->object_bases);
MEM_SAFE_FREE(view_layer->object_bases_array);
@@ -1780,42 +1184,12 @@ static void layer_eval_layer_collection_post(Depsgraph *depsgraph, ViewLayer *vi
}
}
-static void layer_eval_collections_recurse(Depsgraph *depsgraph,
- ListBase *layer_collections,
- LayerCollection *parent_layer_collection)
-{
- for (LayerCollection *layer_collection = layer_collections->first;
- layer_collection != NULL;
- layer_collection = layer_collection->next)
- {
- layer_eval_layer_collection(depsgraph,
- layer_collection,
- parent_layer_collection);
- layer_eval_collections_recurse(depsgraph,
- &layer_collection->layer_collections,
- layer_collection);
- }
-}
-
-void BKE_layer_eval_view_layer(struct Depsgraph *depsgraph,
- struct ID *owner_id,
- ViewLayer *view_layer)
-{
- layer_eval_layer_collection_pre(depsgraph, owner_id, view_layer);
- layer_eval_collections_recurse(depsgraph,
- &view_layer->layer_collections,
- NULL);
- layer_eval_layer_collection_post(depsgraph, view_layer);
-}
-
void BKE_layer_eval_view_layer_indexed(struct Depsgraph *depsgraph,
- struct ID *owner_id,
+ struct Scene *scene,
int view_layer_index)
{
- BLI_assert(GS(owner_id->name) == ID_SCE);
BLI_assert(view_layer_index >= 0);
- Scene *scene = (Scene *)owner_id;
ViewLayer *view_layer = BLI_findlink(&scene->view_layers, view_layer_index);
BLI_assert(view_layer != NULL);
- BKE_layer_eval_view_layer(depsgraph, owner_id, view_layer);
+ BKE_layer_eval_view_layer(depsgraph, scene, view_layer);
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 883f0342159..3926d2055f0 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -91,11 +91,11 @@
#include "BKE_brush.h"
#include "BKE_camera.h"
#include "BKE_cachefile.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_font.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_gpencil.h"
#include "BKE_idcode.h"
#include "BKE_idprop.h"
@@ -437,7 +437,7 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
if (!test) BKE_sound_make_local(bmain, (bSound *)id, lib_local);
return true;
case ID_GR:
- if (!test) BKE_group_make_local(bmain, (Group *)id, lib_local);
+ if (!test) BKE_collection_make_local(bmain, (Collection *)id, lib_local);
return true;
case ID_AR:
if (!test) BKE_armature_make_local(bmain, (bArmature *)id, lib_local);
@@ -615,7 +615,7 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, con
BKE_text_copy_data(bmain, (Text *)*r_newid, (Text *)id, flag);
break;
case ID_GR:
- BKE_group_copy_data(bmain, (Group *)*r_newid, (Group *)id, flag);
+ BKE_collection_copy_data(bmain, (Collection *)*r_newid, (Collection *)id, flag);
break;
case ID_AR:
BKE_armature_copy_data(bmain, (bArmature *)*r_newid, (bArmature *)id, flag);
@@ -729,7 +729,7 @@ void BKE_id_swap(Main *bmain, ID *id_a, ID *id_b)
CASE_SWAP(ID_TXT, Text);
CASE_SWAP(ID_SPK, Speaker);
CASE_SWAP(ID_SO, bSound);
- CASE_SWAP(ID_GR, Group);
+ CASE_SWAP(ID_GR, Collection);
CASE_SWAP(ID_AR, bArmature);
CASE_SWAP(ID_AC, bAction);
CASE_SWAP(ID_NT, bNodeTree);
@@ -935,7 +935,7 @@ ListBase *which_libbase(Main *mainlib, short type)
case ID_SO:
return &(mainlib->sound);
case ID_GR:
- return &(mainlib->group);
+ return &(mainlib->collection);
case ID_AR:
return &(mainlib->armature);
case ID_AC:
@@ -1096,7 +1096,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[INDEX_ID_TXT] = &(main->text);
lb[INDEX_ID_SO] = &(main->sound);
- lb[INDEX_ID_GR] = &(main->group);
+ lb[INDEX_ID_GR] = &(main->collection);
lb[INDEX_ID_PAL] = &(main->palettes);
lb[INDEX_ID_PC] = &(main->paintcurves);
lb[INDEX_ID_BR] = &(main->brush);
@@ -1165,7 +1165,7 @@ size_t BKE_libblock_get_alloc_info(short type, const char **name)
CASE_RETURN(ID_SPK, Speaker);
CASE_RETURN(ID_LP, LightProbe);
CASE_RETURN(ID_SO, bSound);
- CASE_RETURN(ID_GR, Group);
+ CASE_RETURN(ID_GR, Collection);
CASE_RETURN(ID_AR, bArmature);
CASE_RETURN(ID_AC, bAction);
CASE_RETURN(ID_NT, bNodeTree);
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index efc550ac64c..dbfe619153d 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -72,7 +72,6 @@
#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"
@@ -287,6 +286,16 @@ static void library_foreach_bone(LibraryForeachIDData *data, Bone *bone)
FOREACH_FINALIZE_VOID;
}
+static void library_foreach_layer_collection(LibraryForeachIDData *data, ListBase *lb)
+{
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ FOREACH_CALLBACK_INVOKE(data, lc->collection, IDWALK_CB_NOP);
+ library_foreach_layer_collection(data, &lc->layer_collections);
+ }
+
+ FOREACH_FINALIZE_VOID;
+}
+
static void library_foreach_ID_as_subdata_link(
ID **id_pp, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data)
{
@@ -409,20 +418,21 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
- FOREACH_SCENE_COLLECTION_BEGIN(scene, sc)
- {
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
- }
+ for (CollectionObject *cob = scene->master_collection->gobject.first; cob; cob = cob->next) {
+ CALLBACK_INVOKE(cob->ob, IDWALK_CB_USER);
+ }
+ for (CollectionChild *child = scene->master_collection->children.first; child; child = child->next) {
+ CALLBACK_INVOKE(child->collection, IDWALK_CB_USER);
}
- FOREACH_SCENE_COLLECTION_END;
ViewLayer *view_layer;
for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- CALLBACK_INVOKE(base->object, IDWALK_NOP);
+ CALLBACK_INVOKE(base->object, IDWALK_CB_NOP);
}
+ library_foreach_layer_collection(&data, &view_layer->layer_collections);
+
for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) {
if (fmc->script) {
CALLBACK_INVOKE(fmc->script, IDWALK_CB_NOP);
@@ -702,12 +712,13 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
case ID_GR:
{
- Group *group = (Group *) id;
- FOREACH_GROUP_BASE_BEGIN(group, base)
- {
- CALLBACK_INVOKE(base->object, IDWALK_CB_USER_ONE);
+ Collection *collection = (Collection *) id;
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ CALLBACK_INVOKE(cob->ob, IDWALK_CB_USER);
+ }
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ CALLBACK_INVOKE(child->collection, IDWALK_CB_USER);
}
- FOREACH_GROUP_BASE_END
break;
}
@@ -1048,7 +1059,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
case ID_SPK:
return ELEM(id_type_used, ID_SO);
case ID_GR:
- return ELEM(id_type_used, ID_OB);
+ return ELEM(id_type_used, ID_OB, ID_GR);
case ID_NT:
/* Could be the following, but node.id has no type restriction... */
#if 0
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 983f6781572..cf2a001daaa 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -77,7 +77,6 @@
#include "BKE_curve.h"
#include "BKE_fcurve.h"
#include "BKE_font.h"
-#include "BKE_group.h"
#include "BKE_gpencil.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
@@ -271,25 +270,27 @@ 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->id, ob, false);
+ /* Remove object from all collections in the scene. free_use is false
+ * to avoid recursively calling object free again. */
+ BKE_scene_collections_object_remove(r_id_remap_data->bmain, sce, ob, false);
if (!is_indirect) {
r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
}
}
-static void libblock_remap_data_preprocess_group_unlink(
+static void libblock_remap_data_preprocess_collection_unlink(
IDRemap *r_id_remap_data, Object *ob, const bool skip_indirect, const bool is_indirect)
{
Main *bmain = r_id_remap_data->bmain;
- for (Group *group = bmain->group.first; group; group = group->id.next) {
- if (BKE_group_object_exists(group, ob)) {
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (!BKE_collection_is_in_scene(collection) && BKE_collection_has_object(collection, ob)) {
if (skip_indirect && is_indirect) {
r_id_remap_data->skipped_indirect++;
r_id_remap_data->skipped_refcounted++;
}
else {
- BKE_collections_object_remove(bmain, &group->id, ob, false);
+ BKE_collection_object_remove(bmain, collection, ob, false);
if (!is_indirect) {
r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
@@ -311,12 +312,14 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
/* In case we are unlinking... */
if (!r_id_remap_data->old_id) {
+ /* TODO: how is it valid to iterator over a scene while
+ * removing objects from it? can't this crash? */
/* ... everything from scene. */
FOREACH_SCENE_OBJECT_BEGIN(sce, ob_iter)
{
libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect);
- libblock_remap_data_preprocess_group_unlink(
+ libblock_remap_data_preprocess_collection_unlink(
r_id_remap_data, ob_iter, skip_indirect, is_indirect);
}
FOREACH_SCENE_OBJECT_END;
@@ -326,7 +329,7 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
Object *old_ob = (Object *)r_id_remap_data->old_id;
libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data, sce, old_ob, skip_indirect, is_indirect);
- libblock_remap_data_preprocess_group_unlink(
+ libblock_remap_data_preprocess_collection_unlink(
r_id_remap_data, old_ob, skip_indirect, is_indirect);
}
@@ -360,23 +363,16 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
static void libblock_remap_data_postprocess_object_update(Main *bmain, Object *old_ob, Object *new_ob)
{
- if (old_ob->flag & OB_FROMGROUP) {
- /* Note that for Scene's BaseObject->flag, either we:
- * - unlinked old_ob (i.e. new_ob is NULL), in which case scenes' bases have been removed already.
- * - remapped old_ob by new_ob, in which case scenes' bases are still valid as is.
- * So in any case, no need to update them here. */
- if (BKE_group_object_find(NULL, old_ob) == NULL) {
- old_ob->flag &= ~OB_FROMGROUP;
- }
- if (new_ob == NULL) { /* We need to remove NULL-ified groupobjects... */
- for (Group *group = bmain->group.first; group; group = group->id.next) {
- BKE_group_object_unlink(group, NULL);
- }
- }
- else {
- new_ob->flag |= OB_FROMGROUP;
- }
+ if (new_ob == NULL) {
+ /* In case we unlinked old_ob (new_ob is NULL), the object has already
+ * been removed from the scenes and their collections. We still have
+ * to remove the NULL children from collections not used in any scene. */
+ BKE_collections_object_remove_nulls(bmain);
}
+ else {
+ BKE_main_collection_sync_remap(bmain);
+ }
+
if (old_ob->type == OB_MBALL) {
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->type == OB_MBALL && BKE_mball_is_basis_for(ob, old_ob)) {
@@ -386,27 +382,20 @@ static void libblock_remap_data_postprocess_object_update(Main *bmain, Object *o
}
}
-static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmain), Scene *sce, ID *old_id)
+static void libblock_remap_data_postprocess_collection_update(Main *bmain, Collection *old_collection, Collection *new_collection)
{
- /* Note that here we assume no object has no base (i.e. all objects are assumed instanced
- * in one scene...). */
- FOREACH_SCENE_OBJECT_BEGIN(sce, ob)
- {
- if (ob->flag & OB_FROMGROUP) {
- Group *grp = BKE_group_object_find(NULL, ob);
-
- /* Unlinked group (old_id) is still in bmain... */
- if (grp && (&grp->id == old_id || grp->id.us == 0)) {
- grp = BKE_group_object_find(grp, ob);
- }
- if (!grp) {
- ob->flag &= ~OB_FROMGROUP;
- }
- }
+ if (new_collection == NULL) {
+ /* In case we unlinked old_collection (new_collection is NULL), we need
+ * to remove any collection children that have been set to NULL in the
+ * because of pointer replacement. */
+ BKE_collections_child_remove_nulls(bmain, old_collection);
+ }
+ else {
+ BKE_main_collection_sync_remap(bmain);
}
- FOREACH_SCENE_OBJECT_END;
}
+
static void libblock_remap_data_postprocess_obdata_relink(Main *UNUSED(bmain), Object *ob, ID *new_id)
{
if (ob->data == new_id) {
@@ -588,11 +577,7 @@ void BKE_libblock_remap_locked(
libblock_remap_data_postprocess_object_update(bmain, (Object *)old_id, (Object *)new_id);
break;
case ID_GR:
- if (!new_id) { /* Only affects us in case group was unlinked. */
- for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
- libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, old_id);
- }
- }
+ libblock_remap_data_postprocess_collection_update(bmain, (Collection *)old_id, (Collection *)new_id);
break;
case ID_ME:
case ID_CU:
@@ -689,8 +674,6 @@ void BKE_libblock_relink_ex(
switch (GS(id->name)) {
case ID_SCE:
{
- Scene *sce = (Scene *)id;
-
if (old_id) {
switch (GS(old_id->name)) {
case ID_OB:
@@ -699,21 +682,19 @@ void BKE_libblock_relink_ex(
break;
}
case ID_GR:
- if (!new_id) { /* Only affects us in case group was unlinked. */
- libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, old_id);
- }
+ libblock_remap_data_postprocess_collection_update(bmain, (Collection *)old_id, (Collection *)new_id);
break;
default:
break;
}
}
else {
- /* No choice but to check whole objects/groups. */
+ /* No choice but to check whole objects/collections. */
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
libblock_remap_data_postprocess_object_update(bmain, ob, NULL);
}
- for (Group *grp = bmain->group.first; grp; grp = grp->id.next) {
- libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, NULL);
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ libblock_remap_data_postprocess_collection_update(bmain, collection, NULL);
}
}
break;
@@ -843,7 +824,7 @@ void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
BKE_sound_free((bSound *)id);
break;
case ID_GR:
- BKE_group_free((Group *)id);
+ BKE_collection_free((Collection *)id);
break;
case ID_AR:
BKE_armature_free((bArmature *)id);
@@ -1038,8 +1019,8 @@ void BKE_libblock_free_us(Main *bmain, void *idv) /* test users */
id_us_min(id);
- /* XXX This is a temp (2.77) hack so that we keep same behavior as in 2.76 regarding groups when deleting an object.
- * Since only 'user_one' usage of objects is groups, and only 'real user' usage of objects is scenes,
+ /* XXX This is a temp (2.77) hack so that we keep same behavior as in 2.76 regarding collections when deleting an object.
+ * Since only 'user_one' usage of objects is collections, and only 'real user' usage of objects is scenes,
* removing that 'user_one' tag when there is no more real (scene) users of an object ensures it gets
* fully unlinked.
* But only for local objects, not linked ones!
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index bced9a1e019..1e6d3041f3f 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -80,12 +80,12 @@
#include "BKE_DerivedMesh.h"
#include "BKE_animsys.h"
#include "BKE_anim.h"
+#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
-#include "BKE_group.h"
#include "BKE_icons.h"
#include "BKE_key.h"
#include "BKE_lamp.h"
@@ -719,7 +719,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
ob = BKE_libblock_alloc(bmain, ID_OB, name, 0);
- /* We increase object user count when linking to SceneCollections. */
+ /* We increase object user count when linking to Collections. */
id_us_min(&ob->id);
/* default object vars */
@@ -746,12 +746,12 @@ static Object *object_add_common(Main *bmain, ViewLayer *view_layer, int type, c
/**
* General add: to scene, with layer from area and default name
*
- * Object is added to the active SceneCollection.
+ * Object is added to the active Collection.
* If there is no linked collection to the active ViewLayer we create a new one.
*/
/* creates minimum required data, but without vertices etc. */
Object *BKE_object_add(
- Main *bmain, Scene *scene, ViewLayer *view_layer,
+ Main *bmain, Scene *UNUSED(scene), ViewLayer *view_layer,
int type, const char *name)
{
Object *ob;
@@ -760,8 +760,8 @@ 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->id, layer_collection->scene_collection, ob);
+ layer_collection = BKE_layer_collection_get_active(view_layer);
+ BKE_collection_object_add(bmain, layer_collection->collection, ob);
base = BKE_view_layer_base_find(view_layer, ob);
BKE_view_layer_base_select(view_layer, base);
@@ -782,7 +782,7 @@ Object *BKE_object_add_from(
Base *base;
ob = object_add_common(bmain, view_layer, type, name);
- BKE_collection_object_add_from(scene, ob_src, ob);
+ BKE_collection_object_add_from(bmain, scene, ob_src, ob);
base = BKE_view_layer_base_find(view_layer, ob);
BKE_view_layer_base_select(view_layer, base);
@@ -1157,7 +1157,6 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_
if (ob_src->iuser) ob_dst->iuser = MEM_dupallocN(ob_src->iuser);
if (ob_src->bb) ob_dst->bb = MEM_dupallocN(ob_src->bb);
- ob_dst->flag &= ~OB_FROMGROUP;
BLI_listbase_clear(&ob_dst->modifiers);
@@ -1344,9 +1343,9 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
/* proxy rule: lib_object->proxy_from == the one we borrow from, set temporally while object_update */
/* local_object->proxy == pointer to library object, saved in files and read */
-/* local_object->proxy_group == pointer to group dupli-object, saved in files and read */
+/* local_object->proxy_group == pointer to collection dupli-object, saved in files and read */
-void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
+void BKE_object_make_proxy(Object *ob, Object *target, Object *cob)
{
/* paranoia checks */
if (ID_IS_LINKED(ob) || !ID_IS_LINKED(target)) {
@@ -1355,24 +1354,24 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
}
ob->proxy = target;
- ob->proxy_group = gob;
+ ob->proxy_group = cob;
id_lib_extern(&target->id);
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
DEG_id_tag_update(&target->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* copy transform
- * - gob means this proxy comes from a group, just apply the matrix
+ * - cob means this proxy comes from a collection, just apply the matrix
* so the object wont move from its dupli-transform.
*
- * - no gob means this is being made from a linked object,
+ * - no cob means this is being made from a linked object,
* this is closer to making a copy of the object - in-place. */
- if (gob) {
+ if (cob) {
ob->rotmode = target->rotmode;
- mul_m4_m4m4(ob->obmat, gob->obmat, target->obmat);
- if (gob->dup_group) { /* should always be true */
+ mul_m4_m4m4(ob->obmat, cob->obmat, target->obmat);
+ if (cob->dup_group) { /* should always be true */
float tvec[3];
- mul_v3_mat3_m4v3(tvec, ob->obmat, gob->dup_group->dupli_ofs);
+ mul_v3_mat3_m4v3(tvec, ob->obmat, cob->dup_group->dupli_ofs);
sub_v3_v3(ob->obmat[3], tvec);
}
BKE_object_apply_mat4(ob, ob->obmat, false, true);
@@ -2624,13 +2623,13 @@ static void object_handle_update_proxy(Depsgraph *depsgraph,
Object *object,
const bool do_proxy_update)
{
- /* The case when this is a group proxy, object_update is called in group.c */
+ /* The case when this is a collection proxy, object_update is called in collection.c */
if (object->proxy == NULL) {
return;
}
/* set pointer in library proxy target, for copying, but restore it */
object->proxy->proxy_from = object;
- // printf("set proxy pointer for later group stuff %s\n", ob->id.name);
+ // printf("set proxy pointer for later collection stuff %s\n", ob->id.name);
/* the no-group proxy case, we call update */
if (object->proxy_group == NULL) {
@@ -3410,22 +3409,22 @@ LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer, eObjectSe
/**
* return all groups this object is apart of, caller must free.
*/
-struct LinkNode *BKE_object_groups(Object *ob)
+struct LinkNode *BKE_object_groups(Main *bmain, Object *ob)
{
- LinkNode *group_linknode = NULL;
- Group *group = NULL;
- while ((group = BKE_group_object_find(group, ob))) {
- BLI_linklist_prepend(&group_linknode, group);
+ LinkNode *collection_linknode = NULL;
+ Collection *collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, collection, ob))) {
+ BLI_linklist_prepend(&collection_linknode, collection);
}
- return group_linknode;
+ return collection_linknode;
}
-void BKE_object_groups_clear(Object *ob)
+void BKE_object_groups_clear(Main *bmain, Object *ob)
{
- Group *group = NULL;
- while ((group = BKE_group_object_find(group, ob))) {
- BKE_group_object_unlink(group, ob);
+ Collection *collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, collection, ob))) {
+ BKE_collection_object_remove(bmain, collection, ob, false);
}
}
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index d99a1ba8c0b..5e42cdb6b14 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -48,10 +48,10 @@
#include "DNA_vfont_types.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_DerivedMesh.h"
#include "BKE_font.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_idprop.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
@@ -74,7 +74,7 @@ typedef struct DupliContext {
Depsgraph *depsgraph;
bool do_update;
bool animated;
- Group *group; /* XXX child objects are selected from this group if set, could be nicer */
+ Collection *collection; /* XXX child objects are selected from this group if set, could be nicer */
Object *obedit; /* Only to check if the object is in edit-mode. */
Scene *scene;
@@ -107,7 +107,7 @@ static void init_context(DupliContext *r_ctx, Depsgraph *depsgraph, Scene *scene
/* don't allow BKE_object_handle_update for viewport during render, can crash */
r_ctx->do_update = update && !(G.is_rendering && DEG_get_mode(depsgraph) != DAG_EVAL_RENDER);
r_ctx->animated = false;
- r_ctx->group = NULL;
+ r_ctx->collection = NULL;
r_ctx->object = ob;
r_ctx->obedit = OBEDIT_FROM_OBACT(ob);
@@ -130,8 +130,8 @@ static void copy_dupli_context(DupliContext *r_ctx, const DupliContext *ctx, Obj
r_ctx->animated |= animated; /* object animation makes all children animated */
/* XXX annoying, previously was done by passing an ID* argument, this at least is more explicit */
- if (ctx->gen->type == OB_DUPLIGROUP)
- r_ctx->group = ctx->object->dup_group;
+ if (ctx->gen->type == OB_DUPLICOLLECTION)
+ r_ctx->collection = ctx->object->dup_group;
r_ctx->object = ob;
if (mat)
@@ -210,7 +210,7 @@ static DupliObject *make_dupli(const DupliContext *ctx,
*/
static void make_recursive_duplis(const DupliContext *ctx, Object *ob, float space_mat[4][4], int index, bool animated)
{
- /* simple preventing of too deep nested groups with MAX_DUPLI_RECUR */
+ /* simple preventing of too deep nested collections with MAX_DUPLI_RECUR */
if (ctx->level < MAX_DUPLI_RECUR) {
DupliContext rctx;
copy_dupli_context(&rctx, ctx, ob, space_mat, index, animated);
@@ -235,19 +235,19 @@ static bool is_child(const Object *ob, const Object *parent)
return false;
}
-/* create duplis from every child in scene or group */
+/* create duplis from every child in scene or collection */
static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChildDuplisFunc make_child_duplis_cb)
{
Object *parent = ctx->object;
- if (ctx->group) {
- int groupid = 0;
- FOREACH_GROUP_BASE_BEGIN(ctx->group, base)
+ if (ctx->collection) {
+ int collectionid = 0;
+ FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(ctx->collection, base)
{
Object *ob = base->object;
if ((base->flag & BASE_VISIBLED) && ob != ctx->obedit && is_child(ob, parent)) {
DupliContext pctx;
- copy_dupli_context(&pctx, ctx, ctx->object, NULL, groupid, false);
+ copy_dupli_context(&pctx, ctx, ctx->object, NULL, collectionid, false);
/* mballs have a different dupli handling */
if (ob->type != OB_MBALL) {
@@ -255,9 +255,9 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
}
make_child_duplis_cb(&pctx, userdata, ob);
}
- groupid++;
+ collectionid++;
}
- FOREACH_GROUP_BASE_END
+ FOREACH_COLLECTION_BASE_RECURSIVE_END
}
else {
int baseid = 0;
@@ -281,54 +281,55 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
/*---- Implementations ----*/
-/* OB_DUPLIGROUP */
-static void make_duplis_group(const DupliContext *ctx)
+/* OB_DUPLICOLLECTION */
+static void make_duplis_collection(const DupliContext *ctx)
{
Object *ob = ctx->object;
- Group *group;
+ Collection *collection;
Base *base;
- float group_mat[4][4];
+ float collection_mat[4][4];
int id;
bool animated;
if (ob->dup_group == NULL) return;
- group = ob->dup_group;
+ collection = ob->dup_group;
- /* combine group offset and obmat */
- unit_m4(group_mat);
- sub_v3_v3(group_mat[3], group->dupli_ofs);
- mul_m4_m4m4(group_mat, ob->obmat, group_mat);
+ /* combine collection offset and obmat */
+ unit_m4(collection_mat);
+ sub_v3_v3(collection_mat[3], collection->dupli_ofs);
+ mul_m4_m4m4(collection_mat, ob->obmat, collection_mat);
/* don't access 'ob->obmat' from now on. */
- /* handles animated groups */
+ /* handles animated collections */
/* we need to check update for objects that are not in scene... */
if (ctx->do_update) {
/* note: update is optional because we don't always need object
* transformations to be correct. Also fixes bug [#29616]. */
- BKE_group_handle_recalc_and_update(ctx->depsgraph, ctx->scene, ob, group);
+ BKE_collection_handle_recalc_and_update(ctx->depsgraph, ctx->scene, ob, collection);
}
- animated = BKE_group_is_animated(group, ob);
+ animated = BKE_collection_is_animated(collection, ob);
- for (base = group->view_layer->object_bases.first, id = 0; base; base = base->next, id++) {
+ const ListBase dup_collection_objects = BKE_collection_object_cache_get(collection);
+ for (base = dup_collection_objects.first, id = 0; base; base = base->next, id++) {
if (base->object != ob && (base->flag & BASE_VISIBLED)) {
float mat[4][4];
- /* group dupli offset, should apply after everything else */
- mul_m4_m4m4(mat, group_mat, base->object->obmat);
+ /* collection dupli offset, should apply after everything else */
+ mul_m4_m4m4(mat, collection_mat, base->object->obmat);
make_dupli(ctx, base->object, mat, id, animated, false);
/* recursion */
- make_recursive_duplis(ctx, base->object, group_mat, id, animated);
+ make_recursive_duplis(ctx, base->object, collection_mat, id, animated);
}
}
}
-static const DupliGenerator gen_dupli_group = {
- OB_DUPLIGROUP, /* type */
- make_duplis_group /* make_duplis */
+static const DupliGenerator gen_dupli_collection = {
+ OB_DUPLICOLLECTION, /* type */
+ make_duplis_collection /* make_duplis */
};
/* OB_DUPLIFRAMES */
@@ -341,8 +342,8 @@ static void make_duplis_frames(const DupliContext *ctx)
int cfrao = scene->r.cfra;
int dupend = ob->dupend;
- /* dupliframes not supported inside groups */
- if (ctx->group)
+ /* dupliframes not supported inside collections */
+ if (ctx->collection)
return;
/* if we don't have any data/settings which will lead to object movement,
* don't waste time trying, as it will all look the same...
@@ -601,8 +602,8 @@ static void make_duplis_font(const DupliContext *ctx)
const wchar_t *text = NULL;
bool text_free = false;
- /* font dupliverts not supported inside groups */
- if (ctx->group)
+ /* font dupliverts not supported inside collections */
+ if (ctx->collection)
return;
copy_m4_m4(pmat, par->obmat);
@@ -851,7 +852,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0;
float (*obmat)[4];
int a, b, hair = 0;
- int totpart, totchild, totgroup = 0 /*, pa_num */;
+ int totpart, totchild, totcollection = 0 /*, pa_num */;
int no_draw_flag = PARS_UNEXIST;
@@ -891,10 +892,14 @@ 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->view_layer->object_bases))
+ if (part->dup_group == NULL)
return;
- if (BLI_findptr(&part->dup_group->view_layer->object_bases, par, offsetof(Base, object))) {
+ const ListBase dup_collection_objects = BKE_collection_object_cache_get(part->dup_group);
+ if (BLI_listbase_is_empty(&dup_collection_objects))
+ return;
+
+ if (BLI_findptr(&dup_collection_objects, par, offsetof(Base, object))) {
return;
}
}
@@ -918,31 +923,31 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
/* gather list of objects or single object */
if (part->ren_as == PART_DRAW_GR) {
if (ctx->do_update) {
- BKE_group_handle_recalc_and_update(ctx->depsgraph, scene, par, part->dup_group);
+ BKE_collection_handle_recalc_and_update(ctx->depsgraph, scene, par, part->dup_group);
}
if (part->draw & PART_DRAW_COUNT_GR) {
for (dw = part->dupliweights.first; dw; dw = dw->next)
- totgroup += dw->count;
+ totcollection += dw->count;
}
else {
- FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object)
{
(void) object;
- totgroup++;
+ totcollection++;
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
/* we also copy the actual objects to restore afterwards, since
* BKE_object_where_is_calc_time will change the object which breaks transform */
- oblist = MEM_callocN((size_t)totgroup * sizeof(Object *), "dupgroup object list");
- obcopylist = MEM_callocN((size_t)totgroup * sizeof(Object), "dupgroup copy list");
+ oblist = MEM_callocN((size_t)totcollection * sizeof(Object *), "dupcollection object list");
+ obcopylist = MEM_callocN((size_t)totcollection * sizeof(Object), "dupcollection copy list");
- if (part->draw & PART_DRAW_COUNT_GR && totgroup) {
+ if (part->draw & PART_DRAW_COUNT_GR && totcollection) {
dw = part->dupliweights.first;
- for (a = 0; a < totgroup; dw = dw->next) {
+ for (a = 0; a < totcollection; dw = dw->next) {
for (b = 0; b < dw->count; b++, a++) {
oblist[a] = dw->ob;
obcopylist[a] = *dw->ob;
@@ -951,17 +956,17 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
else {
a = 0;
- FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object)
{
oblist[a] = object;
obcopylist[a] = *object;
a++;
- if (a >= totgroup) {
+ if (a >= totcollection) {
continue;
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
else {
@@ -1003,14 +1008,14 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
if (part->ren_as == PART_DRAW_GR) {
/* prevent divide by zero below [#28336] */
- if (totgroup == 0)
+ if (totcollection == 0)
continue;
- /* for groups, pick the object based on settings */
+ /* for collections, pick the object based on settings */
if (part->draw & PART_DRAW_RAND_GR)
- b = BLI_rand() % totgroup;
+ b = BLI_rand() % totcollection;
else
- b = a % totgroup;
+ b = a % totcollection;
ob = oblist[b];
obmat = oblist[b]->obmat;
@@ -1051,7 +1056,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
b = 0;
- FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object)
{
copy_m4_m4(tmat, oblist[b]->obmat);
@@ -1059,7 +1064,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
mul_mat3_m4_fl(tmat, size * scale);
mul_v3_fl(tmat[3], size * scale);
- /* group dupli offset, should apply after everything else */
+ /* collection dupli offset, should apply after everything else */
if (!is_zero_v3(part->dup_group->dupli_ofs)) {
sub_v3_v3(tmat[3], part->dup_group->dupli_ofs);
}
@@ -1076,7 +1081,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
b++;
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
else {
/* to give ipos in object correct offset */
@@ -1130,7 +1135,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
/* restore objects since they were changed in BKE_object_where_is_calc_time */
if (part->ren_as == PART_DRAW_GR) {
- for (a = 0; a < totgroup; a++)
+ for (a = 0; a < totcollection; a++)
*(oblist[a]) = obcopylist[a];
}
else
@@ -1201,8 +1206,8 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
else if (transflag & OB_DUPLIFRAMES) {
return &gen_dupli_frames;
}
- else if (transflag & OB_DUPLIGROUP) {
- return &gen_dupli_group;
+ else if (transflag & OB_DUPLICOLLECTION) {
+ return &gen_dupli_collection;
}
return NULL;
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index dacd826084f..26c822f5fef 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -65,10 +65,10 @@
#include "BKE_boids.h"
#include "BKE_cloth.h"
+#include "BKE_collection.h"
#include "BKE_colortools.h"
#include "BKE_effect.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_lattice.h"
@@ -372,13 +372,19 @@ void psys_check_group_weights(ParticleSettings *part)
ParticleDupliWeight *dw, *tdw;
int current = 0;
- if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->view_layer->object_bases.first) {
+ if (part->ren_as != PART_DRAW_GR || !part->dup_group) {
+ BLI_freelistN(&part->dupliweights);
+ return;
+ }
+
+ const ListBase dup_group_objects = BKE_collection_object_cache_get(part->dup_group);
+ if (dup_group_objects.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)) {
- Base *base = BLI_findlink(&part->dup_group->view_layer->object_bases, dw->index);
+ if (dw->ob == NULL || !BKE_collection_has_object_recursive(part->dup_group, dw->ob)) {
+ Base *base = BLI_findlink(&dup_group_objects, dw->index);
if (base != NULL) {
dw->ob = base->object;
}
@@ -394,7 +400,7 @@ void psys_check_group_weights(ParticleSettings *part)
}
/* then add objects in the group to new list */
- FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object)
{
dw = part->dupliweights.first;
while (dw && dw->ob != object) {
@@ -408,7 +414,7 @@ void psys_check_group_weights(ParticleSettings *part)
BLI_addtail(&part->dupliweights, dw);
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
dw = part->dupliweights.first;
for (; dw; dw = dw->next) {
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 12b197070a2..7fd7b791a3f 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -59,6 +59,7 @@
#include "BKE_appdir.h"
#include "BKE_anim.h"
#include "BKE_cloth.h"
+#include "BKE_collection.h"
#include "BKE_dynamicpaint.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -1741,8 +1742,8 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
* for baking with linking dupligroups. Once we have better overrides
* this can be revisited so users select the local objects directly. */
if (scene && (duplis-- > 0) && (ob->dup_group)) {
- Group *group = ob->dup_group;
- Base *base = group->view_layer->object_bases.first;
+ Collection *collection = ob->dup_group;
+ Base *base = BKE_collection_object_cache_get(collection).first;
for (; base; base = base->next) {
if (base->object != ob) {
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 1c16d57ab12..5a9b5585efd 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -55,9 +55,9 @@
#include "DNA_scene_types.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_collection.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"
@@ -94,7 +94,7 @@ 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 */
if (rbw->constraints) {
- FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, object)
{
if (object->rigidbody_constraint) {
RigidBodyCon *rbc = object->rigidbody_constraint;
@@ -103,11 +103,11 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
}
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
if (rbw->group) {
- FOREACH_GROUP_OBJECT_BEGIN(rbw->group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object)
{
if (object->rigidbody_object) {
RigidBodyOb *rbo = object->rigidbody_object;
@@ -116,7 +116,7 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
}
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
/* free dynamics world */
RB_dworld_delete(rbw->physics_world);
@@ -1156,7 +1156,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
/* remove object from rigid body constraints */
if (rbw->constraints) {
- FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, obt)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, obt)
{
if (obt && obt->rigidbody_constraint) {
rbc = obt->rigidbody_constraint;
@@ -1165,7 +1165,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
}
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
@@ -1199,9 +1199,10 @@ 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)
{
+ const ListBase objects = BKE_collection_object_cache_get(rbw->group);
int i, n;
- n = BLI_listbase_count(&rbw->group->view_layer->object_bases);
+ n = BLI_listbase_count(&objects);
if (rbw->numbodies != n) {
rbw->numbodies = n;
@@ -1209,12 +1210,12 @@ static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
}
i = 0;
- FOREACH_GROUP_OBJECT_BEGIN(rbw->group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object)
{
rbw->objects[i] = object;
i++;
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
@@ -1340,7 +1341,7 @@ static void rigidbody_update_simulation(struct Depsgraph *depsgraph, Scene *scen
* Memory management needs redesign here, this is just a dirty workaround.
*/
if (rebuild && rbw->constraints) {
- FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, ob)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, ob)
{
RigidBodyCon *rbc = ob->rigidbody_constraint;
if (rbc && rbc->physics_constraint) {
@@ -1349,11 +1350,11 @@ static void rigidbody_update_simulation(struct Depsgraph *depsgraph, Scene *scen
rbc->physics_constraint = NULL;
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
/* update objects */
- FOREACH_GROUP_OBJECT_BEGIN(rbw->group, ob)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, ob)
{
if (ob->type == OB_MESH) {
/* validate that we've got valid object set up here... */
@@ -1396,13 +1397,13 @@ static void rigidbody_update_simulation(struct Depsgraph *depsgraph, Scene *scen
rigidbody_update_sim_ob(depsgraph, scene, rbw, ob, rbo);
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
/* update constraints */
if (rbw->constraints == NULL) /* no constraints, move on */
return;
- FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, ob)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, ob)
{
/* validate that we've got valid object set up here... */
RigidBodyCon *rbc = ob->rigidbody_constraint;
@@ -1430,12 +1431,12 @@ static void rigidbody_update_simulation(struct Depsgraph *depsgraph, Scene *scen
rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
{
- FOREACH_GROUP_BASE_BEGIN(rbw->group, base)
+ FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(rbw->group, base)
{
Object *ob = base->object;
RigidBodyOb *rbo = ob->rigidbody_object;
@@ -1448,7 +1449,7 @@ static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
RB_body_deactivate(rbo->physics_object);
}
}
- FOREACH_GROUP_BASE_END
+ FOREACH_COLLECTION_BASE_RECURSIVE_END
}
bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime)
@@ -1575,7 +1576,8 @@ void BKE_rigidbody_rebuild_world(struct Depsgraph *depsgraph, Scene *scene, floa
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->view_layer->object_bases)) {
+ const ListBase objects = BKE_collection_object_cache_get(rbw->group);
+ if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&objects)) {
cache->flag |= PTCACHE_OUTDATED;
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 950db7d7453..ea0498930ff 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -75,7 +75,6 @@
#include "BKE_freestyle.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
-#include "BKE_group.h"
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
@@ -244,20 +243,18 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
sce_dst->depsgraph_hash = NULL;
sce_dst->fps_info = NULL;
- /* layers and collections */
- sce_dst->collection = MEM_dupallocN(sce_src->collection);
- SceneCollection *mc_src = BKE_collection_master(&sce_src->id);
- SceneCollection *mc_dst = BKE_collection_master(&sce_dst->id);
-
- /* Recursively creates a new SceneCollection tree. */
- BKE_collection_copy_data(mc_dst, mc_src, flag_subdata);
+ /* Master Collection */
+ if (sce_src->master_collection) {
+ sce_dst->master_collection = BKE_collection_copy_master(bmain, sce_src->master_collection, flag);
+ }
+ /* View Layers */
BLI_duplicatelist(&sce_dst->view_layers, &sce_src->view_layers);
for (ViewLayer *view_layer_src = sce_src->view_layers.first, *view_layer_dst = sce_dst->view_layers.first;
view_layer_src;
view_layer_src = view_layer_src->next, view_layer_dst = view_layer_dst->next)
{
- BKE_view_layer_copy_data(view_layer_dst, view_layer_src, mc_dst, mc_src, flag_subdata);
+ BKE_view_layer_copy_data(sce_dst, sce_src, view_layer_dst, view_layer_src, flag_subdata);
}
BLI_duplicatelist(&(sce_dst->markers), &(sce_src->markers));
@@ -407,6 +404,9 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
BKE_id_copy_ex(bmain, (ID *)sce_copy->world, (ID **)&sce_copy->world, LIB_ID_COPY_ACTIONS, false);
}
+ /* Collections */
+ BKE_collection_copy_full(bmain, sce_copy->master_collection);
+
/* Full copy of GreasePencil. */
/* XXX Not copying anim/actions here? */
if (sce_copy->gpd) {
@@ -506,9 +506,15 @@ void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
}
/* Master Collection */
- BKE_collection_master_free(&sce->id, do_id_user);
- MEM_freeN(sce->collection);
- sce->collection = NULL;
+ // TODO: what to do with do_id_user? it's also true when just
+ // closing the file which seems wrong? should decrement users
+ // for objects directly in the master collection? then other
+ // collections in the scene need to do it too?
+ if (sce->master_collection) {
+ BKE_collection_free(sce->master_collection);
+ MEM_freeN(sce->master_collection);
+ sce->master_collection = NULL;
+ }
/* These are freed on doversion. */
BLI_assert(sce->layer_properties == NULL);
@@ -789,8 +795,7 @@ void BKE_scene_init(Scene *sce)
sce->orientation_index_custom = -1;
/* Master Collection */
- sce->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
- BLI_strncpy(sce->collection->name, "Master Collection", sizeof(sce->collection->name));
+ sce->master_collection = BKE_collection_master_add();
BKE_view_layer_add(sce, "View Layer");
@@ -910,29 +915,19 @@ Object *BKE_scene_object_find_by_name(Scene *scene, const char *name)
void BKE_scene_set_background(Main *bmain, Scene *scene)
{
Object *ob;
- Group *group;
/* check for cyclic sets, for reading old files but also for definite security (py?) */
BKE_scene_validate_setscene(bmain, scene);
/* deselect objects (for dataselect) */
for (ob = bmain->object.first; ob; ob = ob->id.next)
- ob->flag &= ~(SELECT | OB_FROMGROUP);
-
- /* group flags again */
- for (group = bmain->group.first; group; group = group->id.next) {
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- object->flag |= OB_FROMGROUP;
- }
- FOREACH_GROUP_OBJECT_END;
- }
+ ob->flag &= ~SELECT;
/* copy layers and flags from bases to objects */
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
ob = base->object;
- /* group patch... */
+ /* collection patch... */
BKE_scene_object_base_flag_sync_from_base(base);
}
}
@@ -1025,9 +1020,9 @@ int BKE_scene_base_iter_next(
else {
if (iter->phase != F_DUPLI) {
if (depsgraph && (*base)->object->transflag & OB_DUPLI) {
- /* groups cannot be duplicated for mballs yet,
+ /* collections cannot be duplicated for mballs yet,
* this enters eternal loop because of
- * makeDispListMBall getting called inside of group_duplilist */
+ * makeDispListMBall getting called inside of collection_duplilist */
if ((*base)->object->dup_group == NULL) {
iter->duplilist = object_duplilist_ex(depsgraph, (*scene), (*base)->object, false);
@@ -1087,11 +1082,11 @@ int BKE_scene_base_iter_next(
return iter->phase;
}
-Scene *BKE_scene_find_from_collection(const Main *bmain, const SceneCollection *scene_collection)
+Scene *BKE_scene_find_from_collection(const Main *bmain, const Collection *collection)
{
for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
for (ViewLayer *layer = scene->view_layers.first; layer; layer = layer->next) {
- if (BKE_view_layer_has_collection(layer, scene_collection)) {
+ if (BKE_view_layer_has_collection(layer, collection)) {
return scene;
}
}
@@ -1555,11 +1550,7 @@ void BKE_scene_object_base_flag_sync_from_base(Base *base)
{
Object *ob = base->object;
- /* keep the object only flags untouched */
- int flag = ob->flag & OB_FROMGROUP;
-
ob->flag = base->flag;
- ob->flag |= flag;
if ((base->flag & BASE_SELECTED) != 0) {
ob->flag |= SELECT;
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 0af400796a4..9aa6c172a90 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -71,10 +71,10 @@ variables on the UI for now
#include "BLI_ghash.h"
#include "BLI_threads.h"
+#include "BKE_collection.h"
#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"
@@ -514,20 +514,18 @@ static void ccd_build_deflector_hash_single(GHash *hash, Object *ob)
}
/**
- * \note group overrides scene when not NULL.
+ * \note collection overrides scene when not NULL.
*/
-static void ccd_build_deflector_hash(ViewLayer *view_layer, Group *group, Object *vertexowner, GHash *hash)
+static void ccd_build_deflector_hash(ViewLayer *view_layer, Collection *collection, Object *vertexowner, GHash *hash)
{
Object *ob;
if (!hash) return;
- /* Explicit collision group. */
- if (group) {
- view_layer = group->view_layer;
- }
+ /* Explicit collision collection. */
+ Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, collection);
- for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ for (; base; base = base->next) {
/* Only proceed for mesh object in same layer. */
if (base->object->type == OB_MESH) {
ob = base->object;
@@ -551,20 +549,18 @@ static void ccd_update_deflector_hash_single(GHash *hash, Object *ob)
}
/**
- * \note group overrides scene when not NULL.
+ * \note collection overrides scene when not NULL.
*/
-static void ccd_update_deflector_hash(ViewLayer *view_layer, Group *group, Object *vertexowner, GHash *hash)
+static void ccd_update_deflector_hash(ViewLayer *view_layer, Collection *collection, Object *vertexowner, GHash *hash)
{
Object *ob;
if ((!hash) || (!vertexowner)) return;
- /* Explicit collision group. */
- if (group) {
- view_layer = group->view_layer;
- }
+ /* Explicit collision collection. */
+ Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, collection);
- for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ for (; base; base = base->next) {
/* Only proceed for mesh object in same layer. */
if (base->object->type == OB_MESH) {
ob = base->object;
@@ -964,11 +960,11 @@ static void free_softbody_intern(SoftBody *sb)
/* +++ dependency information functions*/
/**
- * \note group overrides scene when not NULL.
+ * \note collection overrides scene when not NULL.
*/
-static bool are_there_deflectors(ViewLayer *view_layer)
+static bool are_there_deflectors(Base *first_base)
{
- for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ for (Base *base = first_base; base; base = base->next) {
if (base->object->pd) {
if (base->object->pd->deflect)
return 1;
@@ -978,9 +974,9 @@ static bool are_there_deflectors(ViewLayer *view_layer)
return 0;
}
-static int query_external_colliders(ViewLayer *view_layer, Group *group)
+static int query_external_colliders(ViewLayer *view_layer, Collection *collection)
{
- return(are_there_deflectors(group != NULL ? group->view_layer : view_layer));
+ return(are_there_deflectors(BKE_collection_or_layer_objects(NULL, NULL, view_layer, collection)));
}
/* --- dependency information functions*/
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 7b31415ddcf..8b5c64f4ecd 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -134,9 +134,10 @@ struct ID *BLO_library_link_named_part(struct Main *mainl, BlendHandle **bh, con
struct ID *BLO_library_link_named_part_ex(
struct Main *mainl, BlendHandle **bh,
const short idcode, const char *name, const int flag,
- struct Scene *scene, struct ViewLayer *view_layer);
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer);
void BLO_library_link_end(
- struct Main *mainl, BlendHandle **bh, int flag, struct Scene *scene, struct ViewLayer *view_layer);
+ struct Main *mainl, BlendHandle **bh, int flag,
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer);
void BLO_library_link_copypaste(struct Main *mainl, BlendHandle *bh);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 85c67047be0..44aa8a40993 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -123,13 +123,13 @@
#include "BKE_brush.h"
#include "BKE_cachefile.h"
#include "BKE_cloth.h"
+#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_global.h" // for G
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_library.h" // for which_libbase
#include "BKE_library_idmap.h"
@@ -258,9 +258,10 @@ static void *read_struct(FileData *fd, BHead *bh, const char *blockname);
static void direct_link_modifiers(FileData *fd, ListBase *lb);
static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name);
static BHead *find_bhead_from_idname(FileData *fd, const char *idname);
+
+#ifdef USE_COLLECTION_COMPAT_28
static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc);
-static SceneCollection *get_scene_collection_active_or_create(
- struct Scene *scene, struct ViewLayer *view_layer, const int flag);
+#endif
/* this function ensures that reports are printed,
* in the case of libraray linking errors this is important!
@@ -4835,7 +4836,7 @@ static void lib_link_object(FileData *fd, Main *main)
}
else {
ob->dup_group = NULL;
- ob->transflag &= ~OB_DUPLIGROUP;
+ ob->transflag &= ~OB_DUPLICOLLECTION;
}
ob->proxy = newlibadr_us(fd, ob->id.lib, ob->proxy);
@@ -5343,9 +5344,6 @@ static void direct_link_object(FileData *fd, Object *ob)
{
PartEff *paf;
- /* weak weak... this was only meant as draw flag, now is used in give_base_to_objects too */
- ob->flag &= ~OB_FROMGROUP;
-
/* XXX This should not be needed - but seems like it can happen in some cases, so for now play safe... */
ob->proxy_from = NULL;
@@ -5543,6 +5541,208 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->preview = direct_link_preview_image(fd, ob->preview);
}
+static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *view_settings)
+{
+ view_settings->curve_mapping = newdataadr(fd, view_settings->curve_mapping);
+
+ if (view_settings->curve_mapping)
+ direct_link_curvemapping(fd, view_settings->curve_mapping);
+}
+
+/* ***************** READ VIEW LAYER *************** */
+
+static void direct_link_layer_collections(FileData *fd, ListBase *lb, bool master)
+{
+ link_list(fd, lb);
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+#ifdef USE_COLLECTION_COMPAT_28
+ lc->scene_collection = newdataadr(fd, lc->scene_collection);
+#endif
+
+ /* Master collection is not a real datablock. */
+ if (master) {
+ lc->collection = newdataadr(fd, lc->collection);
+ }
+
+ direct_link_layer_collections(fd, &lc->layer_collections, false);
+ }
+}
+
+static void direct_link_view_layer(FileData *fd, ViewLayer *view_layer)
+{
+ view_layer->stats = NULL;
+ link_list(fd, &view_layer->object_bases);
+ view_layer->basact = newdataadr(fd, view_layer->basact);
+
+ direct_link_layer_collections(fd, &view_layer->layer_collections, true);
+ view_layer->active_collection = newdataadr(fd, view_layer->active_collection);
+
+ view_layer->id_properties = newdataadr(fd, view_layer->id_properties);
+ IDP_DirectLinkGroup_OrFree(&view_layer->id_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
+ link_list(fd, &(view_layer->freestyle_config.modules));
+ link_list(fd, &(view_layer->freestyle_config.linesets));
+
+ BLI_listbase_clear(&view_layer->drawdata);
+ view_layer->object_bases_array = NULL;
+ view_layer->object_bases_hash = NULL;
+}
+
+static void lib_link_layer_collection(FileData *fd, Library *lib, LayerCollection *layer_collection, bool master)
+{
+ /* Master collection is not a real datablock. */
+ if (!master) {
+ layer_collection->collection = newlibadr(fd, lib, layer_collection->collection);
+ }
+
+ for (LayerCollection *layer_collection_nested = layer_collection->layer_collections.first;
+ layer_collection_nested != NULL;
+ layer_collection_nested = layer_collection_nested->next)
+ {
+ lib_link_layer_collection(fd, lib, layer_collection_nested, false);
+ }
+}
+
+static void lib_link_view_layer(FileData *fd, Library *lib, ViewLayer *view_layer)
+{
+ /* tag scene layer to update for collection tree evaluation */
+ view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY;
+
+ for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) {
+ fmc->script = newlibadr(fd, lib, fmc->script);
+ }
+
+ for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) {
+ fls->linestyle = newlibadr_us(fd, lib, fls->linestyle);
+ fls->group = newlibadr_us(fd, lib, fls->group);
+ }
+
+ for (Base *base = view_layer->object_bases.first, *base_next = NULL; base; base = base_next) {
+ base_next = base->next;
+
+ /* we only bump the use count for the collection objects */
+ base->object = newlibadr(fd, lib, base->object);
+ base->flag |= BASE_DIRTY_ENGINE_SETTINGS;
+
+ if (base->object == NULL) {
+ /* Free in case linked object got lost. */
+ BLI_freelinkN(&view_layer->object_bases, base);
+ }
+ }
+
+ for (LayerCollection *layer_collection = view_layer->layer_collections.first;
+ layer_collection != NULL;
+ layer_collection = layer_collection->next)
+ {
+ lib_link_layer_collection(fd, lib, layer_collection, true);
+ }
+
+ IDP_LibLinkProperty(view_layer->id_properties, fd);
+}
+
+/* ***************** READ COLLECTION *************** */
+
+#ifdef USE_COLLECTION_COMPAT_28
+static void direct_link_scene_collection(FileData *fd, SceneCollection *sc)
+{
+ link_list(fd, &sc->objects);
+ link_list(fd, &sc->scene_collections);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ direct_link_scene_collection(fd, nsc);
+ }
+}
+
+static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollection *sc)
+{
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ link->data = newlibadr_us(fd, lib, link->data);
+ BLI_assert(link->data);
+ }
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ lib_link_scene_collection(fd, lib, nsc);
+ }
+}
+#endif
+
+static void direct_link_collection(FileData *fd, Collection *collection)
+{
+ link_list(fd, &collection->gobject);
+ link_list(fd, &collection->children);
+
+ collection->preview = direct_link_preview_image(fd, collection->preview);
+
+ collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
+ BLI_listbase_clear(&collection->object_cache);
+ BLI_listbase_clear(&collection->parents);
+
+#ifdef USE_COLLECTION_COMPAT_28
+ /* This runs before the very first doversion. */
+ if (collection->collection != NULL) {
+ collection->collection = newdataadr(fd, collection->collection);
+ direct_link_scene_collection(fd, collection->collection);
+ }
+
+ if (collection->view_layer != NULL) {
+ collection->view_layer = newdataadr(fd, collection->view_layer);
+ direct_link_view_layer(fd, collection->view_layer);
+ }
+#endif
+}
+
+static void lib_link_collection_data(FileData *fd, Library *lib, Collection *collection)
+{
+ for (CollectionObject *cob = collection->gobject.first, *cob_next = NULL; cob; cob = cob_next) {
+ cob_next = cob->next;
+ cob->ob = newlibadr_us(fd, lib, cob->ob);
+
+ if (cob->ob == NULL) {
+ BLI_assert(!"Collection linked object got lost"); // TODO: remove, only for testing now
+ BLI_freelinkN(&collection->gobject, cob);
+ }
+ }
+
+ for (CollectionChild *child = collection->children.first, *child_next = NULL; child; child = child_next) {
+ child_next = child->next;
+ child->collection = newlibadr_us(fd, lib, child->collection);
+
+ if (child->collection == NULL ||
+ BKE_collection_find_cycle(collection, child->collection))
+ {
+ BLI_assert(!"Collection child got lost"); // TODO: remove, only for testing now
+ BLI_freelinkN(&collection->children, child);
+ }
+ else {
+ CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), "CollectionParent");
+ cparent->collection = collection;
+ BLI_addtail(&child->collection->parents, cparent);
+ }
+ }
+}
+
+static void lib_link_collection(FileData *fd, Main *main)
+{
+ for (Collection *collection = main->collection.first; collection; collection = collection->id.next) {
+ if (collection->id.tag & LIB_TAG_NEED_LINK) {
+ collection->id.tag &= ~LIB_TAG_NEED_LINK;
+ IDP_LibLinkProperty(collection->id.properties, fd);
+
+#ifdef USE_COLLECTION_COMPAT_28
+ if (collection->collection) {
+ lib_link_scene_collection(fd, collection->id.lib, collection->collection);
+ }
+
+ if (collection->view_layer) {
+ lib_link_view_layer(fd, collection->id.lib, collection->view_layer);
+ }
+#endif
+
+ lib_link_collection_data(fd, collection->id.lib, collection);
+ }
+ }
+}
+
/* ************ READ SCENE ***************** */
/* patch for missing scene IDs, can't be in do-versions */
@@ -5605,41 +5805,6 @@ static bool scene_validate_setscene__liblink(Scene *sce, const int totscene)
}
#endif
-static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollection *sc)
-{
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- link->data = newlibadr_us(fd, lib, link->data);
- BLI_assert(link->data);
- }
-
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- lib_link_scene_collection(fd, lib, nsc);
- }
-}
-
-static void lib_link_view_layer(FileData *fd, Library *lib, ViewLayer *view_layer)
-{
- /* tag scene layer to update for collection tree evaluation */
- view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY;
-
- for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) {
- fmc->script = newlibadr(fd, lib, fmc->script);
- }
-
- for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) {
- fls->linestyle = newlibadr_us(fd, lib, fls->linestyle);
- fls->group = newlibadr_us(fd, lib, fls->group);
- }
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- /* we only bump the use count for the collection objects */
- base->object = newlibadr(fd, lib, base->object);
- base->flag |= BASE_DIRTY_ENGINE_SETTINGS;
- }
-
- IDP_LibLinkProperty(view_layer->id_properties, fd);
-}
-
static void lib_link_scene(FileData *fd, Main *main)
{
#ifdef USE_SETSCENE_CHECK
@@ -5750,7 +5915,7 @@ static void lib_link_scene(FileData *fd, Main *main)
BKE_sequencer_update_sound_bounds_all(sce);
- /* rigidbody world relies on it's linked groups */
+ /* rigidbody world relies on it's linked collections */
if (sce->rigidbody_world) {
RigidBodyWorld *rbw = sce->rigidbody_world;
if (rbw->group)
@@ -5780,7 +5945,15 @@ static void lib_link_scene(FileData *fd, Main *main)
/* Motion Tracking */
sce->clip = newlibadr_us(fd, sce->id.lib, sce->clip);
- lib_link_scene_collection(fd, sce->id.lib, sce->collection);
+#ifdef USE_COLLECTION_COMPAT_28
+ if (sce->collection) {
+ lib_link_scene_collection(fd, sce->id.lib, sce->collection);
+ }
+#endif
+
+ if (sce->master_collection) {
+ lib_link_collection_data(fd, sce->id.lib, sce->master_collection);
+ }
for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
lib_link_view_layer(fd, sce->id.lib, view_layer);
@@ -5881,57 +6054,6 @@ static void direct_link_sequence_modifiers(FileData *fd, ListBase *lb)
}
}
-static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *view_settings)
-{
- view_settings->curve_mapping = newdataadr(fd, view_settings->curve_mapping);
-
- if (view_settings->curve_mapping)
- direct_link_curvemapping(fd, view_settings->curve_mapping);
-}
-
-static void direct_link_scene_collection(FileData *fd, SceneCollection *sc)
-{
- link_list(fd, &sc->objects);
- link_list(fd, &sc->scene_collections);
-
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- direct_link_scene_collection(fd, nsc);
- }
-}
-
-static void direct_link_layer_collections(FileData *fd, ListBase *lb)
-{
- link_list(fd, lb);
- for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
- lc->scene_collection = newdataadr(fd, lc->scene_collection);
-
- link_list(fd, &lc->object_bases);
-
- for (LinkData *link = lc->object_bases.first; link; link = link->next) {
- link->data = newdataadr(fd, link->data);
- }
-
- direct_link_layer_collections(fd, &lc->layer_collections);
- }
-}
-
-static void direct_link_view_layer(FileData *fd, ViewLayer *view_layer)
-{
- view_layer->stats = NULL;
- link_list(fd, &view_layer->object_bases);
- view_layer->basact = newdataadr(fd, view_layer->basact);
- direct_link_layer_collections(fd, &view_layer->layer_collections);
-
- view_layer->id_properties = newdataadr(fd, view_layer->id_properties);
- IDP_DirectLinkGroup_OrFree(&view_layer->id_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
-
- link_list(fd, &(view_layer->freestyle_config.modules));
- link_list(fd, &(view_layer->freestyle_config.linesets));
-
- BLI_listbase_clear(&view_layer->drawdata);
- view_layer->object_bases_array = NULL;
-}
-
/**
* Workspaces store a render layer pointer which can only be read after scene is read.
*/
@@ -6206,11 +6328,18 @@ static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain)
direct_link_curvemapping(fd, &sce->r.mblur_shutter_curve);
+#ifdef USE_COLLECTION_COMPAT_28
/* this runs before the very first doversion */
if (sce->collection) {
sce->collection = newdataadr(fd, sce->collection);
direct_link_scene_collection(fd, sce->collection);
}
+#endif
+
+ if (sce->master_collection) {
+ sce->master_collection = newdataadr(fd, sce->master_collection);
+ direct_link_collection(fd, sce->master_collection);
+ }
/* insert into global old-new map for reading without UI (link_global accesses it again) */
link_glob_list(fd, &sce->view_layers);
@@ -7553,71 +7682,6 @@ static void lib_link_sound(FileData *fd, Main *main)
}
}
}
-/* ***************** READ GROUP *************** */
-
-static void direct_link_group(FileData *fd, Group *group)
-{
- link_list(fd, &group->gobject);
-
- group->preview = direct_link_preview_image(fd, group->preview);
-
- /* This runs before the very first doversion. */
- if (group->collection != NULL) {
- group->collection = newdataadr(fd, group->collection);
- direct_link_scene_collection(fd, group->collection);
- }
-
- if (group->view_layer != NULL) {
- group->view_layer = newdataadr(fd, group->view_layer);
- direct_link_view_layer(fd, group->view_layer);
- }
-}
-
-static void lib_link_group(FileData *fd, Main *main)
-{
- for (Group *group = main->group.first; group; group = group->id.next) {
- if (group->id.tag & LIB_TAG_NEED_LINK) {
- group->id.tag &= ~LIB_TAG_NEED_LINK;
- IDP_LibLinkProperty(group->id.properties, fd);
-
- if (group->view_layer == NULL) {
- /* Old file, this is required for doversion. */
- bool add_us = false;
-
- GroupObject *go, *gon;
- go = group->gobject.first;
- while (go) {
- gon = go->next;
- go->ob = newlibadr_real_us(fd, group->id.lib, go->ob);
- if (go->ob != NULL) {
- go->ob->flag |= OB_FROMGROUP;
- /* If group has an object, it increments user... */
- add_us = true;
- }
- else {
- /* Remove NULL objects. */
- BLI_remlink(&group->gobject, go);
- MEM_freeN(go);
- }
- go = gon;
- }
-
- if (add_us) {
- id_us_ensure_real(&group->id);
- }
- /* The rest of the read code is only for new files, skip it. */
- continue;
- }
-
- lib_link_scene_collection(fd, group->id.lib, group->collection);
- lib_link_view_layer(fd, group->id.lib, group->view_layer);
-
- if (!BLI_listbase_is_empty(&group->view_layer->object_bases)) {
- id_us_ensure_real(&group->id);
- }
- }
- }
-}
/* ***************** READ MOVIECLIP *************** */
@@ -8355,7 +8419,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
direct_link_lightprobe(fd, (LightProbe *)id);
break;
case ID_GR:
- direct_link_group(fd, (Group *)id);
+ direct_link_collection(fd, (Collection *)id);
break;
case ID_AR:
direct_link_armature(fd, (bArmature*)id);
@@ -8563,7 +8627,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_speaker(fd, main);
lib_link_lightprobe(fd, main);
lib_link_sound(fd, main);
- lib_link_group(fd, main);
+ lib_link_collection(fd, main);
lib_link_armature(fd, main);
lib_link_action(fd, main);
lib_link_vfont(fd, main);
@@ -8774,6 +8838,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
if (fd->memfile == NULL) {
/* Do not apply in undo case! */
BKE_main_override_static_update(bfd->main);
+ BKE_collections_after_lib_link(bfd->main);
}
lib_verify_nodetree(bfd->main, true);
@@ -9207,18 +9272,21 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting
}
}
-static void expand_group(FileData *fd, Main *mainvar, Group *group)
+static void expand_collection(FileData *fd, Main *mainvar, Collection *collection)
{
- GroupObject *go;
-
- for (go = group->gobject.first; go; go = go->next) {
- expand_doit(fd, mainvar, go->ob);
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ expand_doit(fd, mainvar, cob->ob);
}
- if (group->collection != NULL) {
- expand_scene_collection(fd, mainvar, group->collection);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ expand_doit(fd, mainvar, child->collection);
}
+#ifdef USE_COLLECTION_COMPAT_28
+ if (collection->collection != NULL) {
+ expand_scene_collection(fd, mainvar, collection->collection);
+ }
+#endif
}
static void expand_key(FileData *fd, Main *mainvar, Key *key)
@@ -9531,16 +9599,18 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
}
}
+#ifdef USE_COLLECTION_COMPAT_28
static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc)
{
for (LinkData *link = sc->objects.first; link; link = link->next) {
expand_doit(fd, mainvar, link->data);
}
- for (SceneCollection *nsc= sc->scene_collections.first; nsc; nsc = nsc->next) {
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
expand_scene_collection(fd, mainvar, nsc);
}
}
+#endif
static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
{
@@ -9626,7 +9696,15 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
expand_doit(fd, mainvar, sce->clip);
- expand_scene_collection(fd, mainvar, sce->collection);
+#ifdef USE_COLLECTION_COMPAT_28
+ if (sce->collection) {
+ expand_scene_collection(fd, mainvar, sce->collection);
+ }
+#endif
+
+ if (sce->master_collection) {
+ expand_collection(fd, mainvar, sce->master_collection);
+ }
}
static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
@@ -9833,7 +9911,7 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
expand_action(fd, mainvar, (bAction *)id); // XXX deprecated - old animation system
break;
case ID_GR:
- expand_group(fd, mainvar, (Group *)id);
+ expand_collection(fd, mainvar, (Collection *)id);
break;
case ID_NT:
expand_nodetree(fd, mainvar, (bNodeTree *)id);
@@ -9881,11 +9959,11 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
/* ***************************** */
-static bool object_in_any_scene(Main *mainvar, Object *ob)
+static bool object_in_any_scene(Main *bmain, Object *ob)
{
Scene *sce;
- for (sce = mainvar->scene.first; sce; sce = sce->id.next) {
+ for (sce = bmain->scene.first; sce; sce = sce->id.next) {
if (BKE_scene_object_find(sce, ob)) {
return true;
}
@@ -9894,25 +9972,34 @@ static bool object_in_any_scene(Main *mainvar, Object *ob)
return false;
}
-static void give_base_to_objects(
- Main *mainvar, Scene *scene, ViewLayer *view_layer, Library *lib, const short flag)
+static Collection *get_collection_active(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag)
+{
+ if (flag & FILE_ACTIVE_COLLECTION) {
+ LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
+ return lc->collection;
+ }
+ else {
+ return BKE_collection_add(bmain, scene->master_collection, NULL);
+ }
+}
+
+static void add_loose_objects_to_scene(
+ Main *mainvar, Main *bmain, Scene *scene, ViewLayer *view_layer, Library *lib, const short flag)
{
- Object *ob;
- Base *base;
- SceneCollection *scene_collection = NULL;
const bool is_link = (flag & FILE_LINK) != 0;
BLI_assert(scene);
- /* Give all objects which are LIB_TAG_INDIRECT a base, or for a group when *lib has been set. */
- for (ob = mainvar->object.first; ob; ob = ob->id.next) {
+ /* Give all objects which are LIB_TAG_INDIRECT a base, or for a collection when *lib has been set. */
+ for (Object *ob = mainvar->object.first; ob; ob = ob->id.next) {
if ((ob->id.tag & LIB_TAG_INDIRECT) && (ob->id.tag & LIB_TAG_PRE_EXISTING) == 0) {
bool do_it = false;
if (ob->id.us == 0) {
do_it = true;
}
- else if (!is_link && (ob->id.lib == lib) && (object_in_any_scene(mainvar, ob) == 0)) {
+ else if (!is_link && (ob->id.lib == lib) && (object_in_any_scene(bmain, ob) == 0)) {
/* When appending, make sure any indirectly loaded objects get a base, else they cant be accessed at all
* (see T27437). */
do_it = true;
@@ -9921,17 +10008,14 @@ static void give_base_to_objects(
if (do_it) {
CLAMP_MIN(ob->id.us, 0);
- if (scene_collection == NULL) {
- scene_collection = get_scene_collection_active_or_create(scene, view_layer, FILE_ACTIVE_COLLECTION);
- }
-
- BKE_collection_object_add(&scene->id, scene_collection, ob);
- base = BKE_view_layer_base_find(view_layer, ob);
+ Collection *active_collection = get_collection_active(bmain, scene, view_layer, FILE_ACTIVE_COLLECTION);
+ BKE_collection_object_add(bmain, active_collection, ob);
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
BKE_scene_object_base_flag_sync_from_base(base);
if (flag & FILE_AUTOSELECT) {
/* Note that link_object_postprocess() already checks for FILE_AUTOSELECT flag,
- * but it will miss objects from non-instantiated groups... */
+ * but it will miss objects from non-instantiated collections... */
if (base->flag & BASE_SELECTABLED) {
base->flag |= BASE_SELECTED;
BKE_scene_object_base_flag_sync_from_base(base);
@@ -9946,42 +10030,45 @@ static void give_base_to_objects(
}
}
-static void give_base_to_groups(
- Main *mainvar, Scene *scene, ViewLayer *view_layer, Library *UNUSED(lib), const short UNUSED(flag))
+static void add_collections_to_scene(
+ Main *mainvar, Main *bmain, Scene *scene, ViewLayer *view_layer, Library *UNUSED(lib), const short flag)
{
- Group *group;
- Base *base;
- Object *ob;
- SceneCollection *scene_collection;
-
- /* If the group is empty this function is not even called, so it's safe to ensure a collection at this point. */
- scene_collection = get_scene_collection_active_or_create(scene, view_layer, FILE_ACTIVE_COLLECTION);
+ Collection *active_collection = get_collection_active(bmain, scene, view_layer, FILE_ACTIVE_COLLECTION);
/* Give all objects which are tagged a base. */
- for (group = mainvar->group.first; group; group = group->id.next) {
- if (group->id.tag & LIB_TAG_DOIT) {
- /* Any indirect group should not have been tagged. */
- BLI_assert((group->id.tag & LIB_TAG_INDIRECT) == 0);
+ for (Collection *collection = mainvar->collection.first; collection; collection = collection->id.next) {
+ if (collection->id.tag & LIB_TAG_DOIT) {
+ if (flag & FILE_GROUP_INSTANCE) {
+ /* Any indirect collection should not have been tagged. */
+ BLI_assert((collection->id.tag & LIB_TAG_INDIRECT) == 0);
+
+ /* BKE_object_add(...) messes with the selection. */
+ Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2);
+ ob->type = OB_EMPTY;
- /* BKE_object_add(...) messes with the selection. */
- ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2);
- ob->type = OB_EMPTY;
+ BKE_collection_object_add(bmain, active_collection, ob);
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
- BKE_collection_object_add(&scene->id, scene_collection, ob);
- base = BKE_view_layer_base_find(view_layer, ob);
+ if (base->flag & BASE_SELECTABLED) {
+ base->flag |= BASE_SELECTED;
+ }
- if (base->flag & BASE_SELECTABLED) {
- base->flag |= BASE_SELECTED;
- }
+ BKE_scene_object_base_flag_sync_from_base(base);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ view_layer->basact = base;
- BKE_scene_object_base_flag_sync_from_base(base);
- DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- view_layer->basact = base;
+ /* Assign the collection. */
+ ob->dup_group = collection;
+ ob->transflag |= OB_DUPLICOLLECTION;
+ copy_v3_v3(ob->loc, scene->cursor.location);
+ }
+ else {
+ /* Add collection as child of active collection. */
+ BKE_collection_child_add(bmain, active_collection, collection);
- /* Assign the group. */
- ob->dup_group = group;
- ob->transflag |= OB_DUPLIGROUP;
- copy_v3_v3(ob->loc, scene->cursor.location);
+ collection->id.tag &= ~LIB_TAG_INDIRECT;
+ collection->id.tag |= LIB_TAG_EXTERN;
+ }
}
}
}
@@ -10055,35 +10142,19 @@ static ID *link_named_part(
return id;
}
-static SceneCollection *get_scene_collection_active_or_create(
- struct Scene *scene, struct ViewLayer *view_layer, const int flag)
-{
- LayerCollection *lc = NULL;
-
- if (flag & FILE_ACTIVE_COLLECTION) {
- lc = BKE_layer_collection_get_active_ensure(scene, view_layer);
- }
- else {
- SceneCollection *sc = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL);
- lc = BKE_collection_link(view_layer, sc);
- }
-
- return lc->scene_collection;
-}
-
-static void link_object_postprocess(ID *id, Scene *scene, ViewLayer *view_layer, const int flag)
+static void link_object_postprocess(ID *id, Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag)
{
if (scene) {
/* link to scene */
Base *base;
Object *ob;
- SceneCollection *sc;
+ Collection *collection;
ob = (Object *)id;
ob->mode = OB_MODE_OBJECT;
- sc = get_scene_collection_active_or_create(scene, view_layer, flag);
- BKE_collection_object_add(&scene->id, sc, ob);
+ collection = get_collection_active(bmain, scene, view_layer, flag);
+ BKE_collection_object_add(bmain, collection, ob);
base = BKE_view_layer_base_find(view_layer, ob);
BKE_scene_object_base_flag_sync_from_base(base);
@@ -10121,11 +10192,11 @@ void BLO_library_link_copypaste(Main *mainl, BlendHandle *bh)
id_sort_by_name(lb, id);
if (bhead->code == ID_OB) {
- /* Instead of instancing Base's directly, postpone until after groups are loaded
- * otherwise the base's flag is set incorrectly when groups are used */
+ /* Instead of instancing Base's directly, postpone until after collections are loaded
+ * otherwise the base's flag is set incorrectly when collections are used */
Object *ob = (Object *)id;
ob->mode = OB_MODE_OBJECT;
- /* ensure give_base_to_objects runs on this object */
+ /* ensure add_loose_objects_to_scene runs on this object */
BLI_assert(id->us == 0);
}
}
@@ -10134,17 +10205,16 @@ void BLO_library_link_copypaste(Main *mainl, BlendHandle *bh)
static ID *link_named_part_ex(
Main *mainl, FileData *fd, const short idcode, const char *name, const int flag,
- Scene *scene, ViewLayer *view_layer)
+ Main *bmain, Scene *scene, ViewLayer *view_layer)
{
ID *id = link_named_part(mainl, fd, idcode, name, flag);
if (id && (GS(id->name) == ID_OB)) { /* loose object: give a base */
- link_object_postprocess(id, scene, view_layer, flag);
+ link_object_postprocess(id, bmain, scene, view_layer, flag);
}
else if (id && (GS(id->name) == ID_GR)) {
- /* tag as needing to be instantiated */
- if (flag & FILE_GROUP_INSTANCE)
- id->tag |= LIB_TAG_DOIT;
+ /* tag as needing to be instantiated or linked */
+ id->tag |= LIB_TAG_DOIT;
}
return id;
@@ -10167,24 +10237,24 @@ ID *BLO_library_link_named_part(Main *mainl, BlendHandle **bh, const short idcod
/**
* Link a named datablock from an external blend file.
- * Optionally instantiate the object/group in the scene when the flags are set.
+ * Optionally instantiate the object/collection in the scene when the flags are set.
*
* \param mainl The main database to link from (not the active one).
* \param bh The blender file handle.
* \param idcode The kind of datablock to link.
* \param name The name of the datablock (without the 2 char ID prefix).
* \param flag Options for linking, used for instantiating.
- * \param scene The scene in which to instantiate objects/groups (if NULL, no instantiation is done).
- * \param v3d The active View3D (only to define active layers for instantiated objects & groups, can be NULL).
+ * \param scene The scene in which to instantiate objects/collections (if NULL, no instantiation is done).
+ * \param v3d The active View3D (only to define active layers for instantiated objects & collections, can be NULL).
* \return the linked ID when found.
*/
ID *BLO_library_link_named_part_ex(
Main *mainl, BlendHandle **bh,
const short idcode, const char *name, const int flag,
- Scene *scene, ViewLayer *view_layer)
+ Main *bmain, Scene *scene, ViewLayer *view_layer)
{
FileData *fd = (FileData*)(*bh);
- return link_named_part_ex(mainl, fd, idcode, name, flag, scene, view_layer);
+ return link_named_part_ex(mainl, fd, idcode, name, flag, bmain, scene, view_layer);
}
static void link_id_part(ReportList *reports, FileData *fd, Main *mainvar, ID *id, ID **r_id)
@@ -10237,8 +10307,8 @@ static Main *library_link_begin(Main *mainvar, FileData **fd, const char *filepa
(*fd)->mainlist = MEM_callocN(sizeof(ListBase), "FileData.mainlist");
- /* clear for group instantiating tag */
- BKE_main_id_tag_listbase(&(mainvar->group), LIB_TAG_DOIT, false);
+ /* clear for collection instantiating tag */
+ BKE_main_id_tag_listbase(&(mainvar->collection), LIB_TAG_DOIT, false);
/* make mains */
blo_split_main((*fd)->mainlist, mainvar);
@@ -10297,7 +10367,7 @@ static void split_main_newid(Main *mainptr, Main *main_newid)
}
/* scene and v3d may be NULL. */
-static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene *scene, ViewLayer *view_layer)
+static void library_link_end(Main *mainl, FileData **fd, const short flag, Main *bmain, Scene *scene, ViewLayer *view_layer)
{
Main *mainvar;
Library *curlib;
@@ -10327,6 +10397,7 @@ static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene
mainl = NULL; /* blo_join_main free's mainl, cant use anymore */
lib_link_all(*fd, mainvar);
+ BKE_collections_after_lib_link(mainvar);
/* Yep, second splitting... but this is a very cheap operation, so no big deal. */
blo_split_main((*fd)->mainlist, mainvar);
@@ -10350,22 +10421,19 @@ static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene
lib_verify_nodetree(mainvar, false);
fix_relpaths_library(G.main->name, mainvar); /* make all relative paths, relative to the open blend file */
- /* Give a base to loose objects. If group append, do it for objects too.
- * Only directly linked objects & groups are instantiated by `BLO_library_link_named_part_ex()` & co,
+ /* Give a base to loose objects and collections.
+ * Only directly linked objects & collections are instantiated by `BLO_library_link_named_part_ex()` & co,
* here we handle indirect ones and other possible edge-cases. */
if (scene) {
- give_base_to_objects(mainvar, scene, view_layer, curlib, flag);
-
- if (flag & FILE_GROUP_INSTANCE) {
- give_base_to_groups(mainvar, scene, view_layer, curlib, flag);
- }
+ add_collections_to_scene(mainvar, bmain, scene, view_layer, curlib, flag);
+ add_loose_objects_to_scene(mainvar, bmain, scene, view_layer, curlib, flag);
}
else {
/* printf("library_append_end, scene is NULL (objects wont get bases)\n"); */
}
- /* clear group instantiating tag */
- BKE_main_id_tag_listbase(&(mainvar->group), LIB_TAG_DOIT, false);
+ /* clear collection instantiating tag */
+ BKE_main_id_tag_listbase(&(mainvar->collection), LIB_TAG_DOIT, false);
/* patch to prevent switch_endian happens twice */
if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) {
@@ -10376,19 +10444,20 @@ static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene
/**
* Finalize linking from a given .blend file (library).
- * Optionally instance the indirect object/group in the scene when the flags are set.
+ * Optionally instance the indirect object/collection in the scene when the flags are set.
* \note Do not use \a bh after calling this function, it may frees it.
*
* \param mainl The main database to link from (not the active one).
* \param bh The blender file handle (WARNING! may be freed by this function!).
* \param flag Options for linking, used for instantiating.
- * \param scene The scene in which to instantiate objects/groups (if NULL, no instantiation is done).
- * \param view_layer The scene layer in which to instantiate objects/groups (if NULL, no instantiation is done).
+ * \param bmain The main database in which to instantiate objects/collections
+ * \param scene The scene in which to instantiate objects/collections (if NULL, no instantiation is done).
+ * \param view_layer The scene layer in which to instantiate objects/collections (if NULL, no instantiation is done).
*/
-void BLO_library_link_end(Main *mainl, BlendHandle **bh, int flag, Scene *scene, ViewLayer *view_layer)
+void BLO_library_link_end(Main *mainl, BlendHandle **bh, int flag, Main *bmain, Scene *scene, ViewLayer *view_layer)
{
FileData *fd = (FileData*)(*bh);
- library_link_end(mainl, &fd, flag, scene, view_layer);
+ library_link_end(mainl, &fd, flag, bmain, scene, view_layer);
*bh = (BlendHandle*)fd;
}
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 1d8bea40381..8e0795f7e34 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -2265,7 +2265,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
if (!ELEM(so->outlinevis,
SO_SCENES,
- SO_GROUPS,
SO_LIBRARIES,
SO_SEQUENCE,
SO_DATA_API))
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index c3a634f1e74..43302408dc4 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -59,7 +59,6 @@
#include "BKE_constraint.h"
#include "BKE_customdata.h"
#include "BKE_freestyle.h"
-#include "BKE_group.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
#include "BKE_main.h"
@@ -75,7 +74,6 @@
#include "MEM_guardedalloc.h"
-
static bScreen *screen_parent_find(const bScreen *screen)
{
/* can avoid lookup if screen state isn't maximized/full (parent and child store the same state) */
@@ -185,6 +183,162 @@ static void do_version_workspaces_after_lib_link(Main *bmain)
}
}
+#ifdef USE_COLLECTION_COMPAT_28
+enum {
+ COLLECTION_DEPRECATED_VISIBLE = (1 << 0),
+ COLLECTION_DEPRECATED_VIEWPORT = (1 << 0),
+ COLLECTION_DEPRECATED_SELECTABLE = (1 << 1),
+ COLLECTION_DEPRECATED_DISABLED = (1 << 2),
+ COLLECTION_DEPRECATED_RENDER = (1 << 3),
+};
+
+static void do_version_view_layer_visibility(ViewLayer *view_layer)
+{
+ /* Convert from deprecated VISIBLE flag to DISABLED */
+ LayerCollection *lc;
+ for (lc = view_layer->layer_collections.first;
+ lc;
+ lc = lc->next)
+ {
+ if (lc->flag & COLLECTION_DEPRECATED_DISABLED) {
+ lc->flag &= ~COLLECTION_DEPRECATED_DISABLED;
+ }
+
+ if ((lc->flag & COLLECTION_DEPRECATED_VISIBLE) == 0) {
+ lc->flag |= COLLECTION_DEPRECATED_DISABLED;
+ }
+
+ lc->flag |= COLLECTION_DEPRECATED_VIEWPORT | COLLECTION_DEPRECATED_RENDER;
+ }
+}
+
+static void do_version_layer_collection_pre(ViewLayer *view_layer,
+ ListBase *lb,
+ GSet *enabled_set,
+ GSet *selectable_set)
+{
+ /* Convert from deprecated DISABLED to new layer collection and collection flags */
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ if (lc->scene_collection) {
+ if (!(lc->flag & COLLECTION_DEPRECATED_DISABLED)) {
+ BLI_gset_insert(enabled_set, lc->scene_collection);
+ }
+ if (lc->flag & COLLECTION_DEPRECATED_SELECTABLE) {
+ BLI_gset_insert(selectable_set, lc->scene_collection);
+ }
+ }
+
+ do_version_layer_collection_pre(view_layer, &lc->layer_collections, enabled_set, selectable_set);
+ }
+}
+
+static void do_version_layer_collection_post(ViewLayer *view_layer,
+ ListBase *lb,
+ GSet *enabled_set,
+ GSet *selectable_set,
+ GHash *collection_map)
+{
+ /* Apply layer collection exclude flags. */
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ if (!(lc->collection->flag & COLLECTION_IS_MASTER)) {
+ SceneCollection *sc = BLI_ghash_lookup(collection_map, lc->collection);
+ const bool enabled = (sc && BLI_gset_haskey(enabled_set, sc));
+ const bool selectable = (sc && BLI_gset_haskey(selectable_set, sc));
+
+ if (!enabled) {
+ lc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
+ if (enabled && !selectable) {
+ lc->collection->flag |= COLLECTION_RESTRICT_SELECT;
+ }
+ }
+
+ do_version_layer_collection_post(view_layer, &lc->layer_collections, enabled_set, selectable_set, collection_map);
+ }
+}
+
+static void do_version_scene_collection_convert(Main *bmain,
+ SceneCollection *sc,
+ Collection *collection,
+ GHash *collection_map)
+{
+ if (collection_map) {
+ BLI_ghash_insert(collection_map, collection, sc);
+ }
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc;) {
+ SceneCollection *nsc_next = nsc->next;
+ Collection *ncollection = BKE_collection_add(bmain, collection, nsc->name);
+ do_version_scene_collection_convert(bmain, nsc, ncollection, collection_map);
+ nsc = nsc_next;
+ }
+
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ Object *ob = link->data;
+ if (ob) {
+ BKE_collection_object_add(bmain, collection, ob);
+ id_us_min(&ob->id);
+ }
+ }
+
+ BLI_freelistN(&sc->objects);
+ MEM_freeN(sc);
+}
+
+static void do_version_group_collection_to_collection(Main *bmain, Collection *group)
+{
+ /* Convert old 2.8 group collections to new unified collections. */
+ if (group->collection) {
+ do_version_scene_collection_convert(bmain, group->collection, group, NULL);
+ }
+
+ group->collection = NULL;
+ id_fake_user_set(&group->id);
+}
+
+static void do_version_scene_collection_to_collection(Main *bmain, Scene *scene)
+{
+ /* Convert old 2.8 scene collections to new unified collections. */
+
+ /* Temporarily clear view layers so we don't do any layer collection syncing
+ * and destroy old flags that we want to restore. */
+ ListBase view_layers = scene->view_layers;
+ BLI_listbase_clear(&scene->view_layers);
+
+ if (!scene->master_collection) {
+ scene->master_collection = BKE_collection_master_add();
+ }
+
+ /* Convert scene collections. */
+ GHash *collection_map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ if (scene->collection) {
+ do_version_scene_collection_convert(bmain, scene->collection, scene->master_collection, collection_map);
+ scene->collection = NULL;
+ }
+
+ scene->view_layers = view_layers;
+
+ /* Convert layer collections. */
+ ViewLayer *view_layer;
+ for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ GSet *enabled_set = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ GSet *selectable_set = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+
+ do_version_layer_collection_pre(view_layer, &view_layer->layer_collections, enabled_set, selectable_set);
+ BKE_layer_collection_sync(scene, view_layer);
+ do_version_layer_collection_post(view_layer, &view_layer->layer_collections, enabled_set, selectable_set, collection_map);
+
+ BLI_gset_free(enabled_set, NULL);
+ BLI_gset_free(selectable_set, NULL);
+
+ BKE_layer_collection_sync(scene, view_layer);
+ }
+
+ BLI_ghash_free(collection_map, NULL, NULL);
+}
+#endif
+
+
enum {
DO_VERSION_COLLECTION_VISIBLE = 0,
DO_VERSION_COLLECTION_HIDE = 1,
@@ -192,311 +346,348 @@ enum {
DO_VERSION_COLLECTION_HIDE_ALL = 3,
};
-void do_versions_after_linking_280(Main *main)
+static void do_version_layers_to_collections(Main *bmain, Scene *scene)
{
- if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
- for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
- /* since we don't have access to FileData we check the (always valid) first render layer instead */
- if (scene->view_layers.first == NULL) {
- SceneCollection *sc_master = BKE_collection_master(&scene->id);
- BLI_strncpy(sc_master->name, "Master Collection", sizeof(sc_master->name));
-
- struct DoVersionSceneCollections {
- SceneCollection *collections[20];
- int created;
- const char *suffix;
- int flag_viewport;
- int flag_render;
- } collections[] =
- {
- {
- .collections = {NULL},
- .created = 0,
- .suffix = "",
- .flag_viewport = COLLECTION_SELECTABLE,
- .flag_render = COLLECTION_SELECTABLE
- },
- {
- .collections = {NULL},
- .created = 0,
- .suffix = " - Hide Viewport",
- .flag_viewport = COLLECTION_SELECTABLE,
- .flag_render = COLLECTION_SELECTABLE
- },
- {
- .collections = {NULL},
- .created = 0,
- .suffix = " - Hide Render",
- .flag_viewport = COLLECTION_SELECTABLE,
- .flag_render = COLLECTION_SELECTABLE | COLLECTION_DISABLED
- },
- {
- .collections = {NULL},
- .created = 0,
- .suffix = " - Hide Render All",
- .flag_viewport = COLLECTION_SELECTABLE | COLLECTION_DISABLED,
- .flag_render = COLLECTION_SELECTABLE | COLLECTION_DISABLED
- }
- };
-
- for (int layer = 0; layer < 20; layer++) {
- for (Base *base = scene->base.first; base; base = base->next) {
- if (base->lay & (1 << layer)) {
- int collection_index = -1;
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) &&
- (base->object->restrictflag & OB_RESTRICT_RENDER))
- {
- collection_index = DO_VERSION_COLLECTION_HIDE_ALL;
- }
- else if (base->object->restrictflag & OB_RESTRICT_VIEW) {
- collection_index = DO_VERSION_COLLECTION_HIDE;
- }
- else if (base->object->restrictflag & OB_RESTRICT_RENDER) {
- collection_index = DO_VERSION_COLLECTION_HIDE_RENDER;
- }
- else {
- collection_index = DO_VERSION_COLLECTION_VISIBLE;
- }
+ /* Since we don't have access to FileData we check the (always valid) first
+ * render layer instead. */
+ if (!scene->master_collection) {
+ scene->master_collection = BKE_collection_master_add();
+ }
- /* Create collections when needed only. */
- if ((collections[collection_index].created & (1 << layer)) == 0) {
- char name[MAX_NAME];
-
- if ((collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) == 0) {
- BLI_snprintf(name,
- sizeof(sc_master->name),
- "Collection %d%s",
- layer + 1,
- collections[DO_VERSION_COLLECTION_VISIBLE].suffix);
- collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer] =
- BKE_collection_add(&scene->id, sc_master, COLLECTION_TYPE_NONE, name);
- collections[DO_VERSION_COLLECTION_VISIBLE].created |= (1 << layer);
- }
-
- if (collection_index != DO_VERSION_COLLECTION_VISIBLE) {
- SceneCollection *sc_parent;
- sc_parent = collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer];
- BLI_snprintf(name,
- sizeof(sc_master->name),
- "Collection %d%s",
- layer + 1,
- collections[collection_index].suffix);
- collections[collection_index].collections[layer] = BKE_collection_add(
- &scene->id,
- sc_parent,
- COLLECTION_TYPE_NONE,
- name);
- collections[collection_index].created |= (1 << layer);
- }
- }
+ if (scene->view_layers.first) {
+ return;
+ }
- BKE_collection_object_add(
- &scene->id, collections[collection_index].collections[layer], base->object);
- }
+ /* Create collections from layers. */
+ Collection *collection_master = BKE_collection_master(scene);
- if (base->flag & SELECT) {
- base->object->flag |= SELECT;
- }
- else {
- base->object->flag &= ~SELECT;
- }
- }
+ struct DoVersionSceneCollections {
+ Collection *collections[20];
+ int created;
+ const char *suffix;
+ int flag;
+ } collections[] =
+ {
+ {
+ .collections = {NULL},
+ .created = 0,
+ .suffix = "",
+ .flag = 0,
+ },
+ {
+ .collections = {NULL},
+ .created = 0,
+ .suffix = " - Hide Viewport",
+ .flag = COLLECTION_RESTRICT_VIEW,
+ },
+ {
+ .collections = {NULL},
+ .created = 0,
+ .suffix = " - Hide Render",
+ .flag = COLLECTION_RESTRICT_RENDER,
+ },
+ {
+ .collections = {NULL},
+ .created = 0,
+ .suffix = " - Hide Render All",
+ .flag = COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER,
+ }
+ };
+
+ for (int layer = 0; layer < 20; layer++) {
+ for (Base *base = scene->base.first; base; base = base->next) {
+ if (base->lay & (1 << layer)) {
+ int collection_index = -1;
+ if ((base->object->restrictflag & OB_RESTRICT_VIEW) &&
+ (base->object->restrictflag & OB_RESTRICT_RENDER))
+ {
+ collection_index = DO_VERSION_COLLECTION_HIDE_ALL;
+ }
+ else if (base->object->restrictflag & OB_RESTRICT_VIEW) {
+ collection_index = DO_VERSION_COLLECTION_HIDE;
+ }
+ else if (base->object->restrictflag & OB_RESTRICT_RENDER) {
+ collection_index = DO_VERSION_COLLECTION_HIDE_RENDER;
+ }
+ else {
+ collection_index = DO_VERSION_COLLECTION_VISIBLE;
}
- /* Re-order the nested hidden collections. */
- SceneCollection *scene_collection_parent = sc_master->scene_collections.first;
+ /* Create collections when needed only. */
+ if ((collections[collection_index].created & (1 << layer)) == 0) {
+ char name[MAX_NAME];
- for (int layer = 0; layer < 20; layer++) {
- if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) {
+ if ((collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) == 0) {
+ BLI_snprintf(name,
+ sizeof(collection_master->id.name),
+ "Collection %d%s",
+ layer + 1,
+ collections[DO_VERSION_COLLECTION_VISIBLE].suffix);
- if ((collections[DO_VERSION_COLLECTION_HIDE].created & (1 << layer)) &&
- (collections[DO_VERSION_COLLECTION_HIDE].collections[layer] !=
- scene_collection_parent->scene_collections.first))
- {
- BLI_listbase_swaplinks(
- &scene_collection_parent->scene_collections,
- collections[DO_VERSION_COLLECTION_HIDE].collections[layer],
- scene_collection_parent->scene_collections.first);
- }
+ Collection *collection = BKE_collection_add(bmain, collection_master, name);
+ collection->flag |= collections[DO_VERSION_COLLECTION_VISIBLE].flag;
+ collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer] = collection;
+ collections[DO_VERSION_COLLECTION_VISIBLE].created |= (1 << layer);
- if ((collections[DO_VERSION_COLLECTION_HIDE_ALL].created & (1 << layer)) &&
- (collections[DO_VERSION_COLLECTION_HIDE_ALL].collections[layer] !=
- scene_collection_parent->scene_collections.last))
- {
- BLI_listbase_swaplinks(
- &scene_collection_parent->scene_collections,
- collections[DO_VERSION_COLLECTION_HIDE_ALL].collections[layer],
- scene_collection_parent->scene_collections.last);
+ if (!(scene->lay & (1 << layer))) {
+ collection->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER;
}
+ }
- scene_collection_parent = scene_collection_parent->next;
+ if (collection_index != DO_VERSION_COLLECTION_VISIBLE) {
+ Collection *collection_parent;
+ collection_parent = collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer];
+ BLI_snprintf(name,
+ sizeof(collection_master->id.name),
+ "Collection %d%s",
+ layer + 1,
+ collections[collection_index].suffix);
+
+ Collection *collection = BKE_collection_add(bmain, collection_parent, name);
+ collection->flag |= collections[collection_index].flag;
+ collections[collection_index].collections[layer] = collection;
+ collections[collection_index].created |= (1 << layer);
+
+ if (!(scene->lay & (1 << layer))) {
+ collection->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER;
+ }
}
}
- BLI_assert(scene_collection_parent == NULL);
- /* Handle legacy render layers. */
- {
- for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
-
- ViewLayer *view_layer = BKE_view_layer_add(scene, srl->name);
-
- if (srl->samples != 0) {
- /* It is up to the external engine to handle
- * its own doversion in this case. */
- BKE_override_view_layer_int_add(
- view_layer,
- ID_SCE,
- "samples",
- srl->samples);
- }
+ /* Note usually this would do slow collection syncing for view layers,
+ * but since no view layers exists yet at this point it's fast. */
+ BKE_collection_object_add(bmain,
+ collections[collection_index].collections[layer], base->object);
+ }
- if (srl->mat_override) {
- BKE_override_view_layer_datablock_add(
- view_layer,
- ID_MA,
- "self",
- (ID *)srl->mat_override);
- }
+ if (base->flag & SELECT) {
+ base->object->flag |= SELECT;
+ }
+ else {
+ base->object->flag &= ~SELECT;
+ }
+ }
+ }
- if (srl->layflag & SCE_LAY_DISABLE) {
- view_layer->flag &= ~VIEW_LAYER_RENDER;
- }
+ /* Re-order the nested hidden collections. */
+ CollectionChild *child_parent = collection_master->children.first;
+ Collection *collection_parent = (child_parent) ? child_parent->collection : NULL;
- if ((srl->layflag & SCE_LAY_FRS) == 0) {
- view_layer->flag &= ~VIEW_LAYER_FREESTYLE;
- }
+ for (int layer = 0; layer < 20; layer++) {
+ if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) {
+ CollectionChild *hide_child = BLI_findptr(&collection_parent->children, collections[DO_VERSION_COLLECTION_HIDE].collections[layer], offsetof(CollectionChild, collection));
- /* XXX If we are to keep layflag it should be merged with flag (dfelinto). */
- view_layer->layflag = srl->layflag;
- /* XXX Not sure if we should keep the passes (dfelinto). */
- view_layer->passflag = srl->passflag;
- view_layer->pass_xor = srl->pass_xor;
- view_layer->pass_alpha_threshold = srl->pass_alpha_threshold;
+ if ((collections[DO_VERSION_COLLECTION_HIDE].created & (1 << layer)) &&
+ (hide_child != collection_parent->children.first))
+ {
+ BLI_listbase_swaplinks(
+ &collection_parent->children,
+ hide_child,
+ collection_parent->children.first);
+ }
- BKE_freestyle_config_free(&view_layer->freestyle_config, true);
- view_layer->freestyle_config = srl->freestyleConfig;
- view_layer->id_properties = srl->prop;
+ CollectionChild *hide_all_child = BLI_findptr(&collection_parent->children, collections[DO_VERSION_COLLECTION_HIDE_ALL].collections[layer], offsetof(CollectionChild, collection));
- /* unlink master collection */
- BKE_collection_unlink(view_layer, view_layer->layer_collections.first);
+ if ((collections[DO_VERSION_COLLECTION_HIDE_ALL].created & (1 << layer)) &&
+ (hide_all_child != collection_parent->children.last))
+ {
+ BLI_listbase_swaplinks(
+ &collection_parent->children,
+ hide_all_child,
+ collection_parent->children.last);
+ }
- /* Add new collection bases. */
- for (int layer = 0; layer < 20; layer++) {
- if ((scene->lay & srl->lay & ~(srl->lay_exclude) & (1 << layer)) ||
- (srl->lay_zmask & (scene->lay | srl->lay_exclude) & (1 << layer)))
- {
- if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) {
-
- LayerCollection *layer_collection_parent;
- layer_collection_parent = BKE_collection_link(
- view_layer,
- collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer]);
-
- if (srl->lay_zmask & (1 << layer)) {
- BKE_override_layer_collection_boolean_add(
- layer_collection_parent,
- ID_OB,
- "cycles.is_holdout",
- true);
- }
-
- if ((srl->lay & (1 << layer)) == 0) {
- BKE_override_layer_collection_boolean_add(
- layer_collection_parent,
- ID_OB,
- "cycles_visibility.camera",
- false);
- }
-
- LayerCollection *layer_collection_child;
- layer_collection_child = layer_collection_parent->layer_collections.first;
-
- for (int j = 1; j < 4; j++) {
- if (collections[j].created & (1 << layer)) {
- layer_collection_child->flag = COLLECTION_VIEWPORT |
- COLLECTION_RENDER |
- collections[j].flag_render;
- layer_collection_child = layer_collection_child->next;
- }
- }
- BLI_assert(layer_collection_child == NULL);
- }
- }
- }
+ child_parent = child_parent->next;
+ collection_parent = (child_parent) ? child_parent->collection : NULL;
+ }
+ }
+ BLI_assert(collection_parent == NULL);
- /* for convenience set the same active object in all the layers */
- if (scene->basact) {
- view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object);
- }
+ /* Handle legacy render layers. */
+ bool have_override = false;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if ((base->flag & BASE_SELECTABLED) && (base->object->flag & SELECT)) {
- base->flag |= BASE_SELECTED;
- }
- }
- }
- }
- BLI_freelistN(&scene->r.layers);
+ for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
+ ViewLayer *view_layer = BKE_view_layer_add(scene, srl->name);
- ViewLayer *view_layer = BKE_view_layer_add(scene, "Viewport");
- /* If we ported all the original render layers, we don't need to make the viewport layer renderable. */
- if (!BLI_listbase_is_single(&scene->view_layers)) {
- view_layer->flag &= ~VIEW_LAYER_RENDER;
- }
+ if (srl->samples != 0) {
+ have_override = true;
- /* If layer was not set, disable it. */
- LayerCollection *layer_collection_parent;
- layer_collection_parent =
- ((LayerCollection *)view_layer->layer_collections.first)->layer_collections.first;
+ /* It is up to the external engine to handle
+ * its own doversion in this case. */
+ BKE_override_view_layer_int_add(
+ view_layer,
+ ID_SCE,
+ "samples",
+ srl->samples);
+ }
- for (int layer = 0; layer < 20; layer++) {
- if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) {
- const bool is_disabled = (scene->lay & (1 << layer)) == 0;
+ if (srl->mat_override) {
+ have_override = true;
- /* We only need to disable the parent collection. */
- if (is_disabled) {
- layer_collection_parent->flag |= COLLECTION_DISABLED;
- }
+ BKE_override_view_layer_datablock_add(
+ view_layer,
+ ID_MA,
+ "self",
+ (ID *)srl->mat_override);
+ }
- LayerCollection *layer_collection_child;
- layer_collection_child = layer_collection_parent->layer_collections.first;
+ if (srl->layflag & SCE_LAY_DISABLE) {
+ view_layer->flag &= ~VIEW_LAYER_RENDER;
+ }
- for (int j = 1; j < 4; j++) {
- if (collections[j].created & (1 << layer)) {
- layer_collection_child->flag = COLLECTION_VIEWPORT |
- COLLECTION_RENDER |
- collections[j].flag_viewport;
- layer_collection_child = layer_collection_child->next;
- }
- }
- BLI_assert(layer_collection_child == NULL);
- layer_collection_parent = layer_collection_parent->next;
+ if ((srl->layflag & SCE_LAY_FRS) == 0) {
+ view_layer->flag &= ~VIEW_LAYER_FREESTYLE;
+ }
+
+ /* XXX If we are to keep layflag it should be merged with flag (dfelinto). */
+ view_layer->layflag = srl->layflag;
+ /* XXX Not sure if we should keep the passes (dfelinto). */
+ view_layer->passflag = srl->passflag;
+ view_layer->pass_xor = srl->pass_xor;
+ view_layer->pass_alpha_threshold = srl->pass_alpha_threshold;
+
+ BKE_freestyle_config_free(&view_layer->freestyle_config, true);
+ view_layer->freestyle_config = srl->freestyleConfig;
+ view_layer->id_properties = srl->prop;
+
+ /* Set exclusion and overrides. */
+ for (int layer = 0; layer < 20; layer++) {
+ if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) {
+ Collection *collection = collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer];
+ LayerCollection *lc = BKE_layer_collection_first_from_scene_collection(view_layer, collection);
+
+ if (srl->lay_exclude & (1 << layer)) {
+ /* Disable excluded layer. */
+ have_override = true;
+ lc->flag |= LAYER_COLLECTION_EXCLUDE;
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ nlc->flag |= LAYER_COLLECTION_EXCLUDE;
}
}
- BLI_assert(layer_collection_parent == NULL);
+ else if ((scene->lay & srl->lay & ~(srl->lay_exclude) & (1 << layer)) ||
+ (srl->lay_zmask & (scene->lay | srl->lay_exclude) & (1 << layer)))
+ {
+ if (srl->lay_zmask & (1 << layer)) {
+ have_override = true;
+
+ BKE_override_layer_collection_boolean_add(
+ lc,
+ ID_OB,
+ "cycles.is_holdout",
+ true);
+ }
- /* convert active base */
- if (scene->basact) {
- view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object);
- }
+ if ((srl->lay & (1 << layer)) == 0) {
+ have_override = true;
- /* convert selected bases */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if ((base->flag & BASE_SELECTABLED) && (base->object->flag & SELECT)) {
- base->flag |= BASE_SELECTED;
+ BKE_override_layer_collection_boolean_add(
+ lc,
+ ID_OB,
+ "cycles_visibility.camera",
+ false);
}
+ }
- /* keep lay around for forward compatibility (open those files in 2.79) */
- base->lay = base->object->lay;
+ LayerCollection *nlc = lc->layer_collections.first;
+ for (int j = 1; j < 4; j++) {
+ if (collections[j].created & (1 << layer)) {
+ nlc = nlc->next;
+ }
}
+ BLI_assert(nlc == NULL);
+ }
+ }
+
+ /* for convenience set the same active object in all the layers */
+ if (scene->basact) {
+ view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object);
+ }
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) && (base->object->flag & SELECT)) {
+ base->flag |= BASE_SELECTED;
+ }
+ }
+ }
+
+ BLI_freelistN(&scene->r.layers);
+
+ /* If render layers included overrides, we also create a vanilla
+ * viewport layer without them. */
+ if (have_override) {
+ ViewLayer *view_layer = BKE_view_layer_add(scene, "Viewport");
+
+ /* Make it first in the list. */
+ BLI_remlink(&scene->view_layers, view_layer);
+ BLI_addhead(&scene->view_layers, view_layer);
+
+ /* If we ported all the original render layers, we don't need to make the viewport layer renderable. */
+ if (!BLI_listbase_is_single(&scene->view_layers)) {
+ view_layer->flag &= ~VIEW_LAYER_RENDER;
+ }
+
+ /* convert active base */
+ if (scene->basact) {
+ view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object);
+ }
+
+ /* convert selected bases */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) && (base->object->flag & SELECT)) {
+ base->flag |= BASE_SELECTED;
+ }
- /* remove bases once and for all */
- for (Base *base = scene->base.first; base; base = base->next) {
- id_us_min(&base->object->id);
+ /* keep lay around for forward compatibility (open those files in 2.79) */
+ base->lay = base->object->lay;
+ }
+ }
+
+ /* remove bases once and for all */
+ for (Base *base = scene->base.first; base; base = base->next) {
+ id_us_min(&base->object->id);
+ }
+
+ BLI_freelistN(&scene->base);
+ scene->basact = NULL;
+}
+
+void do_versions_after_linking_280(Main *main)
+{
+ bool use_collection_compat_28 = true;
+
+ if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
+ use_collection_compat_28 = false;
+
+ /* Convert group layer visibility flags to hidden nested collection. */
+ for (Collection *collection = main->collection.first; collection; collection = collection->id.next) {
+ Collection *collection_hidden = NULL;
+
+ if (collection->flag & (COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER)) {
+ continue;
+ }
+
+ for (CollectionObject *cob = collection->gobject.first, *cob_next = NULL; cob; cob = cob_next) {
+ cob_next = cob->next;
+ Object *ob = cob->ob;
+
+ if (!(ob->lay & collection->layer)) {
+ if (collection_hidden == NULL) {
+ collection_hidden = BKE_collection_add(main, collection, "Hidden");
+ collection_hidden->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER;
+ }
+
+ BKE_collection_object_add(main, collection_hidden, ob);
+ BKE_collection_object_remove(main, collection, ob, true);
}
- BLI_freelistN(&scene->base);
- scene->basact = NULL;
}
+
+ /* Add fake user for all existing groups. */
+ id_fake_user_set(&collection->id);
+ }
+
+ /* Convert layers to collections. */
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ do_version_layers_to_collections(main, scene);
}
}
@@ -507,11 +698,11 @@ void do_versions_after_linking_280(Main *main)
ViewLayer *layer = screen->scene->view_layers.first;
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- for (SpaceLink *view_layer = sa->spacedata.first; view_layer; view_layer = view_layer->next) {
- if (view_layer->spacetype == SPACE_OUTLINER) {
- SpaceOops *soutliner = (SpaceOops *)view_layer;
+ for (SpaceLink *space = sa->spacedata.first; space; space = space->next) {
+ if (space->spacetype == SPACE_OUTLINER) {
+ SpaceOops *soutliner = (SpaceOops *)space;
- soutliner->outlinevis = SO_COLLECTIONS;
+ soutliner->outlinevis = SO_VIEW_LAYER;
if (BLI_listbase_count_at_most(&layer->layer_collections, 2) == 1) {
if (soutliner->treestore == NULL) {
@@ -566,7 +757,7 @@ void do_versions_after_linking_280(Main *main)
}
}
- {
+ if (!MAIN_VERSION_ATLEAST(main, 280, 4)) {
for (WorkSpace *workspace = main->workspaces.first; workspace; workspace = workspace->id.next) {
if (workspace->view_layer) {
/* During 2.8 work we temporarly stored view-layer in the
@@ -584,42 +775,7 @@ void do_versions_after_linking_280(Main *main)
}
}
- {
- /* Since we don't have access to FileData we check the (always valid) master collection of the group. */
- for (Group *group = main->group.first; group; group = group->id.next) {
- if (group->collection == NULL) {
- BKE_group_init(group);
- SceneCollection *sc = GROUP_MASTER_COLLECTION(group);
- SceneCollection *sc_hidden = NULL;
-
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- if (go->ob->lay & group->layer) {
- BKE_collection_object_add(&group->id, sc, go->ob);
- }
- else {
- if (sc_hidden == NULL) {
- sc_hidden = BKE_collection_add(&group->id, sc, COLLECTION_TYPE_GROUP_INTERNAL, "Hidden");
- }
- BKE_collection_object_add(&group->id, sc_hidden, go->ob);
- }
- }
-
- if (sc_hidden != NULL) {
- LayerCollection *layer_collection_master, *layer_collection_hidden;
- layer_collection_master = group->view_layer->layer_collections.first;
- layer_collection_hidden = layer_collection_master->layer_collections.first;
- layer_collection_hidden->flag |= COLLECTION_DISABLED;
- }
- }
-
- GroupObject *go;
- while ((go = BLI_pophead(&group->gobject))) {
- MEM_freeN(go);
- }
- }
- }
-
- {
+ if (!MAIN_VERSION_ATLEAST(main, 280, 4)) {
for (Object *object = main->object.first; object; object = object->id.next) {
#ifndef VERSION_280_SUBVERSION_4
/* If any object already has an initialized value for
@@ -687,38 +843,26 @@ void do_versions_after_linking_280(Main *main)
}
}
}
-}
-static void do_version_view_layer_visibility(ViewLayer *view_layer)
-{
- LayerCollection *layer_collection;
- for (layer_collection = view_layer->layer_collections.first;
- layer_collection;
- layer_collection = layer_collection->next)
- {
- if (layer_collection->flag & COLLECTION_DISABLED) {
- BKE_collection_enable(view_layer, layer_collection);
- layer_collection->flag &= ~COLLECTION_DISABLED;
+#ifdef USE_COLLECTION_COMPAT_28
+ if (use_collection_compat_28 && !MAIN_VERSION_ATLEAST(main, 280, 14)) {
+ for (Collection *group = main->collection.first; group; group = group->id.next) {
+ do_version_group_collection_to_collection(main, group);
}
- if ((layer_collection->flag & (1 << 0)) == 0) { /* !COLLECTION_VISIBLE */
- layer_collection->flag |= COLLECTION_DISABLED;
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ do_version_scene_collection_to_collection(main, scene);
}
- layer_collection->flag |= COLLECTION_VIEWPORT | COLLECTION_RENDER;
}
+#endif
}
void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
{
+ bool use_collection_compat_28 = true;
if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
- if (!DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "view_layers")) {
- for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
- /* Master Collection */
- scene->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
- BLI_strncpy(scene->collection->name, "Master Collection", sizeof(scene->collection->name));
- }
- }
+ use_collection_compat_28 = false;
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
scene->r.gauss = 1.5f;
@@ -835,7 +979,9 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
printf("You need to combine transparency and emission shaders to the converted Principled shader nodes.\n");
}
- if ((DNA_struct_elem_find(fd->filesdna, "ViewLayer", "FreestyleConfig", "freestyle_config") == false) &&
+#ifdef USE_COLLECTION_COMPAT_28
+ if (use_collection_compat_28 &&
+ (DNA_struct_elem_find(fd->filesdna, "ViewLayer", "FreestyleConfig", "freestyle_config") == false) &&
DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "view_layers"))
{
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
@@ -849,9 +995,11 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
+#endif
}
- if (!MAIN_VERSION_ATLEAST(main, 280, 3)) {
+#ifdef USE_COLLECTION_COMPAT_28
+ if (use_collection_compat_28 && !MAIN_VERSION_ATLEAST(main, 280, 3)) {
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
ViewLayer *view_layer;
for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
@@ -859,12 +1007,13 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
- for (Group *group = main->group.first; group; group = group->id.next) {
+ for (Collection *group = main->collection.first; group; group = group->id.next) {
if (group->view_layer != NULL) {
do_version_view_layer_visibility(group->view_layer);
}
}
}
+#endif
if (!MAIN_VERSION_ATLEAST(main, 280, 6)) {
if (DNA_struct_elem_find(fd->filesdna, "SpaceOops", "int", "filter") == false) {
@@ -881,14 +1030,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
if (!ELEM(so->outlinevis,
SO_SCENES,
- SO_GROUPS,
SO_LIBRARIES,
SO_SEQUENCE,
SO_DATA_API,
- SO_ID_ORPHANS,
- SO_COLLECTIONS))
+ SO_ID_ORPHANS))
{
- so->outlinevis = SO_COLLECTIONS;
+ so->outlinevis = SO_VIEW_LAYER;
}
}
}
@@ -1079,7 +1226,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
- {
+ if (!MAIN_VERSION_ATLEAST(main, 280, 14)) {
if (!DNA_struct_elem_find(fd->filesdna, "Scene", "SceneDisplay", "display")) {
/* Initialize new scene.SceneDisplay */
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
@@ -1309,6 +1456,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
if (sl->spacetype == SPACE_OUTLINER) {
SpaceOops *soops = (SpaceOops *)sl;
soops->filter_id_type = ID_GR;
+ soops->outlinevis = SO_VIEW_LAYER;
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 57530c6a004..9e0c3f3ccdc 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -1661,7 +1661,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
Curve *cu;
Material *ma;
Mesh *me;
- Group *group;
+ Collection *collection;
Nurb *nu;
BezTriple *bezt;
BPoint *bp;
@@ -1818,9 +1818,9 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
for (me = main->mesh.first; me; me = me->id.next)
customdata_version_242(me);
- for (group = main->group.first; group; group = group->id.next)
- if (group->layer == 0)
- group->layer = (1 << 20) - 1;
+ for (collection = main->collection.first; collection; collection = collection->id.next)
+ if (collection->layer == 0)
+ collection->layer = (1 << 20) - 1;
/* now, subversion control! */
if (main->subversionfile < 3) {
@@ -2471,7 +2471,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
idproperties_fix_group_lengths(main->vfont);
idproperties_fix_group_lengths(main->text);
idproperties_fix_group_lengths(main->sound);
- idproperties_fix_group_lengths(main->group);
+ idproperties_fix_group_lengths(main->collection);
idproperties_fix_group_lengths(main->armature);
idproperties_fix_group_lengths(main->action);
idproperties_fix_group_lengths(main->nodetree);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 507fe2e082c..8ea1205be38 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -162,9 +162,9 @@
#include "BKE_blender_version.h"
#include "BKE_bpath.h"
#include "BKE_curve.h"
+#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_global.h" // for G
-#include "BKE_group.h"
#include "BKE_idcode.h"
#include "BKE_library.h" // for set_listbasepointers
#include "BKE_library_override.h"
@@ -1380,13 +1380,13 @@ static void write_particlesettings(WriteData *wd, ParticleSettings *part)
if (dw->ob != NULL) {
dw->index = 0;
if (part->dup_group) { /* can be NULL if lining fails or set to None */
- FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object)
{
if (object != dw->ob) {
dw->index++;
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
@@ -2356,6 +2356,31 @@ static void write_lamp(WriteData *wd, Lamp *la)
}
}
+static void write_collection_nolib(WriteData *wd, Collection *collection)
+{
+ /* Shared function for collection datablocks and scene master collection. */
+ write_previews(wd, collection->preview);
+
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ writestruct(wd, DATA, CollectionObject, 1, cob);
+ }
+
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ writestruct(wd, DATA, CollectionChild, 1, child);
+ }
+}
+
+static void write_collection(WriteData *wd, Collection *collection)
+{
+ if (collection->id.us > 0 || wd->use_memfile) {
+ /* write LibData */
+ writestruct(wd, ID_GR, Collection, 1, collection);
+ write_iddata(wd, &collection->id);
+
+ write_collection_nolib(wd, collection);
+ }
+}
+
static void write_sequence_modifiers(WriteData *wd, ListBase *modbase)
{
SequenceModifierData *smd;
@@ -2397,24 +2422,11 @@ static void write_paint(WriteData *wd, Paint *p)
}
}
-static void write_scene_collection(WriteData *wd, SceneCollection *sc)
-{
- writestruct(wd, DATA, SceneCollection, 1, sc);
-
- writelist(wd, DATA, LinkData, &sc->objects);
-
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- write_scene_collection(wd, nsc);
- }
-}
-
static void write_layer_collections(WriteData *wd, ListBase *lb)
{
for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
writestruct(wd, DATA, LayerCollection, 1, lc);
- writelist(wd, DATA, LinkData, &lc->object_bases);
-
write_layer_collections(wd, &lc->layer_collections);
}
}
@@ -2623,12 +2635,16 @@ static void write_scene(WriteData *wd, Scene *sce)
write_previews(wd, sce->preview);
write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
- write_scene_collection(wd, sce->collection);
for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
write_view_layer(wd, view_layer);
}
+ if (sce->master_collection) {
+ writestruct(wd, DATA, Collection, 1, sce->master_collection);
+ write_collection_nolib(wd, sce->master_collection);
+ }
+
/* Freed on doversion. */
BLI_assert(sce->layer_properties == NULL);
}
@@ -3046,19 +3062,6 @@ static void write_probe(WriteData *wd, LightProbe *prb)
}
}
-static void write_group(WriteData *wd, Group *group)
-{
- if (group->id.us > 0 || wd->use_memfile) {
- /* write LibData */
- writestruct(wd, ID_GR, Group, 1, group);
- write_iddata(wd, &group->id);
-
- write_previews(wd, group->preview);
- write_scene_collection(wd, group->collection);
- write_view_layer(wd, group->view_layer);
- }
-}
-
static void write_nodetree(WriteData *wd, bNodeTree *ntree)
{
if (ntree->id.us > 0 || wd->use_memfile) {
@@ -3859,7 +3862,7 @@ static bool write_file_handle(
write_sound(wd, (bSound *)id);
break;
case ID_GR:
- write_group(wd, (Group *)id);
+ write_collection(wd, (Collection *)id);
break;
case ID_AR:
write_armature(wd, (bArmature *)id);
diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h
index ed1993015f6..ba4ae964842 100644
--- a/source/blender/blentranslation/BLT_translation.h
+++ b/source/blender/blentranslation/BLT_translation.h
@@ -121,10 +121,10 @@ bool BLT_lang_is_ime_supported(void);
#define BLT_I18NCONTEXT_ID_BRUSH "Brush"
#define BLT_I18NCONTEXT_ID_CAMERA "Camera"
#define BLT_I18NCONTEXT_ID_CACHEFILE "CacheFile"
+#define BLT_I18NCONTEXT_ID_COLLECTION "Collection"
#define BLT_I18NCONTEXT_ID_CURVE "Curve"
#define BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE "FreestyleLineStyle"
#define BLT_I18NCONTEXT_ID_GPENCIL "GPencil"
-#define BLT_I18NCONTEXT_ID_GROUP "Group"
#define BLT_I18NCONTEXT_ID_ID "ID"
#define BLT_I18NCONTEXT_ID_IMAGE "Image"
/*#define BLT_I18NCONTEXT_ID_IPO "Ipo"*/ /* Deprecated */
@@ -175,10 +175,10 @@ typedef struct {
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_BRUSH, "id_brush"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CAMERA, "id_camera"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CACHEFILE, "id_cachefile"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_COLLECTION, "id_collection"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CURVE, "id_curve"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, "id_fs_linestyle"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_GPENCIL, "id_gpencil"), \
- BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_GROUP, "id_group"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ID, "id_id"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_IMAGE, "id_image"), \
/*BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_IPO, "id_ipo"),*/ \
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index d50c4bb23c4..89015f45e5a 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -266,7 +266,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->id, ob, true);
+ BKE_scene_collections_object_remove(G.main, sce, ob, true);
}
libnode_ob.clear();
@@ -409,7 +409,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
Object *obn = BKE_object_copy(G.main, source_ob);
DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- BKE_collection_object_add_from(sce, source_ob, obn);
+ BKE_collection_object_add_from(G.main, sce, source_ob, obn);
if (instance_node) {
anim_importer.read_node_transform(instance_node, obn);
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index a1d542daa14..5d1df800746 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -26,7 +26,7 @@
extern "C" {
#include "BLI_utildefines.h"
- #include "BKE_group.h"
+ #include "BKE_collection.h"
#include "BKE_object.h"
#include "BLI_listbase.h"
}
@@ -171,15 +171,15 @@ void SceneExporter::writeNodes(Depsgraph *depsgraph, Object *ob, Scene *sce)
}
// empty object
- else if (ob->type == OB_EMPTY) { // TODO: handle groups (OB_DUPLIGROUP
- if ((ob->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && ob->dup_group) {
- Group *group = ob->dup_group;
+ else if (ob->type == OB_EMPTY) { // TODO: handle groups (OB_DUPLICOLLECTION
+ if ((ob->transflag & OB_DUPLICOLLECTION) == OB_DUPLICOLLECTION && ob->dup_group) {
+ Collection *collection = ob->dup_group;
/* printf("group detected '%s'\n", group->id.name + 2); */
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
printf("\t%s\n", object->id.name);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index 778ead55c8d..b8fde34cc96 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -163,8 +163,8 @@ Object *bc_add_object(Scene *scene, ViewLayer *view_layer, int type, const char
ob->lay = scene->lay;
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- LayerCollection *layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer);
- BKE_collection_object_add(&scene->id, layer_collection->scene_collection, ob);
+ LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
+ BKE_collection_object_add(G.main, layer_collection->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/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index 604034bb0a7..0a0e7ee638b 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -262,11 +262,9 @@ void DEG_debug_print_eval_parent_typed(struct Depsgraph *depsgraph,
const char *function_name,
const char *object_name,
const void *object_address,
- const char *object_type,
const char *parent_comment,
const char *parent_name,
- const void *parent_address,
- const char *parent_type);
+ const void *parent_address);
void DEG_debug_print_eval_time(struct Depsgraph *depsgraph,
const char* function_name,
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
index 3460cbf7c91..202e8ef3cf0 100644
--- a/source/blender/depsgraph/DEG_depsgraph_build.h
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -42,7 +42,7 @@ struct Depsgraph;
struct CacheFile;
struct EffectorWeights;
-struct Group;
+struct Collection;
struct Main;
struct ModifierData;
struct Object;
@@ -159,7 +159,7 @@ typedef bool (*DEG_CollobjFilterFunction)(struct Object *obj, struct ModifierDat
void DEG_add_collision_relations(struct DepsNodeHandle *handle,
struct Scene *scene,
struct Object *object,
- struct Group *group,
+ struct Collection *collection,
unsigned int modifier_type,
DEG_CollobjFilterFunction fn,
bool dupli,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 31a0e74b569..98881ba3e57 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -71,12 +71,12 @@ extern "C" {
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_idcode.h"
-#include "BKE_group.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
@@ -388,7 +388,7 @@ void DepsgraphNodeBuilder::build_id(ID* id) {
}
switch (GS(id->name)) {
case ID_GR:
- build_group((Group *)id);
+ build_collection((Collection *)id);
break;
case ID_OB:
build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY);
@@ -419,29 +419,21 @@ void DepsgraphNodeBuilder::build_id(ID* id) {
}
}
-void DepsgraphNodeBuilder::build_group(Group *group)
+void DepsgraphNodeBuilder::build_collection(Collection *collection)
{
- if (built_map_.checkIsBuiltAndTag(group)) {
+ if (built_map_.checkIsBuiltAndTag(collection)) {
return;
}
- /* Build group objects. */
- LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) {
- build_object(-1, base->object, DEG_ID_LINKED_INDIRECTLY);
+ /* Build collection objects. */
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
+ build_object(-1, cob->ob, DEG_ID_LINKED_INDIRECTLY);
}
- /* Operation to evaluate the whole view layer.
- *
- * NOTE: We re-use DONE opcode even though the function does everything.
- * This way we wouldn't need to worry about possible relations from DONE,
- * regardless whether it's a group or scene or something else.
- */
- add_id_node(&group->id);
- Group *group_cow = get_cow_datablock(group);
- add_operation_node(&group->id,
- DEG_NODE_TYPE_LAYER_COLLECTIONS,
- function_bind(BKE_group_eval_view_layers,
- _1,
- group_cow),
- DEG_OPCODE_VIEW_LAYER_EVAL);
+ /* Build child collections. */
+ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
+ build_collection(child->collection);
+ }
+
+ add_id_node(&collection->id);
}
void DepsgraphNodeBuilder::build_object(int base_index,
@@ -514,7 +506,7 @@ void DepsgraphNodeBuilder::build_object(int base_index,
}
/* Object dupligroup. */
if (object->dup_group != NULL) {
- build_group(object->dup_group);
+ build_collection(object->dup_group);
}
}
@@ -848,7 +840,8 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
/* objects - simulation participants */
if (rbw->group) {
- LISTBASE_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) {
+ const ListBase group_objects = BKE_collection_object_cache_get(rbw->group);
+ LISTBASE_FOREACH (Base *, base, &group_objects) {
Object *object = base->object;
if (!object || (object->type != OB_MESH))
@@ -922,7 +915,7 @@ void DepsgraphNodeBuilder::build_particles(Object *object)
break;
case PART_DRAW_GR:
if (part->dup_group != NULL) {
- build_group(part->dup_group);
+ build_collection(part->dup_group);
}
break;
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 0ed3f5e334f..488f4f273b9 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -43,7 +43,7 @@ struct GHash;
struct ID;
struct Image;
struct FCurve;
-struct Group;
+struct Collection;
struct Key;
struct LayerCollection;
struct Main;
@@ -158,10 +158,11 @@ struct DepsgraphNodeBuilder {
int name_tag = -1);
void build_id(ID* id);
+ void build_layer_collections(ListBase *lb);
void build_view_layer(Scene *scene,
ViewLayer *view_layer,
eDepsNode_LinkedState_Type linked_state);
- void build_group(Group *group);
+ void build_collection(Collection *collection);
void build_object(int base_index,
Object *object,
eDepsNode_LinkedState_Type linked_state);
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 ac3970ed3ab..a396aecd3a8 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
@@ -65,6 +65,14 @@ extern "C" {
namespace DEG {
+void DepsgraphNodeBuilder::build_layer_collections(ListBase *lb)
+{
+ for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) {
+ build_collection(lc->collection);
+ build_layer_collections(&lc->layer_collections);
+ }
+}
+
void DepsgraphNodeBuilder::build_view_layer(
Scene *scene,
ViewLayer *view_layer,
@@ -100,6 +108,7 @@ void DepsgraphNodeBuilder::build_view_layer(
base->object->select_color = select_color++;
++base_index;
}
+ build_layer_collections(&view_layer->layer_collections);
if (scene->camera != NULL) {
build_object(-1, scene->camera, DEG_ID_LINKED_INDIRECTLY);
}
@@ -140,7 +149,7 @@ void DepsgraphNodeBuilder::build_view_layer(
DEG_NODE_TYPE_LAYER_COLLECTIONS,
function_bind(BKE_layer_eval_view_layer_indexed,
_1,
- &scene_cow->id,
+ scene_cow,
view_layer_index_),
DEG_OPCODE_VIEW_LAYER_EVAL);
/* Parameters evaluation for scene relations mainly. */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index e1eae851ec6..edb2969fa63 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -72,12 +72,12 @@ extern "C" {
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
#include "BKE_effect.h"
#include "BKE_collision.h"
#include "BKE_fcurve.h"
-#include "BKE_group.h"
#include "BKE_key.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -296,14 +296,14 @@ void DepsgraphRelationBuilder::add_collision_relations(
const OperationKey &key,
Scene *scene,
Object *object,
- Group *group,
+ Collection *collection,
bool dupli,
const char *name)
{
unsigned int numcollobj;
Object **collobjs = get_collisionobjects_ext(scene,
object,
- group,
+ collection,
&numcollobj,
eModifierType_Collision,
dupli);
@@ -397,7 +397,7 @@ void DepsgraphRelationBuilder::build_id(ID *id)
}
switch (GS(id->name)) {
case ID_GR:
- build_group(NULL, (Group *)id);
+ build_collection(NULL, (Collection *)id);
break;
case ID_OB:
build_object(NULL, (Object *)id);
@@ -425,19 +425,23 @@ void DepsgraphRelationBuilder::build_id(ID *id)
}
}
-void DepsgraphRelationBuilder::build_group(Object *object, Group *group)
+void DepsgraphRelationBuilder::build_collection(Object *object, Collection *collection)
{
- const bool group_done = built_map_.checkIsBuiltAndTag(group);
+ const bool group_done = built_map_.checkIsBuiltAndTag(collection);
OperationKey object_local_transform_key(object != NULL ? &object->id : NULL,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_LOCAL);
if (!group_done) {
- LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) {
- build_object(NULL, base->object);
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
+ build_object(NULL, cob->ob);
+ }
+ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
+ build_collection(NULL, child->collection);
}
}
if (object != NULL) {
- LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) {
+ const ListBase group_objects = BKE_collection_object_cache_get(collection);
+ LISTBASE_FOREACH (Base *, base, &group_objects) {
ComponentKey dupli_transform_key(&base->object->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup");
}
@@ -549,7 +553,7 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
}
/* Object dupligroup. */
if (object->dup_group != NULL) {
- build_group(object, object->dup_group);
+ build_collection(object, object->dup_group);
}
}
@@ -1353,7 +1357,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
/* objects - simulation participants */
if (rbw->group) {
- LISTBASE_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) {
+ const ListBase group_objects = BKE_collection_object_cache_get(rbw->group);
+ LISTBASE_FOREACH (Base *, base, &group_objects) {
Object *object = base->object;
if (object == NULL || object->type != OB_MESH) {
continue;
@@ -1407,7 +1412,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
/* constraints */
if (rbw->constraints) {
- LISTBASE_FOREACH (Base *, base, &rbw->constraints->view_layer->object_bases) {
+ const ListBase constraint_objects = BKE_collection_object_cache_get(rbw->constraints);
+ LISTBASE_FOREACH (Base *, base, &constraint_objects) {
Object *object = base->object;
if (object == NULL || !object->rigidbody_constraint) {
continue;
@@ -1529,8 +1535,8 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
break;
case PART_DRAW_GR:
if (part->dup_group != NULL) {
- build_group(NULL, part->dup_group);
- LISTBASE_FOREACH (GroupObject *, go, &part->dup_group->gobject) {
+ build_collection(NULL, part->dup_group);
+ LISTBASE_FOREACH (CollectionObject *, go, &part->dup_group->gobject) {
build_particles_visualization_object(object,
psys,
go->ob);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 9e45d01fd79..fec30160622 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -55,7 +55,7 @@ struct ListBase;
struct GHash;
struct ID;
struct FCurve;
-struct Group;
+struct Collection;
struct Key;
struct LayerCollection;
struct Main;
@@ -195,8 +195,9 @@ struct DepsgraphRelationBuilder
bool check_unique = false);
void build_id(ID* id);
+ void build_layer_collections(ListBase *lb);
void build_view_layer(Scene *scene, ViewLayer *view_layer);
- void build_group(Object *object, Group *group);
+ void build_collection(Object *object, Collection *collection);
void build_object(Base *base, Object *object);
void build_object_flags(Base *base, Object *object);
void build_object_data(Object *object);
@@ -259,7 +260,7 @@ struct DepsgraphRelationBuilder
void add_collision_relations(const OperationKey &key,
Scene *scene,
Object *object,
- Group *group,
+ Collection *collection,
bool dupli,
const char *name);
void add_forcefield_relations(const OperationKey &key,
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 99295a733fc..f575be9f659 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
@@ -69,6 +69,14 @@ extern "C" {
namespace DEG {
+void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb)
+{
+ for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) {
+ build_collection(NULL, lc->collection);
+ build_layer_collections(&lc->layer_collections);
+ }
+}
+
void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_layer)
{
/* Setup currently building context. */
@@ -81,6 +89,9 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
build_object(base, base->object);
}
+
+ build_layer_collections(&view_layer->layer_collections);
+
if (scene->camera != NULL) {
build_object(NULL, scene->camera);
}
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index f25be922db9..4307ac94390 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -696,30 +696,26 @@ void DEG_debug_print_eval_parent_typed(struct Depsgraph *depsgraph,
const char *function_name,
const char *object_name,
const void *object_address,
- const char *object_type,
const char *parent_comment,
const char *parent_name,
- const void *parent_address,
- const char *parent_type)
+ const void *parent_address)
{
if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
return;
}
fprintf(stdout,
- "%s%s on %s %s(%p)%s [%s] %s %s %s(%p)%s %s\n",
+ "%s%s on %s %s(%p) [%s] %s %s %s(%p)%s\n",
depsgraph_name_for_logging(depsgraph).c_str(),
function_name,
object_name,
DEG::deg_color_for_pointer(object_address).c_str(),
object_address,
- object_type,
DEG::deg_color_end().c_str(),
parent_comment,
parent_name,
DEG::deg_color_for_pointer(parent_address).c_str(),
parent_address,
- DEG::deg_color_end().c_str(),
- parent_type);
+ DEG::deg_color_end().c_str());
fflush(stdout);
}
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 18f1d6edbaf..84b9bad17c9 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -328,14 +328,14 @@ void DEG_relations_tag_update(Main *bmain)
void DEG_add_collision_relations(DepsNodeHandle *handle,
Scene *scene,
Object *object,
- Group *group,
+ Collection *collection,
unsigned int modifier_type,
DEG_CollobjFilterFunction fn,
bool dupli,
const char *name)
{
unsigned int numcollobj;
- Object **collobjs = get_collisionobjects_ext(scene, object, group, &numcollobj, modifier_type, dupli);
+ Object **collobjs = get_collisionobjects_ext(scene, object, collection, &numcollobj, modifier_type, dupli);
for (unsigned int i = 0; i < numcollobj; i++) {
Object *ob1 = collobjs[i];
diff --git a/source/blender/depsgraph/intern/depsgraph_intern.h b/source/blender/depsgraph/intern/depsgraph_intern.h
index c048a7c1b93..526cecde457 100644
--- a/source/blender/depsgraph/intern/depsgraph_intern.h
+++ b/source/blender/depsgraph/intern/depsgraph_intern.h
@@ -49,7 +49,7 @@ extern "C" {
#include "DEG_depsgraph_debug.h"
struct DEGEditorUpdateContext;
-struct Group;
+struct Collection;
struct Main;
struct Scene;
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 95d6acdf56b..c07bf4337db 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -35,8 +35,8 @@
#include "DNA_lightprobe_types.h"
#include "DNA_view3d_types.h"
+#include "BKE_collection.h"
#include "BKE_object.h"
-#include "BKE_group.h"
#include "MEM_guardedalloc.h"
#include "GPU_material.h"
@@ -389,7 +389,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
EEVEE_LightProbesInfo *pinfo = sldata->probes;
/* Make sure no aditionnal visibility check runs by default. */
- pinfo->vis_data.group = NULL;
+ pinfo->vis_data.collection = NULL;
pinfo->do_cube_update = false;
pinfo->num_cube = 1; /* at least one for the world */
@@ -581,7 +581,7 @@ bool EEVEE_lightprobes_obj_visibility_cb(bool vis_in, void *user_data)
EEVEE_ObjectEngineData *oed = (EEVEE_ObjectEngineData *)user_data;
/* test disabled if group is NULL */
- if (oed->test_data->group == NULL)
+ if (oed->test_data->collection == NULL)
return vis_in;
if (oed->test_data->cached == false)
@@ -593,7 +593,7 @@ bool EEVEE_lightprobes_obj_visibility_cb(bool vis_in, void *user_data)
if (oed->ob_vis_dirty) {
oed->ob_vis_dirty = false;
- oed->ob_vis = BKE_group_object_exists(oed->test_data->group, oed->ob);
+ oed->ob_vis = BKE_collection_has_object_recursive(oed->test_data->collection, oed->ob);
oed->ob_vis = (oed->test_data->invert) ? !oed->ob_vis : oed->ob_vis;
}
@@ -1301,7 +1301,7 @@ static void render_scene_to_probe(
DRW_stats_group_end();
/* Make sure no aditionnal visibility check runs after this. */
- pinfo->vis_data.group = NULL;
+ pinfo->vis_data.collection = NULL;
/* Restore */
txl->planar_pool = tmp_planar_pool;
@@ -1400,7 +1400,7 @@ static void render_scene_to_planar(
DRW_stats_group_end();
/* Make sure no aditionnal visibility check runs after this. */
- pinfo->vis_data.group = NULL;
+ pinfo->vis_data.collection = NULL;
/* Restore */
txl->planar_pool = tmp_planar_pool;
@@ -1554,7 +1554,7 @@ void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); i++) {
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
LightProbe *prb = (LightProbe *)ob->data;
- pinfo->vis_data.group = prb->visibility_grp;
+ pinfo->vis_data.collection = prb->visibility_grp;
pinfo->vis_data.invert = prb->flag & LIGHTPROBE_FLAG_INVERT_GROUP;
render_scene_to_planar(sldata, vedata, i, ped);
}
@@ -1603,7 +1603,7 @@ static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve
continue;
}
LightProbe *prb = (LightProbe *)ob->data;
- pinfo->vis_data.group = prb->visibility_grp;
+ pinfo->vis_data.collection = prb->visibility_grp;
pinfo->vis_data.invert = prb->flag & LIGHTPROBE_FLAG_INVERT_GROUP;
render_scene_to_probe(sldata, vedata, ob->obmat[3], prb->clipsta, prb->clipend);
glossy_filter_probe(sldata, vedata, psl, i, prb->intensity);
@@ -1711,7 +1711,7 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
egrid->level_bias = (float)(1 << 0);
DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data);
}
- pinfo->vis_data.group = prb->visibility_grp;
+ pinfo->vis_data.collection = prb->visibility_grp;
pinfo->vis_data.invert = prb->flag & LIGHTPROBE_FLAG_INVERT_GROUP;
render_scene_to_probe(sldata, vedata, pos, prb->clipsta, prb->clipend);
diffuse_filter_probe(sldata, vedata, psl, egrid->offset + cell_id,
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 3ab1d55aeac..c95e51548d0 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -413,7 +413,7 @@ typedef struct EEVEE_PlanarReflection {
typedef struct EEVEE_LightProbeVisTest {
bool invert;
bool cached; /* Reuse last test results */
- struct Group *group; /* Skip test if NULL */
+ struct Collection *collection; /* Skip test if NULL */
} EEVEE_LightProbeVisTest;
typedef struct EEVEE_LightProbesInfo {
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index b7eaa1a4a5f..aad4f71fe9a 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -84,12 +84,12 @@
#include "BLI_ghash.h"
#include "BLI_string.h"
-#include "BKE_animsys.h"
#include "BKE_action.h"
-#include "BKE_fcurve.h"
+#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_main.h"
@@ -1727,7 +1727,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
* - used to ease the process of doing multiple-character choreographies
*/
if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
- if (BKE_group_object_exists(ads->filter_grp, ob) == 0)
+ if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0)
continue;
}
@@ -2894,7 +2894,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m
* - used to ease the process of doing multiple-character choreographies
*/
if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
- if (BKE_group_object_exists(ads->filter_grp, ob) == 0)
+ if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0)
return false;
}
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index 6dfe17f227a..84889033f30 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -48,6 +48,7 @@
#include "DNA_anim_types.h"
#include "DNA_curve_types.h"
+#include "DNA_group_types.h"
#include "DNA_object_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
@@ -1128,7 +1129,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
struct Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *sc = CTX_data_scene_collection(C);
+ Collection *collection = CTX_data_collection(C);
bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0);
bGPDstroke *gps, *prev_gps = NULL;
Object *ob;
@@ -1158,7 +1159,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->id, sc, ob);
+ BKE_collection_object_add(bmain, collection, 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 d9c743aaf27..8d64d8b67e9 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -71,7 +71,6 @@
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_font.h"
-#include "BKE_group.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
@@ -1048,11 +1047,11 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, false);
}
-/********************* Add Group Instance Operator ********************/
+/********************* Add Collection Instance Operator ********************/
-static int group_instance_add_exec(bContext *C, wmOperator *op)
+static int collection_instance_add_exec(bContext *C, wmOperator *op)
{
- Group *group;
+ Collection *collection;
unsigned int layer;
float loc[3], rot[3];
@@ -1060,7 +1059,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
char name[MAX_ID_NAME - 2];
RNA_string_get(op->ptr, "name", name);
- group = (Group *)BKE_libblock_find_name(ID_GR, name);
+ collection = (Collection *)BKE_libblock_find_name(ID_GR, name);
if (0 == RNA_struct_property_is_set(op->ptr, "location")) {
const wmEvent *event = CTX_wm_window(C)->eventstate;
@@ -1073,22 +1072,30 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
}
}
else
- group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group"));
+ collection = BLI_findlink(&CTX_data_main(C)->collection, RNA_enum_get(op->ptr, "collection"));
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
- if (group) {
+ if (collection) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, loc, rot, false, layer);
- ob->dup_group = group;
- ob->transflag |= OB_DUPLIGROUP;
- id_us_plus(&group->id);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ /* Avoid dependency cycles. */
+ LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
+ while (BKE_collection_find_cycle(active_lc->collection, collection)) {
+ active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
+ }
+
+ Object *ob = ED_object_add_type(C, OB_EMPTY, collection->id.name + 2, loc, rot, false, layer);
+ ob->dup_group = collection;
+ ob->transflag |= OB_DUPLICOLLECTION;
+ id_us_plus(&collection->id);
/* works without this except if you try render right after, see: 22027 */
DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&group->id, 0);
+ DEG_id_tag_update(&collection->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
@@ -1099,27 +1106,27 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
}
/* only used as menu */
-void OBJECT_OT_group_instance_add(wmOperatorType *ot)
+void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Add Group Instance";
- ot->description = "Add a dupligroup instance";
- ot->idname = "OBJECT_OT_group_instance_add";
+ ot->name = "Add Collection Instance";
+ ot->description = "Add a collection instance";
+ ot->idname = "OBJECT_OT_collection_instance_add";
/* api callbacks */
ot->invoke = WM_enum_search_invoke;
- ot->exec = group_instance_add_exec;
+ ot->exec = collection_instance_add_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_string(ot->srna, "name", "Group", MAX_ID_NAME - 2, "Name", "Group name to add");
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "");
- RNA_def_enum_funcs(prop, RNA_group_itemf);
+ RNA_def_string(ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Collection name to add");
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
+ RNA_def_enum_funcs(prop, RNA_collection_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
ED_object_add_generic_props(ot, false);
@@ -1197,7 +1204,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);
- BKE_collections_object_remove(bmain, &scene->id, ob, true);
+ BKE_scene_collections_object_remove(bmain, scene, ob, true);
}
static int object_delete_exec(bContext *C, wmOperator *op)
@@ -1331,7 +1338,7 @@ static void copy_object_set_idnew(bContext *C)
/********************* Make Duplicates Real ************************/
/**
- * \note regarding hashing dupli-objects when using OB_DUPLIGROUP, skip the first member of #DupliObject.persistent_id
+ * \note regarding hashing dupli-objects when using OB_DUPLICOLLECTION, skip the first member of #DupliObject.persistent_id
* since its a unique index and we only want to know if the group objects are from the same dupli-group instance.
*/
static unsigned int dupliobject_group_hash(const void *ptr)
@@ -1346,7 +1353,7 @@ static unsigned int dupliobject_group_hash(const void *ptr)
}
/**
- * \note regarding hashing dupli-objects when NOT using OB_DUPLIGROUP, include the first member of #DupliObject.persistent_id
+ * \note regarding hashing dupli-objects when NOT using OB_DUPLICOLLECTION, include the first member of #DupliObject.persistent_id
* since its the index of the vertex/face the object is instantiated on and we want to identify objects on the same vertex/face.
*/
static unsigned int dupliobject_hash(const void *ptr)
@@ -1418,7 +1425,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
dupli_gh = BLI_ghash_ptr_new(__func__);
if (use_hierarchy) {
- if (base->object->transflag & OB_DUPLIGROUP) {
+ if (base->object->transflag & OB_DUPLICOLLECTION) {
parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
}
else {
@@ -1438,7 +1445,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
ob_dst->totcol = 0;
}
- BKE_collection_object_add_from(scene, base->object, ob_dst);
+ BKE_collection_object_add_from(bmain, scene, base->object, ob_dst);
base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
BLI_assert(base_dst != NULL);
@@ -1492,7 +1499,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
* they won't be read, this is simply for a hash lookup. */
DupliObject dob_key;
dob_key.ob = ob_src_par;
- if (base->object->transflag & OB_DUPLIGROUP) {
+ if (base->object->transflag & OB_DUPLICOLLECTION) {
memcpy(&dob_key.persistent_id[1],
&dob->persistent_id[1],
sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
@@ -1537,7 +1544,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
}
}
- if (base->object->transflag & OB_DUPLIGROUP && base->object->dup_group) {
+ if (base->object->transflag & OB_DUPLICOLLECTION && base->object->dup_group) {
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->proxy_group == base->object) {
ob->proxy = NULL;
@@ -1659,7 +1666,7 @@ static Base *duplibase_for_convert(Main *bmain, Scene *scene, ViewLayer *view_la
obn = BKE_object_copy(bmain, ob);
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- BKE_collection_object_add_from(scene, ob, obn);
+ BKE_collection_object_add_from(bmain, scene, ob, obn);
basen = BKE_view_layer_base_find(view_layer, obn);
ED_object_base_select(basen, BA_SELECT);
@@ -2068,23 +2075,23 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
base = BKE_view_layer_base_find(view_layer, ob);
if ((base != NULL) && (base->flag & BASE_VISIBLED)) {
- BKE_collection_object_add_from(scene, ob, obn);
+ BKE_collection_object_add_from(bmain, scene, ob, obn);
}
else {
- LayerCollection *layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer);
- BKE_collection_object_add(&scene->id, layer_collection->scene_collection, obn);
+ LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
+ BKE_collection_object_add(bmain, layer_collection->collection, obn);
}
basen = BKE_view_layer_base_find(view_layer, obn);
- /* 1) duplis should end up in same group as the original
- * 2) Rigid Body sim participants MUST always be part of a group...
+ /* 1) duplis should end up in same collection as the original
+ * 2) Rigid Body sim participants MUST always be part of a collection...
*/
// XXX: is 2) really a good measure here?
- if ((ob->flag & OB_FROMGROUP) != 0 || ob->rigidbody_object || ob->rigidbody_constraint) {
- Group *group;
- for (group = bmain->group.first; group; group = group->id.next) {
- if (BKE_group_object_exists(group, ob))
- BKE_group_object_add(group, obn);
+ if (ob->rigidbody_object || ob->rigidbody_constraint) {
+ Collection *collection;
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (BKE_collection_has_object(collection, ob))
+ BKE_collection_object_add(bmain, collection, obn);
}
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index b9a7da02611..a2e91761a38 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -1506,11 +1506,12 @@ bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_onl
static int move_to_collection_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_index");
- const bool is_add = RNA_boolean_get(op->ptr, "is_add");
+ const bool is_link = STREQ(op->idname, "OBJECT_OT_link_to_collection");
const bool is_new = RNA_boolean_get(op->ptr, "is_new");
- SceneCollection *scene_collection;
+ Collection *collection;
if (!RNA_property_is_set(op->ptr, prop)) {
BKE_report(op->reports, RPT_ERROR, "No collection selected");
@@ -1518,8 +1519,8 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
}
int collection_index = RNA_property_int_get(op->ptr, prop);
- scene_collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
- if (scene_collection == NULL) {
+ collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
+ if (collection == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
return OPERATOR_CANCELLED;
}
@@ -1540,24 +1541,24 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
if (is_new) {
char new_collection_name[MAX_NAME];
RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
- scene_collection = BKE_collection_add(&scene->id, scene_collection, COLLECTION_TYPE_NONE, new_collection_name);
+ collection = BKE_collection_add(bmain, collection, new_collection_name);
}
if ((single_object != NULL) &&
- is_add &&
- BLI_findptr(&scene_collection->objects, single_object, offsetof(LinkData, data)))
+ is_link &&
+ BLI_findptr(&collection->gobject, single_object, offsetof(CollectionObject, ob)))
{
- BKE_reportf(op->reports, RPT_ERROR, "%s already in %s", single_object->id.name + 2, scene_collection->name);
+ BKE_reportf(op->reports, RPT_ERROR, "%s already in %s", single_object->id.name + 2, collection->id.name + 2);
return OPERATOR_CANCELLED;
}
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
- if (!is_add) {
- BKE_collection_object_move(&scene->id, scene_collection, NULL, ob);
+ if (!is_link) {
+ BKE_collection_object_move(bmain, scene, collection, NULL, ob);
}
else {
- BKE_collection_object_add(&scene->id, scene_collection, ob);
+ BKE_collection_object_add(bmain, collection, ob);
}
}
CTX_DATA_END;
@@ -1566,8 +1567,8 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
RPT_INFO,
"%s %s to %s",
(single_object != NULL) ? single_object->id.name + 2 : "Objects",
- is_add ? "added" : "moved",
- scene_collection->name);
+ is_link ? "linked" : "moved",
+ collection->id.name + 2);
DEG_relations_tag_update(CTX_data_main(C));
DEG_id_tag_update(&scene->id, 0);
@@ -1579,26 +1580,27 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-typedef struct MoveToCollectionData {
+struct MoveToCollectionData {
struct MoveToCollectionData *next, *prev;
int index;
- struct SceneCollection *collection;
+ struct Collection *collection;
struct ListBase submenus;
PointerRNA ptr;
struct wmOperatorType *ot;
-} MoveToCollectionData;
+};
static int move_to_collection_menus_create(wmOperator *op, MoveToCollectionData *menu)
{
int index = menu->index;
- for (SceneCollection *scene_collection = menu->collection->scene_collections.first;
- scene_collection != NULL;
- scene_collection = scene_collection->next)
+ for (CollectionChild *child = menu->collection->children.first;
+ child != NULL;
+ child = child->next)
{
+ Collection *collection = child->collection;
MoveToCollectionData *submenu = MEM_callocN(sizeof(MoveToCollectionData),
"MoveToCollectionData submenu - expected memleak");
BLI_addtail(&menu->submenus, submenu);
- submenu->collection = scene_collection;
+ submenu->collection = collection;
submenu->index = ++index;
index = move_to_collection_menus_create(op, submenu);
submenu->ot = op->type;
@@ -1631,11 +1633,19 @@ static void move_to_collection_menus_free(MoveToCollectionData **menu)
static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout, void *menu_v)
{
MoveToCollectionData *menu = menu_v;
+ const char *name;
+
+ if (menu->collection->flag & COLLECTION_IS_MASTER) {
+ name = IFACE_("Scene Collection");
+ }
+ else {
+ name = menu->collection->id.name + 2;
+ }
uiItemIntO(layout,
- menu->collection->name,
+ name,
ICON_NONE,
- "OBJECT_OT_move_to_collection",
+ menu->ot->idname,
"collection_index",
menu->index);
uiItemS(layout);
@@ -1658,7 +1668,6 @@ static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout
"New Collection",
ICON_ZOOMIN,
menu->ptr.data,
- /* We use invoke here so we can read ctrl from event. */
WM_OP_INVOKE_DEFAULT,
0,
NULL);
@@ -1668,15 +1677,15 @@ static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionDat
{
if (BLI_listbase_is_empty(&menu->submenus)) {
uiItemIntO(layout,
- menu->collection->name,
+ menu->collection->id.name + 2,
ICON_NONE,
- "OBJECT_OT_move_to_collection",
+ menu->ot->idname,
"collection_index",
menu->index);
}
else {
uiItemMenuF(layout,
- menu->collection->name,
+ menu->collection->id.name + 2,
ICON_NONE,
move_to_collection_menu_create,
menu);
@@ -1686,8 +1695,10 @@ static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionDat
/* This is allocated statically because we need this available for the menus creation callback. */
static MoveToCollectionData *master_collection_menu = NULL;
-static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
+ Scene *scene = CTX_data_scene(C);
+
/* Reset the menus data for the current master collection, and free previously allocated data. */
move_to_collection_menus_free(&master_collection_menu);
@@ -1695,16 +1706,15 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
prop = RNA_struct_find_property(op->ptr, "collection_index");
if (RNA_property_is_set(op->ptr, prop)) {
int collection_index = RNA_property_int_get(op->ptr, prop);
- RNA_boolean_set(op->ptr, "is_add", event->ctrl);
if (RNA_boolean_get(op->ptr, "is_new")) {
prop = RNA_struct_find_property(op->ptr, "new_collection_name");
if (!RNA_property_is_set(op->ptr, prop)) {
char name[MAX_NAME];
- SceneCollection *scene_collection;
+ Collection *collection;
- scene_collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
- BKE_collection_new_name_get(&CTX_data_scene(C)->id, scene_collection, name);
+ collection = BKE_collection_from_index(scene, collection_index);
+ BKE_collection_new_name_get(collection, name);
RNA_property_string_set(op->ptr, prop, name);
return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y);
@@ -1713,7 +1723,7 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
return move_to_collection_exec(C, op);
}
- SceneCollection *master_collection = BKE_collection_master(&CTX_data_scene(C)->id);
+ Collection *master_collection = BKE_collection_master(scene);
/* We need the data to be allocated so it's available during menu drawing.
* Technically we could use wmOperator->customdata. However there is no free callback
@@ -1733,10 +1743,10 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
uiLayout *layout;
/* Build the menus. */
- pup = UI_popup_menu_begin(C, IFACE_("Move to Collection"), ICON_NONE);
+ const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
+ pup = UI_popup_menu_begin(C, title, ICON_NONE);
layout = UI_popup_menu_layout(pup);
- /* We use invoke here so we can read ctrl from event. */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
move_to_collection_menu_create(C, layout, master_collection_menu);
@@ -1752,7 +1762,7 @@ void OBJECT_OT_move_to_collection(wmOperatorType *ot)
/* identifiers */
ot->name = "Move to Collection";
- ot->description = "Move to a collection only (Ctrl to add)";
+ ot->description = "Move objects to a scene collection";
ot->idname = "OBJECT_OT_move_to_collection";
/* api callbacks */
@@ -1766,7 +1776,32 @@ void OBJECT_OT_move_to_collection(wmOperatorType *ot)
prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
"Collection Index", "Index of the collection to move to", 0, INT_MAX);
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_boolean(ot->srna, "is_add", false, "Add", "Keep object in original collections as well");
+ prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_string(ot->srna, "new_collection_name", NULL, MAX_NAME, "Name",
+ "Name of the newly added collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+void OBJECT_OT_link_to_collection(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Link to Collection";
+ ot->description = "Link objects to a collection";
+ ot->idname = "OBJECT_OT_link_to_collection";
+
+ /* api callbacks */
+ ot->exec = move_to_collection_exec;
+ ot->invoke = move_to_collection_invoke;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
+ "Collection Index", "Index of the collection to move to", 0, INT_MAX);
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index cb0fbdda970..0a6a81d99da 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -39,8 +39,8 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_main.h"
@@ -64,8 +64,9 @@
/********************* 3d view operators ***********************/
/* can be called with C == NULL */
-static const EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *collection_object_active_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
+ Main *bmain = CTX_data_main(C);
Object *ob;
EnumPropertyItem *item = NULL, item_tmp = {0};
int totitem = 0;
@@ -78,25 +79,25 @@ static const EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA
/* check that the object exists */
if (ob) {
- Group *group;
+ Collection *collection;
int i = 0, count = 0;
- /* if 2 or more groups, add option to add to all groups */
- group = NULL;
- while ((group = BKE_group_object_find(group, ob)))
+ /* if 2 or more collections, add option to add to all collections */
+ collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, collection, ob)))
count++;
if (count >= 2) {
- item_tmp.identifier = item_tmp.name = "All Groups";
+ item_tmp.identifier = item_tmp.name = "All Collections";
item_tmp.value = INT_MAX; /* this will give NULL on lookup */
RNA_enum_item_add(&item, &totitem, &item_tmp);
RNA_enum_item_add_separator(&item, &totitem);
}
- /* add groups */
- group = NULL;
- while ((group = BKE_group_object_find(group, ob))) {
- item_tmp.identifier = item_tmp.name = group->id.name + 2;
+ /* add collections */
+ collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, collection, ob))) {
+ item_tmp.identifier = item_tmp.name = collection->id.name + 2;
/* item_tmp.icon = ICON_ARMATURE_DATA; */
item_tmp.value = i;
RNA_enum_item_add(&item, &totitem, &item_tmp);
@@ -110,48 +111,48 @@ static const EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA
return item;
}
-/* get the group back from the enum index, quite awkward and UI specific */
-static Group *group_object_active_find_index(Object *ob, const int group_object_index)
+/* get the collection back from the enum index, quite awkward and UI specific */
+static Collection *collection_object_active_find_index(Main *bmain, Object *ob, const int collection_object_index)
{
- Group *group = NULL;
+ Collection *collection = NULL;
int i = 0;
- while ((group = BKE_group_object_find(group, ob))) {
- if (i == group_object_index) {
+ while ((collection = BKE_collection_object_find(bmain, collection, ob))) {
+ if (i == collection_object_index) {
break;
}
i++;
}
- return group;
+ return collection;
}
static int objects_add_active_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- int single_group_index = RNA_enum_get(op->ptr, "group");
- Group *single_group = group_object_active_find_index(ob, single_group_index);
- Group *group;
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(bmain, ob, single_collection_index);
+ Collection *collection;
bool is_cycle = false;
bool updated = false;
if (ob == NULL)
return OPERATOR_CANCELLED;
- /* now add all selected objects to the group(s) */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (single_group && group != single_group)
+ /* now add all selected objects to the collection(s) */
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (single_collection && collection != single_collection)
continue;
- if (!BKE_group_object_exists(group, ob))
+ if (!BKE_collection_has_object(collection, ob))
continue;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- if (BKE_group_object_exists(group, base->object))
+ if (BKE_collection_has_object(collection, base->object))
continue;
- if (!BKE_group_object_cyclic_check(bmain, base->object, group)) {
- BKE_group_object_add(group, base->object);
+ if (!BKE_collection_object_cyclic_check(bmain, base->object, collection)) {
+ BKE_collection_object_add(bmain, collection, base->object);
updated = true;
}
else {
@@ -162,7 +163,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
}
if (is_cycle)
- BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected");
+ BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
if (!updated)
return OPERATOR_CANCELLED;
@@ -173,14 +174,14 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GROUP_OT_objects_add_active(wmOperatorType *ot)
+void COLLECTION_OT_objects_add_active(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Add Selected To Active Group";
- ot->description = "Add the object to an object group that contains the active object";
- ot->idname = "GROUP_OT_objects_add_active";
+ ot->name = "Add Selected To Active Collection";
+ ot->description = "Add the object to an object collection that contains the active object";
+ ot->idname = "COLLECTION_OT_objects_add_active";
/* api callbacks */
ot->exec = objects_add_active_exec;
@@ -191,8 +192,8 @@ void GROUP_OT_objects_add_active(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to add other selected objects to");
- RNA_def_enum_funcs(prop, group_object_active_itemf);
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to add other selected objects to");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
@@ -202,26 +203,26 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
- int single_group_index = RNA_enum_get(op->ptr, "group");
- Group *single_group = group_object_active_find_index(ob, single_group_index);
- Group *group;
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(bmain, ob, single_collection_index);
+ Collection *collection;
bool ok = false;
if (ob == NULL)
return OPERATOR_CANCELLED;
- /* linking to same group requires its own loop so we can avoid
- * looking up the active objects groups each time */
+ /* linking to same collection requires its own loop so we can avoid
+ * looking up the active objects collections each time */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (single_group && group != single_group)
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (single_collection && collection != single_collection)
continue;
- if (BKE_group_object_exists(group, ob)) {
- /* Remove groups from selected objects */
+ if (BKE_collection_has_object(collection, ob)) {
+ /* Remove collections from selected objects */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_group_object_unlink(group, base->object);
+ BKE_collection_object_remove(bmain, collection, base->object, false);
ok = 1;
}
CTX_DATA_END;
@@ -229,7 +230,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
}
if (!ok)
- BKE_report(op->reports, RPT_ERROR, "Active object contains no groups");
+ BKE_report(op->reports, RPT_ERROR, "Active object contains no collections");
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
@@ -237,14 +238,14 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GROUP_OT_objects_remove_active(wmOperatorType *ot)
+void COLLECTION_OT_objects_remove_active(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Remove Selected From Active Group";
- ot->description = "Remove the object from an object group that contains the active object";
- ot->idname = "GROUP_OT_objects_remove_active";
+ ot->name = "Remove Selected From Active Collection";
+ ot->description = "Remove the object from an object collection that contains the active object";
+ ot->idname = "COLLECTION_OT_objects_remove_active";
/* api callbacks */
ot->exec = objects_remove_active_exec;
@@ -255,19 +256,19 @@ void GROUP_OT_objects_remove_active(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to remove other selected objects from");
- RNA_def_enum_funcs(prop, group_object_active_itemf);
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to remove other selected objects from");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
-static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_object_groups_clear(base->object);
+ BKE_object_groups_clear(bmain, base->object);
}
CTX_DATA_END;
@@ -277,43 +278,43 @@ static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void GROUP_OT_objects_remove_all(wmOperatorType *ot)
+void COLLECTION_OT_objects_remove_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove From All Groups";
- ot->description = "Remove selected objects from all groups";
- ot->idname = "GROUP_OT_objects_remove_all";
+ ot->name = "Remove From All Unlinked Collections";
+ ot->description = "Remove selected objects from all collections not used in a scene";
+ ot->idname = "COLLECTION_OT_objects_remove_all";
/* api callbacks */
- ot->exec = group_objects_remove_all_exec;
+ ot->exec = collection_objects_remove_all_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int group_objects_remove_exec(bContext *C, wmOperator *op)
+static int collection_objects_remove_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- int single_group_index = RNA_enum_get(op->ptr, "group");
- Group *single_group = group_object_active_find_index(ob, single_group_index);
- Group *group;
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(bmain, ob, single_collection_index);
+ Collection *collection;
bool updated = false;
if (ob == NULL)
return OPERATOR_CANCELLED;
- for (group = bmain->group.first; group; group = group->id.next) {
- if (single_group && group != single_group)
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (single_collection && collection != single_collection)
continue;
- if (!BKE_group_object_exists(group, ob))
+ if (!BKE_collection_has_object(collection, ob))
continue;
- /* now remove all selected objects from the group */
+ /* now remove all selected objects from the collection */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_group_object_unlink(group, base->object);
+ BKE_collection_object_remove(bmain, collection, base->object, false);
updated = true;
}
CTX_DATA_END;
@@ -328,17 +329,17 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GROUP_OT_objects_remove(wmOperatorType *ot)
+void COLLECTION_OT_objects_remove(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Remove From Group";
- ot->description = "Remove selected objects from a group";
- ot->idname = "GROUP_OT_objects_remove";
+ ot->name = "Remove From Collection";
+ ot->description = "Remove selected objects from a collection";
+ ot->idname = "COLLECTION_OT_objects_remove";
/* api callbacks */
- ot->exec = group_objects_remove_exec;
+ ot->exec = collection_objects_remove_exec;
ot->invoke = WM_menu_invoke;
ot->poll = ED_operator_objectmode;
@@ -346,25 +347,24 @@ void GROUP_OT_objects_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to remove this object from");
- RNA_def_enum_funcs(prop, group_object_active_itemf);
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to remove this object from");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
-static int group_create_exec(bContext *C, wmOperator *op)
+static int collection_create_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Group *group = NULL;
char name[MAX_ID_NAME - 2]; /* id name */
RNA_string_get(op->ptr, "name", name);
- group = BKE_group_add(bmain, name);
+ Collection *collection = BKE_collection_add(bmain, NULL, name);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- BKE_group_object_add(group, base->object);
+ BKE_collection_object_add(bmain, collection, base->object);
}
CTX_DATA_END;
@@ -374,102 +374,101 @@ static int group_create_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GROUP_OT_create(wmOperatorType *ot)
+void COLLECTION_OT_create(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Create New Group";
- ot->description = "Create an object group from selected objects";
- ot->idname = "GROUP_OT_create";
+ ot->name = "Create New Collection";
+ ot->description = "Create an object collection from selected objects";
+ ot->idname = "COLLECTION_OT_create";
/* api callbacks */
- ot->exec = group_create_exec;
+ ot->exec = collection_create_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_string(ot->srna, "name", "Group", MAX_ID_NAME - 2, "Name", "Name of the new group");
+ RNA_def_string(ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Name of the new collection");
}
/****************** properties window operators *********************/
-static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- Group *group;
if (ob == NULL)
return OPERATOR_CANCELLED;
- group = BKE_group_add(bmain, "Group");
- BKE_group_object_add(group, ob);
+ Collection *collection = BKE_collection_add(bmain, NULL, "Collection");
+ BKE_collection_object_add(bmain, collection, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_add(wmOperatorType *ot)
+void OBJECT_OT_collection_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add to Group";
- ot->idname = "OBJECT_OT_group_add";
- ot->description = "Add an object to a new group";
+ ot->name = "Add to Collection";
+ ot->idname = "OBJECT_OT_collection_add";
+ ot->description = "Add an object to a new collection";
/* api callbacks */
- ot->exec = group_add_exec;
+ ot->exec = collection_add_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int group_link_exec(bContext *C, wmOperator *op)
+static int collection_link_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_context(C);
- Group *group = BLI_findlink(&bmain->group, RNA_enum_get(op->ptr, "group"));
+ Collection *collection = BLI_findlink(&bmain->collection, RNA_enum_get(op->ptr, "collection"));
- if (ELEM(NULL, ob, group))
+ if (ELEM(NULL, ob, collection))
return OPERATOR_CANCELLED;
- /* Early return check, if the object is already in group
+ /* Early return check, if the object is already in collection
* we could skip all the dependency check and just consider
* operator is finished.
*/
- if (BKE_group_object_exists(group, ob)) {
+ if (BKE_collection_has_object(collection, ob)) {
return OPERATOR_FINISHED;
}
- /* Adding object to group which is used as dupligroup for self is bad idea.
+ /* Adding object to collection which is used as duplicollection for self is bad idea.
*
- * It is also bad idea to add object to group which is in group which
+ * It is also bad idea to add object to collection which is in collection which
* contains our current object.
*/
- if (BKE_group_object_cyclic_check(bmain, ob, group)) {
- BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected");
+ if (BKE_collection_object_cyclic_check(bmain, ob, collection)) {
+ BKE_report(op->reports, RPT_ERROR, "Could not add the collection because of dependency cycle detected");
return OPERATOR_CANCELLED;
}
- BKE_group_object_add(group, ob);
+ BKE_collection_object_add(bmain, collection, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_link(wmOperatorType *ot)
+void OBJECT_OT_collection_link(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Link to Group";
- ot->idname = "OBJECT_OT_group_link";
- ot->description = "Add an object to an existing group";
+ ot->name = "Link to Collection";
+ ot->idname = "OBJECT_OT_collection_link";
+ ot->description = "Add an object to an existing collection";
/* api callbacks */
- ot->exec = group_link_exec;
+ ot->exec = collection_link_exec;
ot->invoke = WM_enum_search_invoke;
ot->poll = ED_operator_objectmode;
@@ -477,36 +476,37 @@ void OBJECT_OT_group_link(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "");
- RNA_def_enum_funcs(prop, RNA_group_local_itemf);
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
+ RNA_def_enum_funcs(prop, RNA_collection_local_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
-static int group_remove_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
Object *ob = ED_object_context(C);
- Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!ob || !group)
+ if (!ob || !collection)
return OPERATOR_CANCELLED;
- BKE_group_object_unlink(group, ob);
+ BKE_collection_object_remove(bmain, collection, ob, false);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_remove(wmOperatorType *ot)
+void OBJECT_OT_collection_remove(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Group";
- ot->idname = "OBJECT_OT_group_remove";
- ot->description = "Remove the active object from this group";
+ ot->name = "Remove Collection";
+ ot->idname = "OBJECT_OT_collection_remove";
+ ot->description = "Remove the active object from this collection";
/* api callbacks */
- ot->exec = group_remove_exec;
+ ot->exec = collection_remove_exec;
ot->poll = ED_operator_objectmode;
/* flags */
@@ -514,47 +514,47 @@ void OBJECT_OT_group_remove(wmOperatorType *ot)
}
-static int group_unlink_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_unlink_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!group)
+ if (!collection)
return OPERATOR_CANCELLED;
- BKE_libblock_delete(bmain, group);
+ BKE_libblock_delete(bmain, collection);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_unlink(wmOperatorType *ot)
+void OBJECT_OT_collection_unlink(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Unlink Group";
- ot->idname = "OBJECT_OT_group_unlink";
- ot->description = "Unlink the group from all objects";
+ ot->name = "Unlink Collection";
+ ot->idname = "OBJECT_OT_collection_unlink";
+ ot->description = "Unlink the collection from all objects";
/* api callbacks */
- ot->exec = group_unlink_exec;
+ ot->exec = collection_unlink_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select objects in the same group as the active */
+static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select objects in the same collection as the active */
{
- Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!group)
+ if (!collection)
return OPERATOR_CANCELLED;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- if (BKE_group_object_exists(group, base->object)) {
+ if (BKE_collection_has_object_recursive(collection, base->object)) {
ED_object_base_select(base, BA_SELECT);
}
}
@@ -566,12 +566,12 @@ static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select o
return OPERATOR_FINISHED;
}
-void OBJECT_OT_grouped_select(wmOperatorType *ot)
+void OBJECT_OT_collection_objects_select(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Grouped";
- ot->idname = "OBJECT_OT_grouped_select";
- ot->description = "Select all objects in group";
+ ot->name = "Select Objects in Collection";
+ ot->idname = "OBJECT_OT_collection_objects_select";
+ ot->description = "Select all objects in collection";
/* api callbacks */
ot->exec = select_grouped_exec;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index dbb81be124a..445b14982ee 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -88,6 +88,7 @@ void OBJECT_OT_paths_clear(struct wmOperatorType *ot);
void OBJECT_OT_forcefield_toggle(struct wmOperatorType *ot);
void OBJECT_OT_move_to_collection(struct wmOperatorType *ot);
+void OBJECT_OT_link_to_collection(struct wmOperatorType *ot);
/* object_select.c */
void OBJECT_OT_select_all(struct wmOperatorType *ot);
@@ -99,7 +100,6 @@ void OBJECT_OT_select_grouped(struct wmOperatorType *ot);
void OBJECT_OT_select_mirror(struct wmOperatorType *ot);
void OBJECT_OT_select_more(struct wmOperatorType *ot);
void OBJECT_OT_select_less(struct wmOperatorType *ot);
-void OBJECT_OT_select_same_group(struct wmOperatorType *ot);
void OBJECT_OT_select_same_collection(struct wmOperatorType *ot);
/* object_add.c */
@@ -115,7 +115,7 @@ void OBJECT_OT_lamp_add(struct wmOperatorType *ot);
void OBJECT_OT_effector_add(struct wmOperatorType *ot);
void OBJECT_OT_camera_add(struct wmOperatorType *ot);
void OBJECT_OT_speaker_add(struct wmOperatorType *ot);
-void OBJECT_OT_group_instance_add(struct wmOperatorType *ot);
+void OBJECT_OT_collection_instance_add(struct wmOperatorType *ot);
void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot);
void OBJECT_OT_duplicate(struct wmOperatorType *ot);
@@ -134,11 +134,11 @@ void OBJECT_OT_hook_reset(struct wmOperatorType *ot);
void OBJECT_OT_hook_recenter(struct wmOperatorType *ot);
/* object_group.c */
-void GROUP_OT_create(struct wmOperatorType *ot);
-void GROUP_OT_objects_remove_all(struct wmOperatorType *ot);
-void GROUP_OT_objects_remove(struct wmOperatorType *ot);
-void GROUP_OT_objects_add_active(struct wmOperatorType *ot);
-void GROUP_OT_objects_remove_active(struct wmOperatorType *ot);
+void COLLECTION_OT_create(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_remove_all(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_remove(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_add_active(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_remove_active(struct wmOperatorType *ot);
/* object_modifier.c */
int edit_modifier_poll_generic(struct bContext *C, struct StructRNA *rna_type, int obtype_flag);
@@ -251,11 +251,11 @@ void OBJECT_OT_shape_key_mirror(struct wmOperatorType *ot);
void OBJECT_OT_shape_key_move(struct wmOperatorType *ot);
/* object_group.c */
-void OBJECT_OT_group_add(struct wmOperatorType *ot);
-void OBJECT_OT_group_link(struct wmOperatorType *ot);
-void OBJECT_OT_group_remove(struct wmOperatorType *ot);
-void OBJECT_OT_group_unlink(struct wmOperatorType *ot);
-void OBJECT_OT_grouped_select(struct wmOperatorType *ot);
+void OBJECT_OT_collection_add(struct wmOperatorType *ot);
+void OBJECT_OT_collection_link(struct wmOperatorType *ot);
+void OBJECT_OT_collection_remove(struct wmOperatorType *ot);
+void OBJECT_OT_collection_unlink(struct wmOperatorType *ot);
+void OBJECT_OT_collection_objects_select(struct wmOperatorType *ot);
/* object_bake.c */
void OBJECT_OT_bake_image(wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index c4c86b3932d..c47d741f818 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -93,7 +93,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_select_random);
WM_operatortype_append(OBJECT_OT_select_all);
- WM_operatortype_append(OBJECT_OT_select_same_group);
WM_operatortype_append(OBJECT_OT_select_same_collection);
WM_operatortype_append(OBJECT_OT_select_by_type);
WM_operatortype_append(OBJECT_OT_select_linked);
@@ -102,11 +101,11 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_select_more);
WM_operatortype_append(OBJECT_OT_select_less);
- WM_operatortype_append(GROUP_OT_create);
- WM_operatortype_append(GROUP_OT_objects_remove_all);
- WM_operatortype_append(GROUP_OT_objects_remove);
- WM_operatortype_append(GROUP_OT_objects_add_active);
- WM_operatortype_append(GROUP_OT_objects_remove_active);
+ WM_operatortype_append(COLLECTION_OT_create);
+ WM_operatortype_append(COLLECTION_OT_objects_remove_all);
+ WM_operatortype_append(COLLECTION_OT_objects_remove);
+ WM_operatortype_append(COLLECTION_OT_objects_add_active);
+ WM_operatortype_append(COLLECTION_OT_objects_remove_active);
WM_operatortype_append(OBJECT_OT_delete);
WM_operatortype_append(OBJECT_OT_text_add);
@@ -120,7 +119,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_add);
WM_operatortype_append(OBJECT_OT_add_named);
WM_operatortype_append(OBJECT_OT_effector_add);
- WM_operatortype_append(OBJECT_OT_group_instance_add);
+ WM_operatortype_append(OBJECT_OT_collection_instance_add);
WM_operatortype_append(OBJECT_OT_metaball_add);
WM_operatortype_append(OBJECT_OT_duplicates_make_real);
WM_operatortype_append(OBJECT_OT_duplicate);
@@ -213,6 +212,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(TRANSFORM_OT_vertex_warp);
WM_operatortype_append(OBJECT_OT_move_to_collection);
+ WM_operatortype_append(OBJECT_OT_link_to_collection);
WM_operatortype_append(OBJECT_OT_shape_key_add);
WM_operatortype_append(OBJECT_OT_shape_key_remove);
@@ -221,11 +221,11 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_shape_key_mirror);
WM_operatortype_append(OBJECT_OT_shape_key_move);
- WM_operatortype_append(OBJECT_OT_group_add);
- WM_operatortype_append(OBJECT_OT_group_link);
- WM_operatortype_append(OBJECT_OT_group_remove);
- WM_operatortype_append(OBJECT_OT_group_unlink);
- WM_operatortype_append(OBJECT_OT_grouped_select);
+ WM_operatortype_append(OBJECT_OT_collection_add);
+ WM_operatortype_append(OBJECT_OT_collection_link);
+ WM_operatortype_append(OBJECT_OT_collection_remove);
+ WM_operatortype_append(OBJECT_OT_collection_unlink);
+ WM_operatortype_append(OBJECT_OT_collection_objects_select);
WM_operatortype_append(OBJECT_OT_hook_add_selob);
WM_operatortype_append(OBJECT_OT_hook_add_newob);
@@ -395,11 +395,11 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "ANIM_OT_keyframe_delete_v3d", IKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_verify_item(keymap, "ANIM_OT_keying_set_active_set", IKEY, KM_PRESS, KM_CTRL | KM_SHIFT | KM_ALT, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_create", GKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove", GKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_all", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL | KM_ALT, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_create", GKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_remove", GKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_remove_all", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL | KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_object_specials", WKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index dd919aedabb..c5cf946cfb3 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -70,7 +70,6 @@
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_fcurve.h"
#include "BKE_idprop.h"
#include "BKE_lamp.h"
@@ -329,7 +328,7 @@ static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
else {
/* error.. cannot continue */
- BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or group");
+ BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or collection");
return OPERATOR_CANCELLED;
}
@@ -343,7 +342,8 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
if (gob->dup_group != NULL) {
- Base *base = BLI_findlink(&gob->dup_group->view_layer->object_bases, RNA_enum_get(op->ptr, "object"));
+ const ListBase dup_group_objects = BKE_collection_object_cache_get(gob->dup_group);
+ Base *base = BLI_findlink(&dup_group_objects, RNA_enum_get(op->ptr, "object"));
ob = base->object;
}
else {
@@ -385,8 +385,8 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
}
/* Generic itemf's for operators that take library args */
-static const EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *proxy_collection_object_itemf(bContext *C, PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop), bool *r_free)
{
EnumPropertyItem item_tmp = {0}, *item = NULL;
int totitem = 0;
@@ -397,13 +397,13 @@ static const EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA
return DummyRNA_DEFAULT_items;
/* find the object to affect */
- FOREACH_GROUP_OBJECT_BEGIN(ob->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(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;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -431,8 +431,8 @@ void OBJECT_OT_proxy_make(wmOperatorType *ot)
/* properties */
/* XXX, relies on hard coded ID at the moment */
prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Proxy Object",
- "Name of lib-linked/grouped object to make a proxy for");
- RNA_def_enum_funcs(prop, proxy_group_object_itemf);
+ "Name of lib-linked/collection object to make a proxy for");
+ RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
@@ -1343,7 +1343,8 @@ static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr))
static int make_links_scene_exec(bContext *C, wmOperator *op)
{
- Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
+ Main *bmain = CTX_data_main(C);
+ Scene *scene_to = BLI_findlink(&bmain->scene, RNA_enum_get(op->ptr, "scene"));
if (scene_to == NULL) {
BKE_report(op->reports, RPT_ERROR, "Could not find scene");
@@ -1360,10 +1361,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- SceneCollection *sc_to = BKE_collection_master(&scene_to->id);
+ Collection *collection_to = BKE_collection_master(scene_to);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- BKE_collection_object_add(&scene_to->id, sc_to, base->object);
+ BKE_collection_object_add(bmain, collection_to, base->object);
}
CTX_DATA_END;
@@ -1379,7 +1380,7 @@ enum {
MAKE_LINKS_MATERIALS = 2,
MAKE_LINKS_ANIMDATA = 3,
MAKE_LINKS_GROUP = 4,
- MAKE_LINKS_DUPLIGROUP = 5,
+ MAKE_LINKS_DUPLICOLLECTION = 5,
MAKE_LINKS_MODIFIERS = 6,
MAKE_LINKS_FONTS = 7,
};
@@ -1400,7 +1401,7 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst
break;
case MAKE_LINKS_ANIMDATA:
case MAKE_LINKS_GROUP:
- case MAKE_LINKS_DUPLIGROUP:
+ case MAKE_LINKS_DUPLICOLLECTION:
return true;
case MAKE_LINKS_MODIFIERS:
if (!ELEM(OB_EMPTY, ob_src->type, ob_dst->type)) {
@@ -1424,16 +1425,16 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
ID *obdata_id;
int a;
- /* group */
- LinkNode *ob_groups = NULL;
+ /* collection */
+ LinkNode *ob_collections = NULL;
bool is_cycle = false;
bool is_lib = false;
ob_src = ED_object_active_context(C);
- /* avoid searching all groups in source object each time */
+ /* avoid searching all collections in source object each time */
if (type == MAKE_LINKS_GROUP) {
- ob_groups = BKE_object_groups(ob_src);
+ ob_collections = BKE_object_groups(bmain, ob_src);
}
CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases)
@@ -1478,15 +1479,15 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
break;
case MAKE_LINKS_GROUP:
{
- LinkNode *group_node;
+ LinkNode *collection_node;
- /* first clear groups */
- BKE_object_groups_clear(ob_dst);
+ /* first clear collections */
+ BKE_object_groups_clear(bmain, ob_dst);
- /* now add in the groups from the link nodes */
- for (group_node = ob_groups; group_node; group_node = group_node->next) {
- if (ob_dst->dup_group != group_node->link) {
- BKE_group_object_add(group_node->link, ob_dst);
+ /* now add in the collections from the link nodes */
+ for (collection_node = ob_collections; collection_node; collection_node = collection_node->next) {
+ if (ob_dst->dup_group != collection_node->link) {
+ BKE_collection_object_add(bmain, collection_node->link, ob_dst);
}
else {
is_cycle = true;
@@ -1494,11 +1495,11 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
}
break;
}
- case MAKE_LINKS_DUPLIGROUP:
+ case MAKE_LINKS_DUPLICOLLECTION:
ob_dst->dup_group = ob_src->dup_group;
if (ob_dst->dup_group) {
id_us_plus(&ob_dst->dup_group->id);
- ob_dst->transflag |= OB_DUPLIGROUP;
+ ob_dst->transflag |= OB_DUPLICOLLECTION;
}
break;
case MAKE_LINKS_MODIFIERS:
@@ -1542,12 +1543,12 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
if (type == MAKE_LINKS_GROUP) {
- if (ob_groups) {
- BLI_linklist_free(ob_groups, NULL);
+ if (ob_collections) {
+ BLI_linklist_free(ob_collections, NULL);
}
if (is_cycle) {
- BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected");
+ BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
}
}
@@ -1595,7 +1596,7 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
{MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Materials", ""},
{MAKE_LINKS_ANIMDATA, "ANIMATION", 0, "Animation Data", ""},
{MAKE_LINKS_GROUP, "GROUPS", 0, "Group", ""},
- {MAKE_LINKS_DUPLIGROUP, "DUPLIGROUP", 0, "DupliGroup", ""},
+ {MAKE_LINKS_DUPLICOLLECTION, "DUPLICOLLECTION", 0, "DupliGroup", ""},
{MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""},
{MAKE_LINKS_FONTS, "FONTS", 0, "Fonts", ""},
{0, NULL, 0, NULL, NULL}};
@@ -1619,19 +1620,11 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
-static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups)
+static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob)
{
/* base gets copy of object */
Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
- if (copy_groups) {
- if (ob->flag & OB_FROMGROUP) {
- obn->flag |= OB_FROMGROUP;
- }
- }
- else {
- /* copy already clears */
- }
/* remap gpencil parenting */
if (scene->gpd) {
@@ -1647,42 +1640,42 @@ static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob,
return obn;
}
-static void libblock_relink_scene_collection(SceneCollection *sc)
+static void libblock_relink_collection(Collection *collection)
{
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- BKE_libblock_relink_to_newid(link->data);
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ BKE_libblock_relink_to_newid(&cob->ob->id);
}
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- libblock_relink_scene_collection(nsc);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ libblock_relink_collection(child->collection);
}
}
-static void single_object_users_scene_collection(Main *bmain, Scene *scene, SceneCollection *sc, const int flag, const bool copy_groups)
+static void single_object_users_collection(Main *bmain, Scene *scene, Collection *collection, const int flag, const bool copy_collections)
{
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- Object *ob = link->data;
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Object *ob = cob->ob;
/* an object may be in more than one collection */
if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
- link->data = single_object_users_object(bmain, scene, link->data, copy_groups);
+ cob->ob = single_object_users_object(bmain, scene, cob->ob);
}
}
}
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ single_object_users_collection(bmain, scene, child->collection, flag, copy_collections);
}
}
-/* Warning, sets ID->newid pointers of objects and groups, but does not clear them. */
-static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups)
+/* Warning, sets ID->newid pointers of objects and collections, but does not clear them. */
+static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
{
- Group *group, *groupn;
+ Collection *collection, *collectionn;
/* duplicate all the objects of the scene */
- SceneCollection *msc = BKE_collection_master(&scene->id);
- single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups);
+ Collection *master_collection = BKE_collection_master(scene);
+ single_object_users_collection(bmain, scene, master_collection, flag, copy_collections);
/* loop over ViewLayers and assign the pointers accordingly */
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
@@ -1691,40 +1684,39 @@ 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->view_layer->object_bases.first) {
+ /* duplicate collections that consist entirely of duplicated objects */
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (copy_collections) {
bool all_duplicated = true;
+ bool any_duplicated = false;
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- if (object->id.newid == NULL) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ any_duplicated = true;
+ if (cob->ob->id.newid == NULL) {
all_duplicated = false;
break;
}
}
- FOREACH_GROUP_OBJECT_END;
- if (all_duplicated) {
- groupn = ID_NEW_SET(group, BKE_group_copy(bmain, group));
+ if (any_duplicated && all_duplicated) {
+ // TODO: test if this works, with child collections ..
+ collectionn = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
- FOREACH_GROUP_BASE_BEGIN(groupn, base)
- {
- base->object = (Object *)base->object->id.newid;
+ for (CollectionObject *cob = collectionn->gobject.first; cob; cob = cob->next) {
+ cob->ob = (Object *)cob->ob->id.newid;
}
- FOREACH_GROUP_BASE_END
}
}
}
- /* group pointers in scene */
+ /* collection pointers in scene */
BKE_scene_groups_relink(scene);
ID_NEW_REMAP(scene->camera);
if (v3d) ID_NEW_REMAP(v3d->camera);
- /* object and group pointers */
- libblock_relink_scene_collection(msc);
+ /* object and collection pointers */
+ libblock_relink_collection(master_collection);
}
/* not an especially efficient function, only added so the single user
@@ -1917,9 +1909,9 @@ static void single_mat_users_expand(Main *bmain)
}
/* used for copying scenes */
-void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bool copy_groups)
+void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bool copy_collections)
{
- single_object_users(bmain, scene, NULL, 0, copy_groups);
+ single_object_users(bmain, scene, NULL, 0, copy_collections);
if (full) {
single_obdata_users(bmain, scene, NULL, 0);
@@ -2038,7 +2030,7 @@ static void tag_localizable_objects(bContext *C, const int mode)
* Instance indirectly referenced zero user objects,
* otherwise they're lost on reload, see T40595.
*/
-static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene, ViewLayer *view_layer, SceneCollection *sc)
+static bool make_local_all__instance_indirect_unused(Main *bmain, ViewLayer *view_layer, Collection *collection)
{
Object *ob;
bool changed = false;
@@ -2049,7 +2041,7 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene,
id_us_plus(&ob->id);
- BKE_collection_object_add(&scene->id, sc, ob);
+ BKE_collection_object_add(bmain, collection, ob);
base = BKE_view_layer_base_find(view_layer, ob);
base->flag |= BASE_SELECTED;
BKE_scene_object_base_flag_sync_from_base(base);
@@ -2117,7 +2109,6 @@ static void make_local_material_tag(Material *ma)
static int make_local_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
ParticleSystem *psys;
Material *ma, ***matarar;
const int mode = RNA_enum_get(op->ptr, "type");
@@ -2126,14 +2117,14 @@ static int make_local_exec(bContext *C, wmOperator *op)
/* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */
if (mode == MAKE_LOCAL_ALL) {
ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *scene_collection = CTX_data_scene_collection(C);
+ Collection *collection = CTX_data_collection(C);
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
/* De-select so the user can differentiate newly instanced from existing objects. */
BKE_view_layer_base_deselect_all(view_layer);
- if (make_local_all__instance_indirect_unused(bmain, scene, view_layer, scene_collection)) {
+ if (make_local_all__instance_indirect_unused(bmain, view_layer, collection)) {
BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss");
}
}
@@ -2282,7 +2273,7 @@ static int make_override_static_invoke(bContext *C, wmOperator *op, const wmEven
}
else {
/* Error.. cannot continue. */
- BKE_report(op->reports, RPT_ERROR, "Can only make static override for a referenced object or group");
+ BKE_report(op->reports, RPT_ERROR, "Can only make static override for a referenced object or collection");
return OPERATOR_CANCELLED;
}
@@ -2296,23 +2287,24 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
bool success = false;
if (!ID_IS_LINKED(obact) && obact->dup_group != NULL && ID_IS_LINKED(obact->dup_group)) {
- Base *base = BLI_findlink(&obact->dup_group->view_layer->object_bases, RNA_enum_get(op->ptr, "object"));
- Object *obgroup = obact;
+ const ListBase dup_collection_objects = BKE_collection_object_cache_get(obact->dup_group);
+ Base *base = BLI_findlink(&dup_collection_objects, RNA_enum_get(op->ptr, "object"));
+ Object *obcollection = obact;
obact = base->object;
- Group *group = obgroup->dup_group;
+ Collection *collection = obcollection->dup_group;
- /* First, we make a static override of the linked group itself. */
- group->id.tag |= LIB_TAG_DOIT;
+ /* First, we make a static override of the linked collection itself. */
+ collection->id.tag |= LIB_TAG_DOIT;
- /* Then, we make static override of the whole set of objects in the group. */
- FOREACH_GROUP_OBJECT_BEGIN(group, ob)
+ /* Then, we make static override of the whole set of objects in the Collection. */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, ob)
{
ob->id.tag |= LIB_TAG_DOIT;
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- /* Then, we make static override of the whole set of objects in the group. */
- FOREACH_GROUP_OBJECT_BEGIN(group, ob)
+ /* Then, we make static override of the whole set of objects in the collection. */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, ob)
{
if (ob->type == OB_ARMATURE && ob->pose != NULL) {
for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
@@ -2322,25 +2314,25 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
}
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
success = BKE_override_static_create_from_tag(bmain);
/* Intantiate our newly overridden objects in scene, if not yet done. */
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- Group *new_group = (Group *)group->id.newid;
- FOREACH_GROUP_OBJECT_BEGIN(new_group, new_ob)
+ Collection *new_collection = (Collection *)collection->id.newid;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(new_collection, new_ob)
{
if (new_ob != NULL &&
new_ob->id.override_static != NULL &&
(base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL)
{
- BKE_collection_object_add_from(scene, obgroup, new_ob);
+ BKE_collection_object_add_from(bmain, scene, obcollection, new_ob);
DEG_id_tag_update_ex(bmain, &new_ob->id, OB_RECALC_OB | DEG_TAG_BASE_FLAGS_UPDATE);
- /* parent to 'group' empty */
+ /* parent to 'collection' empty */
if (new_ob->parent == NULL) {
- new_ob->parent = obgroup;
+ new_ob->parent = obcollection;
}
if (new_ob == (Object *)obact->id.newid) {
base = BKE_view_layer_base_find(view_layer, new_ob);
@@ -2354,10 +2346,10 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
BKE_override_static_operations_create(&new_ob->id, true);
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- /* obgroup is no more dupligroup-ing, it merely parents whole group of overriding instantiated objects. */
- obgroup->dup_group = NULL;
+ /* obcollection is no more duplicollection-ing, it merely parents whole collection of overriding instantiated objects. */
+ obcollection->dup_group = NULL;
/* Also, we'd likely want to lock by default things like transformations of implicitly overriden objects? */
@@ -2423,8 +2415,8 @@ void OBJECT_OT_make_override_static(wmOperatorType *ot)
/* properties */
PropertyRNA *prop;
prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Override Object",
- "Name of lib-linked/group object to make an override from");
- RNA_def_enum_funcs(prop, proxy_group_object_itemf);
+ "Name of lib-linked/collection object to make an override from");
+ RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
@@ -2441,16 +2433,16 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */
const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
- const bool copy_groups = false;
+ const bool copy_collections = false;
bool update_deps = false;
if (RNA_boolean_get(op->ptr, "object")) {
if (flag == SELECT) {
BKE_view_layer_selected_objects_tag(view_layer, OB_DONE);
- single_object_users(bmain, scene, v3d, OB_DONE, copy_groups);
+ single_object_users(bmain, scene, v3d, OB_DONE, copy_collections);
}
else {
- single_object_users(bmain, scene, v3d, 0, copy_groups);
+ single_object_users(bmain, scene, v3d, 0, copy_collections);
}
/* needed since object relationships may have changed */
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index d0d0418c861..d5e6f08352f 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -50,8 +50,8 @@
#include "BLT_translation.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -267,12 +267,12 @@ static bool object_select_all_by_material(bContext *C, Material *mat)
static bool object_select_all_by_dup_group(bContext *C, Object *ob)
{
bool changed = false;
- Group *dup_group = (ob->transflag & OB_DUPLIGROUP) ? ob->dup_group : NULL;
+ Collection *dup_group = (ob->transflag & OB_DUPLICOLLECTION) ? ob->dup_group : NULL;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- Group *dup_group_other = (base->object->transflag & OB_DUPLIGROUP) ? base->object->dup_group : NULL;
+ Collection *dup_group_other = (base->object->transflag & OB_DUPLICOLLECTION) ? base->object->dup_group : NULL;
if (dup_group == dup_group_other) {
ED_object_base_select(base, BA_SELECT);
changed = true;
@@ -475,7 +475,6 @@ enum {
OBJECT_GRPSEL_SIBLINGS = 3,
OBJECT_GRPSEL_TYPE = 4,
OBJECT_GRPSEL_COLLECTION = 5,
- OBJECT_GRPSEL_GROUP = 6,
OBJECT_GRPSEL_HOOK = 7,
OBJECT_GRPSEL_PASS = 8,
OBJECT_GRPSEL_COLOR = 9,
@@ -490,7 +489,6 @@ static const EnumPropertyItem prop_select_grouped_types[] = {
{OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"},
{OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"},
{OBJECT_GRPSEL_COLLECTION, "COLLECTION", 0, "Collection", "Shared collection"},
- {OBJECT_GRPSEL_GROUP, "GROUP", 0, "Group", "Shared group"},
{OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
{OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
{OBJECT_GRPSEL_COLOR, "COLOR", 0, "Color", "Object Color"},
@@ -542,30 +540,30 @@ static bool select_grouped_parent(bContext *C) /* Makes parent active and de-sel
}
-#define GROUP_MENU_MAX 24
-static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */
+#define COLLECTION_MENU_MAX 24
+static bool select_grouped_collection(bContext *C, Object *ob) /* Select objects in the same group as the active */
{
bool changed = false;
- Group *group, *ob_groups[GROUP_MENU_MAX];
- int group_count = 0, i;
+ Collection *collection, *ob_collections[COLLECTION_MENU_MAX];
+ int collection_count = 0, i;
uiPopupMenu *pup;
uiLayout *layout;
- for (group = CTX_data_main(C)->group.first; group && group_count < GROUP_MENU_MAX; group = group->id.next) {
- if (BKE_group_object_exists(group, ob)) {
- ob_groups[group_count] = group;
- group_count++;
+ for (collection = CTX_data_main(C)->collection.first; collection && collection_count < COLLECTION_MENU_MAX; collection = collection->id.next) {
+ if (BKE_collection_has_object(collection, ob)) {
+ ob_collections[collection_count] = collection;
+ collection_count++;
}
}
- if (!group_count)
+ if (!collection_count)
return 0;
- else if (group_count == 1) {
- group = ob_groups[0];
+ else if (collection_count == 1) {
+ collection = ob_collections[0];
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- if (BKE_group_object_exists(group, base->object)) {
+ if (BKE_collection_has_object(collection, base->object)) {
ED_object_base_select(base, BA_SELECT);
changed = true;
}
@@ -576,12 +574,12 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in
}
/* build the menu. */
- pup = UI_popup_menu_begin(C, IFACE_("Select Group"), ICON_NONE);
+ pup = UI_popup_menu_begin(C, IFACE_("Select Collection"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
- for (i = 0; i < group_count; i++) {
- group = ob_groups[i];
- uiItemStringO(layout, group->id.name + 2, 0, "OBJECT_OT_select_same_group", "group", group->id.name + 2);
+ for (i = 0; i < collection_count; i++) {
+ collection = ob_collections[i];
+ uiItemStringO(layout, collection->id.name + 2, 0, "OBJECT_OT_select_same_collection", "collection", collection->id.name + 2);
}
UI_popup_menu_end(C, pup);
@@ -662,60 +660,6 @@ static bool select_grouped_type(bContext *C, Object *ob)
return changed;
}
-#define COLLECTION_MENU_MAX 24
-static bool select_grouped_collection(bContext *C, Object *ob) /* Select objects in the same collection as the active */
-{
- typedef struct EnumeratedCollection {
- struct SceneCollection *collection;
- int index;
- } EnumeratedCollection;
-
- bool changed = false;
- SceneCollection *collection;
- EnumeratedCollection ob_collections[COLLECTION_MENU_MAX];
- int collection_count = 0, i;
- uiPopupMenu *pup;
- uiLayout *layout;
-
- i = 0;
- FOREACH_SCENE_COLLECTION_BEGIN(CTX_data_scene(C), scene_collection)
- {
- if (BKE_collection_object_exists(scene_collection, ob)) {
- ob_collections[collection_count].index = i;
- ob_collections[collection_count].collection = scene_collection;
- if (++collection_count >= COLLECTION_MENU_MAX) {
- break;
- }
- }
- i++;
- }
- FOREACH_SCENE_COLLECTION_END;
-
- if (!collection_count) {
- return 0;
- }
- else if (collection_count == 1) {
- collection = ob_collections[0].collection;
- return BKE_collection_objects_select(CTX_data_view_layer(C), collection);
- }
-
- /* build the menu. */
- pup = UI_popup_menu_begin(C, IFACE_("Select Collection"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- for (i = 0; i < collection_count; i++) {
- uiItemIntO(layout,
- ob_collections[i].collection->name,
- ICON_NONE,
- "OBJECT_OT_select_same_collection",
- "collection_index",
- ob_collections[i].index);
- }
-
- UI_popup_menu_end(C, pup);
- return changed; /* The operator already handle this! */
-}
-
static bool select_grouped_index_object(bContext *C, Object *ob)
{
bool changed = false;
@@ -841,9 +785,6 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
case OBJECT_GRPSEL_COLLECTION:
changed |= select_grouped_collection(C, ob);
break;
- case OBJECT_GRPSEL_GROUP:
- changed |= select_grouped_group(C, ob);
- break;
case OBJECT_GRPSEL_HOOK:
changed |= select_grouped_object_hooks(C, ob);
break;
@@ -960,28 +901,28 @@ void OBJECT_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
-/**************************** Select In The Same Group ****************************/
+/**************************** Select In The Same Collection ****************************/
-static int object_select_same_group_exec(bContext *C, wmOperator *op)
+static int object_select_same_collection_exec(bContext *C, wmOperator *op)
{
- Group *group;
- char group_name[MAX_ID_NAME];
+ Collection *collection;
+ char collection_name[MAX_ID_NAME];
/* passthrough if no objects are visible */
if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
- RNA_string_get(op->ptr, "group", group_name);
+ RNA_string_get(op->ptr, "collection", collection_name);
- group = (Group *)BKE_libblock_find_name(ID_GR, group_name);
+ collection = (Collection *)BKE_libblock_find_name(ID_GR, collection_name);
- if (!group) {
+ if (!collection) {
return OPERATOR_PASS_THROUGH;
}
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- if (BKE_group_object_exists(group, base->object)) {
+ if (BKE_collection_has_object(collection, base->object)) {
ED_object_base_select(base, BA_SELECT);
}
}
@@ -993,67 +934,24 @@ static int object_select_same_group_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void OBJECT_OT_select_same_group(wmOperatorType *ot)
-{
-
- /* identifiers */
- ot->name = "Select Same Group";
- ot->description = "Select object in the same group";
- ot->idname = "OBJECT_OT_select_same_group";
-
- /* api callbacks */
- ot->exec = object_select_same_group_exec;
- ot->poll = objects_selectable_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_string(ot->srna, "group", NULL, MAX_ID_NAME, "Group", "Name of the group to select");
-}
-
-/**************************** Select In The Same Collection ****************************/
-
-static int object_select_same_collection_exec(bContext *C, wmOperator *op)
-{
- SceneCollection *collection;
-
- /* passthrough if no objects are visible */
- if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
-
- int collection_index = RNA_int_get(op->ptr, "collection_index");
- collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
-
- if (!collection) {
- return OPERATOR_PASS_THROUGH;
- }
-
- if (BKE_collection_objects_select(CTX_data_view_layer(C), collection)) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
- }
-
- return OPERATOR_FINISHED;
-}
-
void OBJECT_OT_select_same_collection(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
+
/* identifiers */
ot->name = "Select Same Collection";
ot->description = "Select object in the same collection";
ot->idname = "OBJECT_OT_select_same_collection";
-
+
/* api callbacks */
ot->exec = object_select_same_collection_exec;
ot->poll = objects_selectable_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_int(ot->srna, "collection_index", -1, -1, INT_MAX,
- "Collection Index", "Index of the collection to select", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_string(ot->srna, "collection", NULL, MAX_ID_NAME, "Collection", "Name of the collection to select");
}
+
/**************************** Select Mirror ****************************/
static int object_select_mirror_exec(bContext *C, wmOperator *op)
{
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index a862ef718d2..6b22521eedd 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -879,7 +879,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if (ob->data == NULL) {
/* special support for dupligroups */
- if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group && (ob->dup_group->id.tag & LIB_TAG_DOIT) == 0) {
+ if ((ob->transflag & OB_DUPLICOLLECTION) && ob->dup_group && (ob->dup_group->id.tag & LIB_TAG_DOIT) == 0) {
if (ID_IS_LINKED(ob->dup_group)) {
tot_lib_error++;
}
@@ -1088,7 +1088,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if ((ob_other->flag & OB_DONE) == 0 &&
((ob->data && (ob->data == ob_other->data)) ||
(ob->dup_group == ob_other->dup_group &&
- (ob->transflag | ob_other->transflag) & OB_DUPLIGROUP)))
+ (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION)))
{
ob_other->flag |= OB_DONE;
DEG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA);
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 3bcc047bf5b..f62b72679d0 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -37,8 +37,8 @@
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
@@ -83,14 +83,14 @@ bool ED_rigidbody_constraint_add(Main *bmain, Scene *scene, Object *ob, int type
}
/* create constraint group if it doesn't already exits */
if (rbw->constraints == NULL) {
- rbw->constraints = BKE_group_add(bmain, "RigidBodyConstraints");
+ rbw->constraints = BKE_collection_add(bmain, NULL, "RigidBodyConstraints");
}
/* make rigidbody constraint settings */
ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type);
ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE;
/* add constraint to rigid body constraint group */
- BKE_group_object_add(rbw->constraints, ob);
+ BKE_collection_object_add(bmain, rbw->constraints, ob);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -103,7 +103,7 @@ void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
BKE_rigidbody_remove_constraint(scene, ob);
if (rbw)
- BKE_group_object_unlink(rbw->constraints, ob);
+ BKE_collection_object_remove(bmain, rbw->constraints, ob, false);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 3553ffa5033..99976898ac1 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -42,8 +42,8 @@
#include "BLT_translation.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
@@ -109,7 +109,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
scene->rigidbody_world = rbw;
}
if (rbw->group == NULL) {
- rbw->group = BKE_group_add(bmain, "RigidBodyWorld");
+ rbw->group = BKE_collection_add(bmain, NULL, "RigidBodyWorld");
}
/* make rigidbody object settings */
@@ -120,7 +120,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
/* add object to rigid body group */
- BKE_group_object_add(rbw->group, ob);
+ BKE_collection_object_add(bmain, rbw->group, ob);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -134,7 +134,7 @@ void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
BKE_rigidbody_remove_object(scene, ob);
if (rbw)
- BKE_group_object_unlink(rbw->group, ob);
+ BKE_collection_object_remove(bmain, rbw->group, ob, false);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index d0390985181..946da6f1ed8 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -51,6 +51,7 @@
#include "DNA_world_types.h"
#include "DNA_camera_types.h"
+#include "DNA_group_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
@@ -252,7 +253,7 @@ static Scene *preview_get_scene(Main *pr_main)
return pr_main->scene.first;
}
-static const char *preview_layer_name(const char pr_type)
+static const char *preview_collection_name(const char pr_type)
{
switch (pr_type) {
case MA_FLAT:
@@ -281,19 +282,21 @@ static const char *preview_layer_name(const char pr_type)
}
}
-static void set_preview_layer(ViewLayer *view_layer, char pr_type)
+static void set_preview_collection(Scene *scene, ViewLayer *view_layer, char pr_type)
{
- LayerCollection *lc;
- const char *collection_name = preview_layer_name(pr_type);
+ LayerCollection *lc = view_layer->layer_collections.first;
+ const char *collection_name = preview_collection_name(pr_type);
- for (lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- if (STREQ(lc->scene_collection->name, collection_name)) {
- lc->flag = COLLECTION_VIEWPORT | COLLECTION_RENDER;
+ for (lc = lc->layer_collections.first; lc; lc = lc->next) {
+ if (STREQ(lc->collection->id.name + 2, collection_name)) {
+ lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER;
}
else {
- lc->flag = COLLECTION_DISABLED;
+ lc->collection->flag |= COLLECTION_RESTRICT_RENDER;
}
}
+
+ BKE_layer_collection_sync(scene, view_layer);
}
static World *preview_get_localized_world(ShaderPreview *sp, World *world)
@@ -389,10 +392,10 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
}
if (sp->pr_method == PR_ICON_RENDER) {
- set_preview_layer(view_layer, MA_SPHERE_A);
+ set_preview_collection(sce, view_layer, MA_SPHERE_A);
}
else {
- set_preview_layer(view_layer, mat->pr_type);
+ set_preview_collection(sce, view_layer, mat->pr_type);
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
@@ -433,7 +436,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
sp->texcopy = tex;
BLI_addtail(&pr_main->tex, tex);
}
- set_preview_layer(view_layer, MA_TEXTURE);
+ set_preview_collection(sce, view_layer, MA_TEXTURE);
if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
@@ -451,7 +454,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
BLI_addtail(&pr_main->lamp, la);
}
- set_preview_layer(view_layer, MA_LAMP);
+ set_preview_collection(sce, view_layer, MA_LAMP);
if (sce->world) {
/* Only use lighting from the lamp. */
@@ -483,7 +486,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
BLI_addtail(&pr_main->world, wrld);
}
- set_preview_layer(view_layer, MA_SKY);
+ set_preview_collection(sce, view_layer, MA_SKY);
sce->world = wrld;
if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 5353c250d1e..2a0be4eaf0d 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -776,7 +776,7 @@ static void action_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, I
}
if ((ID *)sact->ads.filter_grp == old_id) {
- sact->ads.filter_grp = (Group *)new_id;
+ sact->ads.filter_grp = (Collection *)new_id;
}
if ((ID *)sact->ads.source == old_id) {
sact->ads.source = new_id;
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 6793f0a0195..207e08c9a44 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -191,40 +191,6 @@ static int buttons_context_path_workspace(ButsContextPath *path)
return RNA_struct_is_a(ptr->type, &RNA_WorkSpace);
}
-static int buttons_context_path_collection(ButsContextPath *path, eSpaceButtons_Collection_Context collection_context)
-{
- PointerRNA *ptr = &path->ptr[path->len - 1];
-
- /* if we already have a (pinned) Collection, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_LayerCollection)) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
- ViewLayer *view_layer = ptr->data;
-
- if (collection_context == SB_COLLECTION_CTX_GROUP) {
- Object *ob = OBACT(view_layer);
- if (ob && ob->dup_group) {
- view_layer = ob->dup_group->view_layer;
-
- /* Replace the view layer by the group in the context path. */
- RNA_pointer_create(NULL, &RNA_Group, ob->dup_group, &path->ptr[path->len - 1]);
- }
- }
-
- LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
-
- if (layer_collection) {
- RNA_pointer_create(NULL, &RNA_LayerCollection, layer_collection, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- }
-
- /* no path to a collection possible */
- return 0;
-}
-
static int buttons_context_path_object(ButsContextPath *path)
{
PointerRNA *ptr = &path->ptr[path->len - 1];
@@ -562,9 +528,6 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
case BCONTEXT_WORKSPACE:
found = buttons_context_path_workspace(path);
break;
- case BCONTEXT_COLLECTION:
- found = buttons_context_path_collection(path, sbuts->collection_context);
- break;
case BCONTEXT_OBJECT:
case BCONTEXT_PHYSICS:
case BCONTEXT_CONSTRAINT:
@@ -982,10 +945,6 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
set_pointer_type(path, result, &RNA_FreestyleLineStyle);
return 1;
}
- else if (CTX_data_equals(member, "collection")) {
- set_pointer_type(path, result, &RNA_LayerCollection);
- return 1;
- }
else {
return 0; /* not found */
}
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 6ad5ed40f74..05304ecbf94 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -156,8 +156,6 @@ static void buttons_main_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, "world", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_WORKSPACE)
ED_region_panels(C, ar, "workspace", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_COLLECTION)
- ED_region_panels(C, ar, "collection", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_OBJECT)
ED_region_panels(C, ar, "object", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_DATA)
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index ff144fec778..8d3647def9e 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -755,7 +755,7 @@ static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID
if (sgraph->ads) {
if ((ID *)sgraph->ads->filter_grp == old_id) {
- sgraph->ads->filter_grp = (Group *)new_id;
+ sgraph->ads->filter_grp = (Collection *)new_id;
}
if ((ID *)sgraph->ads->source == old_id) {
sgraph->ads->source = new_id;
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index c7d4fa1465b..dfcf5fd5d8d 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -37,6 +37,7 @@
#include "DNA_meta_types.h"
#include "DNA_scene_types.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -271,36 +272,26 @@ 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)
+static void stats_dupli_object_group_count(Collection *collection, int *count)
{
- for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
- (*count)++;
- }
+ *count += BLI_listbase_count(&collection->gobject);
- 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);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ stats_dupli_object_group_count(child->collection, count);
}
}
-static void stats_dupli_object_group_doit(SceneCollection *scene_collection, SceneStats *stats, ParticleSystem *psys,
+static void stats_dupli_object_group_doit(Collection *collection, SceneStats *stats, ParticleSystem *psys,
const int totgroup, int *cur)
{
- for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
int tot = count_particles_mod(psys, totgroup, *cur);
- stats_object(link->data, 0, tot, stats);
+ stats_object(cob->ob, 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);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ stats_dupli_object_group_doit(child->collection, stats, psys, totgroup, cur);
}
}
@@ -323,9 +314,9 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
else if (part->draw_as == PART_DRAW_GR && part->dup_group) {
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);
+ Collection *collection = part->dup_group;
+ stats_dupli_object_group_count(collection, &totgroup);
+ stats_dupli_object_group_doit(collection, stats, psys, totgroup, &cur);
}
}
@@ -353,7 +344,7 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
stats->totobj += tot;
stats_object(ob, base->flag & BASE_SELECTED, tot, stats);
}
- else if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
+ else if ((ob->transflag & OB_DUPLICOLLECTION) && ob->dup_group) {
/* Dupli Group */
int tot = count_duplilist(ob);
stats->totobj += tot;
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 222fb6d8fbd..7245fd9c17f 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -571,7 +571,7 @@ static void nla_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *
if (snla->ads) {
if ((ID *)snla->ads->filter_grp == old_id) {
- snla->ads->filter_grp = (Group *)new_id;
+ snla->ads->filter_grp = (Collection *)new_id;
}
if ((ID *)snla->ads->source == old_id) {
snla->ads->source = new_id;
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 4ea2c243365..9bb3871c247 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -24,9 +24,14 @@
* \ingroup spoutliner
*/
+#include <string.h>
+
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+
#include "BKE_context.h"
#include "BKE_collection.h"
#include "BKE_layer.h"
@@ -36,9 +41,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-#include "DNA_group_types.h"
-#include "DNA_object_types.h"
-
+#include "ED_object.h"
#include "ED_screen.h"
#include "WM_api.h"
@@ -52,26 +55,44 @@
#include "outliner_intern.h" /* own include */
-/* Prototypes. */
-static int collection_delete_exec(struct bContext *C, struct wmOperator *op);
-
/* -------------------------------------------------------------------- */
-static LayerCollection *outliner_collection_active(bContext *C)
+bool outliner_is_collection_tree_element(const TreeElement *te)
{
- return CTX_data_layer_collection(C);
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (!tselem) {
+ return false;
+ }
+
+ if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
+ return true;
+ }
+ else if (tselem->type == 0 && te->idcode == ID_GR) {
+ return true;
+ }
+
+ return false;
}
-SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te)
+Collection *outliner_collection_from_tree_element(const TreeElement *te)
{
TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == TSE_SCENE_COLLECTION) {
- return te->directdata;
+ if (!tselem) {
+ return false;
}
- else if (tselem->type == TSE_LAYER_COLLECTION) {
+
+ if (tselem->type == TSE_LAYER_COLLECTION) {
LayerCollection *lc = te->directdata;
- return lc->scene_collection;
+ return lc->collection;
+ }
+ else if (ELEM(tselem->type, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
+ Scene *scene = (Scene*)tselem->id;
+ return BKE_collection_master(scene);
+ }
+ else if (tselem->type == 0 && te->idcode == ID_GR) {
+ return (Collection*)tselem->id;
}
return NULL;
@@ -83,956 +104,593 @@ SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te)
static int collections_editor_poll(bContext *C)
{
SpaceOops *so = CTX_wm_space_outliner(C);
- return (so != NULL) && (so->outlinevis == SO_COLLECTIONS);
+ return (so != NULL) && ELEM(so->outlinevis, SO_VIEW_LAYER, SO_SCENES);
}
-static int outliner_objects_collection_poll(bContext *C)
-{
- SpaceOops *so = CTX_wm_space_outliner(C);
- if (so == NULL) {
- return 0;
- }
-
- /* Groups don't support filtering. */
- if ((so->outlinevis != SO_GROUPS) && (so->filter & SO_FILTER_NO_COLLECTION)) {
- return 0;
- }
+/********************************* New Collection ****************************/
- return ELEM(so->outlinevis, SO_COLLECTIONS, SO_GROUPS);
-}
-
-/* -------------------------------------------------------------------- */
-/* collection manager operators */
-
-/**
- * Recursively get the collection for a given index
- */
-static SceneCollection *scene_collection_from_index(ListBase *lb, const int number, int *i)
+struct CollectionNewData
{
- for (SceneCollection *sc = lb->first; sc; sc = sc->next) {
- if (*i == number) {
- return sc;
- }
+ bool error;
+ Collection *collection;
+};
- (*i)++;
+static TreeTraversalAction collection_find_selected_to_add(TreeElement *te, void *customdata)
+{
+ struct CollectionNewData *data = customdata;
+ Collection *collection = outliner_collection_from_tree_element(te);
- SceneCollection *sc_nested = scene_collection_from_index(&sc->scene_collections, number, i);
- if (sc_nested) {
- return sc_nested;
- }
+ if (!collection) {
+ return TRAVERSE_SKIP_CHILDS;
}
- return NULL;
-}
-typedef struct TreeElementFindData {
- SceneCollection *collection;
- TreeElement *r_result_te;
-} TreeElementFindData;
-
-static TreeTraversalAction tree_element_find_by_scene_collection_cb(TreeElement *te, void *customdata)
-{
- TreeElementFindData *data = customdata;
- const SceneCollection *current_element_sc = outliner_scene_collection_from_tree_element(te);
-
- if (current_element_sc == data->collection) {
- data->r_result_te = te;
+ if (data->collection != NULL) {
+ data->error = true;
return TRAVERSE_BREAK;
}
+ data->collection = collection;
return TRAVERSE_CONTINUE;
}
-static TreeElement *outliner_tree_element_from_layer_collection_index(
- SpaceOops *soops, ViewLayer *view_layer,
- const int index)
+static int collection_new_exec(bContext *C, wmOperator *op)
{
- LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index);
-
- if (lc == NULL) {
- return NULL;
- }
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
- /* Find the tree element containing the LayerCollection's scene_collection. */
- TreeElementFindData data = {
- .collection = lc->scene_collection,
- .r_result_te = NULL,
+ struct CollectionNewData data = {
+ .error = false,
+ .collection = NULL,
};
- outliner_tree_traverse(soops, &soops->tree, 0, 0, tree_element_find_by_scene_collection_cb, &data);
-
- return data.r_result_te;
-}
-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->id);
- SceneCollection *sc;
+ if (RNA_boolean_get(op->ptr, "nested")) {
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
- int scene_collection_index = RNA_enum_get(op->ptr, "scene_collection");
- if (scene_collection_index == 0) {
- sc = sc_master;
- }
- else {
- int index = 1;
- sc = scene_collection_from_index(&sc_master->scene_collections, scene_collection_index, &index);
- BLI_assert(sc);
+ if (data.error) {
+ BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
+ return OPERATOR_CANCELLED;
+ }
}
- BKE_collection_link(view_layer, sc);
-
- DEG_relations_tag_update(CTX_data_main(C));
+ if (!data.collection && (soops->outlinevis == SO_VIEW_LAYER)) {
+ data.collection = BKE_collection_master(scene);
+ }
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
+ BKE_collection_add(
+ bmain,
+ data.collection,
+ NULL);
+ outliner_cleanup_tree(soops);
+ DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
-static int collection_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- 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);
- }
- else {
- return WM_enum_search_invoke(C, op, event);
- }
-}
-
-static void collection_scene_collection_itemf_recursive(
- EnumPropertyItem *tmp, EnumPropertyItem **item, int *totitem, int *value, SceneCollection *sc)
-{
- tmp->value = *value;
- tmp->icon = ICON_COLLAPSEMENU;
- tmp->identifier = sc->name;
- tmp->name = sc->name;
- RNA_enum_item_add(item, totitem, tmp);
-
- (*value)++;
-
- for (SceneCollection *ncs = sc->scene_collections.first; ncs; ncs = ncs->next) {
- collection_scene_collection_itemf_recursive(tmp, item, totitem, value, ncs);
- }
-}
-
-static const EnumPropertyItem *collection_scene_collection_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
-{
- EnumPropertyItem tmp = {0, "", 0, "", ""};
- EnumPropertyItem *item = NULL;
- int value = 0, totitem = 0;
-
- Scene *scene = CTX_data_scene(C);
- SceneCollection *sc = BKE_collection_master(&scene->id);
-
- collection_scene_collection_itemf_recursive(&tmp, &item, &totitem, &value, sc);
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
-}
-
-void OUTLINER_OT_collection_link(wmOperatorType *ot)
+void OUTLINER_OT_collection_new(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
- ot->name = "Link Collection";
- ot->idname = "OUTLINER_OT_collection_link";
- ot->description = "Link a new collection to the active layer";
+ ot->name = "New Collection";
+ ot->idname = "OUTLINER_OT_collection_new";
+ ot->description = "Add a new collection inside selected collection";
/* api callbacks */
- ot->exec = collection_link_exec;
- ot->invoke = collection_link_invoke;
+ ot->exec = collection_new_exec;
+ ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_enum(ot->srna, "scene_collection", DummyRNA_NULL_items, 0, "Scene Collection", "");
- RNA_def_enum_funcs(prop, collection_scene_collection_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "nested", true, "Nested", "Add as child of selected collection");;
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/**
- * Returns true if selected element is a collection directly
- * linked to the active ViewLayer (not a nested collection)
- */
-static int collection_unlink_poll(bContext *C)
+/**************************** Delete Collection ******************************/
+
+struct CollectionEditData {
+ Scene *scene;
+ SpaceOops *soops;
+ GSet *collections_to_edit;
+};
+
+static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *customdata)
{
- if (collections_editor_poll(C) == 0) {
- return 0;
- }
+ struct CollectionEditData *data = customdata;
+ Collection *collection = outliner_collection_from_tree_element(te);
- LayerCollection *lc = outliner_collection_active(C);
+ if (!collection) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
- if (lc == NULL) {
- return 0;
+ if (collection == BKE_collection_master(data->scene)) {
+ /* skip - showing warning/error message might be missleading
+ * when deleting multiple collections, so just do nothing */
+ }
+ else {
+ /* Delete, duplicate and link don't edit children, those will come along
+ * with the parents. */
+ BLI_gset_add(data->collections_to_edit, collection);
+ return TRAVERSE_SKIP_CHILDS;
}
- ViewLayer *view_layer = CTX_data_view_layer(C);
- return BLI_findindex(&view_layer->layer_collections, lc) != -1 ? 1 : 0;
+ return TRAVERSE_CONTINUE;
}
-static int collection_unlink_exec(bContext *C, wmOperator *op)
+static int collection_delete_exec(bContext *C, wmOperator *op)
{
- LayerCollection *lc = outliner_collection_active(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ bool hierarchy = RNA_boolean_get(op->ptr, "hierarchy");
- if (lc == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Active element is not a collection");
- return OPERATOR_CANCELLED;
- }
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- BKE_collection_unlink(view_layer, lc);
+ /* We first walk over and find the Collections we actually want to delete (ignoring duplicates). */
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
- if (soops) {
- outliner_cleanup_tree(soops);
+ /* Effectively delete the collections. */
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ /* TODO: what if collection was child and got deleted in the meantime? */
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ BKE_collection_delete(bmain, collection, hierarchy);
}
- DEG_relations_tag_update(CTX_data_main(C));
+ BLI_gset_free(data.collections_to_edit, NULL);
+
+ DEG_relations_tag_update(bmain);
/* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&CTX_data_scene(C)->id, 0);
+ DEG_id_tag_update(&scene->id, 0);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_unlink(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Unlink Collection";
- ot->idname = "OUTLINER_OT_collection_unlink";
- ot->description = "Unlink collection from the active layer";
-
- /* api callbacks */
- ot->exec = collection_unlink_exec;
- ot->poll = collection_unlink_poll;
-
- /* flags */
- 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_parent = BKE_collection_master(&scene->id);
- SceneCollection *scene_collection = BKE_collection_add(&scene->id, scene_collection_parent, COLLECTION_TYPE_NONE, NULL);
- BKE_collection_link(view_layer, scene_collection);
-
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_new(wmOperatorType *ot)
+void OUTLINER_OT_collection_delete(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "New Collection";
- ot->idname = "OUTLINER_OT_collection_new";
- ot->description = "Add a new collection to the scene";
+ ot->name = "Delete Collection";
+ ot->idname = "OUTLINER_OT_collection_delete";
+ ot->description = "Delete selected collections";
/* api callbacks */
- ot->exec = collection_new_exec;
+ ot->exec = collection_delete_exec;
+ ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/**********************************************************************************/
-/* Add new nested collection. */
+/****************************** Select Objects *******************************/
-struct CollectionNewData
-{
+struct CollectionObjectsSelectData {
bool error;
- SceneCollection *scene_collection;
+ LayerCollection *layer_collection;
};
-static TreeTraversalAction collection_find_selected_to_add(TreeElement *te, void *customdata)
+static TreeTraversalAction outliner_find_first_selected_layer_collection(TreeElement *te, void *customdata)
{
- struct CollectionNewData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
-
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
- }
+ struct CollectionObjectsSelectData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (data->scene_collection != NULL) {
- data->error = true;
- return TRAVERSE_BREAK;
+ switch (tselem->type) {
+ case TSE_LAYER_COLLECTION:
+ data->layer_collection = te->directdata;
+ return TRAVERSE_BREAK;
+ case TSE_R_LAYER:
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
+ return TRAVERSE_CONTINUE;
+ default:
+ return TRAVERSE_SKIP_CHILDS;
}
-
- data->scene_collection = scene_collection;
- return TRAVERSE_CONTINUE;
}
-static int collection_nested_new_exec(bContext *C, wmOperator *op)
+static LayerCollection *outliner_active_layer_collection(bContext *C)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- struct CollectionNewData data = {
- .error = false,
- .scene_collection = NULL,
+ struct CollectionObjectsSelectData data = {
+ .layer_collection = NULL,
};
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_layer_collection, &data);
+ return data.layer_collection;
+}
+
+static int collection_objects_select_exec(bContext *C, wmOperator *op)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *layer_collection = outliner_active_layer_collection(C);
+ bool deselect = STREQ(op->idname, "OUTLINER_OT_collection_objects_deselect");
- if (data.error) {
- BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
+ if (layer_collection == NULL) {
return OPERATOR_CANCELLED;
}
- BKE_collection_add(
- &scene->id,
- data.scene_collection,
- COLLECTION_TYPE_NONE,
- NULL);
+ BKE_layer_collection_objects_select(view_layer, layer_collection, deselect);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
- outliner_cleanup_tree(soops);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_nested_new(wmOperatorType *ot)
+void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "New Nested Collection";
- ot->idname = "OUTLINER_OT_collection_nested_new";
- ot->description = "Add a new collection inside selected collection";
+ ot->name = "Select Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_select";
+ ot->description = "Select objects in collection";
/* api callbacks */
- ot->exec = collection_nested_new_exec;
+ ot->exec = collection_objects_select_exec;
ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/**********************************************************************************/
-/* Delete selected collection. */
-
-void OUTLINER_OT_collection_delete_selected(wmOperatorType *ot)
+void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Delete Selected Collections";
- ot->idname = "OUTLINER_OT_collection_delete_selected";
- ot->description = "Delete all the selected collections";
+ ot->name = "Deselect Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_deselect";
+ ot->description = "Deselect objects in collection";
/* api callbacks */
- ot->exec = collection_delete_exec;
+ ot->exec = collection_objects_select_exec;
ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/**********************************************************************************/
-/* Add new selected objects. */
+/************************** Duplicate Collection *****************************/
-struct SceneCollectionSelectedData {
- ListBase scene_collections_array;
+struct CollectionDuplicateData {
+ TreeElement *te;
};
-static TreeTraversalAction collection_find_selected_scene_collections(TreeElement *te, void *customdata)
+static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *te, void *customdata)
{
- struct SceneCollectionSelectedData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
+ struct CollectionDuplicateData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
+ switch (tselem->type) {
+ case TSE_LAYER_COLLECTION:
+ data->te = te;
+ return TRAVERSE_BREAK;
+ case TSE_R_LAYER:
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
+ default:
+ return TRAVERSE_CONTINUE;
}
-
- BLI_addtail(&data->scene_collections_array, BLI_genericNodeN(scene_collection));
- return TRAVERSE_CONTINUE;
}
-static int collection_objects_add_exec(bContext *C, wmOperator *op)
+static TreeElement *outliner_active_collection(bContext *C)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- struct SceneCollectionSelectedData data = {
- .scene_collections_array = {NULL, NULL},
+ struct CollectionDuplicateData data = {
+ .te = NULL,
};
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_scene_collections, &data);
-
- if (BLI_listbase_is_empty(&data.scene_collections_array)) {
- BKE_report(op->reports, RPT_ERROR, "No collection is selected");
- return OPERATOR_CANCELLED;
- }
-
- CTX_DATA_BEGIN (C, struct Object *, ob, selected_objects)
- {
- LISTBASE_FOREACH (LinkData *, link, &data.scene_collections_array) {
- SceneCollection *scene_collection = link->data;
- BKE_collection_object_add(
- &scene->id,
- scene_collection,
- ob);
- }
- }
- CTX_DATA_END;
- BLI_freelistN(&data.scene_collections_array);
-
- outliner_cleanup_tree(soops);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_objects_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Objects";
- ot->idname = "OUTLINER_OT_collection_objects_add";
- ot->description = "Add selected objects to collection";
-
- /* api callbacks */
- ot->exec = collection_objects_add_exec;
- ot->poll = collections_editor_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_collection, &data);
+ return data.te;
}
-/**********************************************************************************/
-/* Remove selected objects. */
-
-
-static int collection_objects_remove_exec(bContext *C, wmOperator *op)
+static int collection_duplicate_exec(bContext *C, wmOperator *op)
{
- SpaceOops *soops = CTX_wm_space_outliner(C);
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
-
- struct SceneCollectionSelectedData data = {
- .scene_collections_array = {NULL, NULL},
- };
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te = outliner_active_collection(C);
+ BLI_assert(te != NULL);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_scene_collections, &data);
+ Collection *collection = outliner_collection_from_tree_element(te);
+ Collection *parent = (te->parent) ? outliner_collection_from_tree_element(te->parent) : NULL;
- if (BLI_listbase_is_empty(&data.scene_collections_array)) {
- BKE_report(op->reports, RPT_ERROR, "No collection is selected");
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ BKE_report(op->reports, RPT_ERROR, "Can't duplicate the master collection");
return OPERATOR_CANCELLED;
}
- CTX_DATA_BEGIN (C, struct Object *, ob, selected_objects)
- {
- LISTBASE_FOREACH (LinkData *, link, &data.scene_collections_array) {
- SceneCollection *scene_collection = link->data;
- BKE_collection_object_remove(
- bmain,
- &scene->id,
- scene_collection,
- ob,
- true);
- }
+ switch (soops->outlinevis) {
+ case SO_SCENES:
+ case SO_VIEW_LAYER:
+ case SO_LIBRARIES:
+ BKE_collection_copy(bmain, parent, collection);
+ break;
}
- CTX_DATA_END;
- BLI_freelistN(&data.scene_collections_array);
- outliner_cleanup_tree(soops);
DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));
+
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_objects_remove(wmOperatorType *ot)
+void OUTLINER_OT_collection_duplicate(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Objects";
- ot->idname = "OUTLINER_OT_collection_objects_remove";
- ot->description = "Remove selected objects from collection";
+ ot->name = "Duplicate Collection";
+ ot->idname = "OUTLINER_OT_collection_duplicate";
+ ot->description = "Duplicate selected collections";
/* api callbacks */
- ot->exec = collection_objects_remove_exec;
+ ot->exec = collection_duplicate_exec;
ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static TreeElement *outliner_collection_parent_element_get(TreeElement *te)
-{
- TreeElement *te_parent = te;
- while ((te_parent = te_parent->parent)) {
- if (outliner_scene_collection_from_tree_element(te->parent)) {
- return te_parent;
- }
- }
- return NULL;
-}
+/**************************** Link Collection ******************************/
-static int object_collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_link_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceOops *soops = CTX_wm_space_outliner(C);
Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Collection *active_collection = CTX_data_layer_collection(C)->collection;
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
- struct ObjectsSelectedData data = {
- .objects_selected_array = {NULL, NULL},
- };
-
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
- TreeElement *te = (TreeElement *)link->data;
- Object *ob = (Object *)TREESTORE(te)->id;
- SceneCollection *scene_collection = NULL;
+ /* We first walk over and find the Collections we actually want to link (ignoring duplicates). */
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
- TreeElement *te_parent = outliner_collection_parent_element_get(te);
- if (te_parent != NULL) {
- scene_collection = outliner_scene_collection_from_tree_element(te_parent);
- ID *owner_id = TREESTORE(te_parent)->id;
- BKE_collection_object_remove(bmain, owner_id, scene_collection, ob, true);
- DEG_id_tag_update(owner_id, DEG_TAG_BASE_FLAGS_UPDATE);
- }
+ /* Effectively link the collections. */
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ BKE_collection_child_add(bmain, active_collection, collection);
+ id_fake_user_clear(&collection->id);
}
- BLI_freelistN(&data.objects_selected_array);
+ BLI_gset_free(data.collections_to_edit, NULL);
- outliner_cleanup_tree(soops);
DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, NULL);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, NULL);
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_object_remove_from_collection(wmOperatorType *ot)
+void OUTLINER_OT_collection_link(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Object from Collection";
- ot->idname = "OUTLINER_OT_object_remove_from_collection";
- ot->description = "Remove selected objects from their respective collection";
+ ot->name = "Link Collection";
+ ot->idname = "OUTLINER_OT_collection_link";
+ ot->description = "Link selected collections to active scene";
/* api callbacks */
- ot->exec = object_collection_remove_exec;
- ot->poll = outliner_objects_collection_poll;
+ ot->exec = collection_link_exec;
+ ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int object_add_to_new_collection_exec(bContext *C, wmOperator *op)
-{
- int operator_result = OPERATOR_CANCELLED;
+/************************** Instance Collection ******************************/
- SpaceOops *soops = CTX_wm_space_outliner(C);
+static int collection_instance_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);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
- SceneCollection *scene_collection_parent, *scene_collection_new;
- TreeElement *te_active, *te_parent;
-
- struct ObjectsSelectedData data = {{NULL}}, active = {{NULL}};
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_HIGHLIGHTED, outliner_find_selected_objects, &active);
- if (BLI_listbase_is_empty(&active.objects_selected_array)) {
- BKE_report(op->reports, RPT_ERROR, "No object is selected");
- goto cleanup;
- }
+ /* We first walk over and find the Collections we actually want to instance (ignoring duplicates). */
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
- if (BLI_listbase_is_empty(&data.objects_selected_array)) {
- BKE_report(op->reports, RPT_ERROR, "No objects are selected");
- goto cleanup;
- }
+ /* Find an active collection to add to, that doesn't give dependency cycles. */
+ LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
- /* Heuristic to get the "active" / "last object" */
- te_active = ((LinkData *)active.objects_selected_array.first)->data;
- te_parent = outliner_collection_parent_element_get(te_active);
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- if (te_parent == NULL) {
- BKE_reportf(op->reports, RPT_ERROR, "Couldn't find collection of \"%s\" object", te_active->name);
- goto cleanup;
+ while (BKE_collection_find_cycle(active_lc->collection, collection)) {
+ active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
+ }
}
- ID *owner_id = TREESTORE(te_parent)->id;
- scene_collection_parent = outliner_scene_collection_from_tree_element(te_parent);
- scene_collection_new = BKE_collection_add(owner_id, scene_collection_parent, scene_collection_parent->type, NULL);
-
- LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
- TreeElement *te = (TreeElement *)link->data;
- Object *ob = (Object *)TREESTORE(te)->id;
- BKE_collection_object_add(owner_id, scene_collection_new, ob);
+ /* Effectively instance the collections. */
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ Object *ob = ED_object_add_type(C, OB_EMPTY, collection->id.name + 2, scene->cursor.location, NULL, false, scene->layact);
+ ob->dup_group = collection;
+ ob->transflag |= OB_DUPLICOLLECTION;
+ id_lib_extern(&collection->id);
}
- outliner_cleanup_tree(soops);
+ BLI_gset_free(data.collections_to_edit, NULL);
+
DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- operator_result = OPERATOR_FINISHED;
-cleanup:
- BLI_freelistN(&active.objects_selected_array);
- BLI_freelistN(&data.objects_selected_array);
- return operator_result;
+ return OPERATOR_FINISHED;
}
-void OUTLINER_OT_object_add_to_new_collection(wmOperatorType *ot)
+void OUTLINER_OT_collection_instance(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add Objects to New Collection";
- ot->idname = "OUTLINER_OT_object_add_to_new_collection";
- ot->description = "Add objects to a new collection";
+ ot->name = "Instance Collection";
+ ot->idname = "OUTLINER_OT_collection_instance";
+ ot->description = "Instance selected collections to active scene";
/* api callbacks */
- ot->exec = object_add_to_new_collection_exec;
- ot->poll = outliner_objects_collection_poll;
+ ot->exec = collection_instance_exec;
+ ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-struct CollectionDeleteData {
- Scene *scene;
- SpaceOops *soops;
- GSet *collections_to_delete;
-};
+/************************** Exclude Collection ******************************/
-static TreeTraversalAction collection_find_data_to_delete(TreeElement *te, void *customdata)
+static TreeTraversalAction layer_collection_find_data_to_edit(TreeElement *te, void *customdata)
{
- struct CollectionDeleteData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
+ struct CollectionEditData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
+ if (!(tselem && tselem->type == TSE_LAYER_COLLECTION)) {
+ return TRAVERSE_CONTINUE;
}
- if (scene_collection == BKE_collection_master(&data->scene->id)) {
+ LayerCollection *lc = te->directdata;
+
+ if (lc->collection->flag & COLLECTION_IS_MASTER) {
/* skip - showing warning/error message might be missleading
* when deleting multiple collections, so just do nothing */
}
else {
- BLI_gset_add(data->collections_to_delete, scene_collection);
- return TRAVERSE_SKIP_CHILDS; /* Childs will be gone anyway, no need to recurse deeper. */
+ /* Delete, duplicate and link don't edit children, those will come along
+ * with the parents. */
+ BLI_gset_add(data->collections_to_edit, lc);
}
return TRAVERSE_CONTINUE;
}
-static TreeTraversalAction collection_delete_elements_from_collection(TreeElement *te, void *customdata)
+static int collections_view_layer_poll(bContext *C, bool include)
{
- struct CollectionDeleteData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
-
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
- }
-
- const bool will_be_deleted = BLI_gset_haskey(data->collections_to_delete, scene_collection);
- if (will_be_deleted) {
- outliner_free_tree_element(te, te->parent ? &te->parent->subtree : &data->soops->tree);
- /* Childs are freed now, so don't recurse into them. */
- return TRAVERSE_SKIP_CHILDS;
+ /* Poll function so the right click menu show current state of selected collections. */
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ if (!(soops && soops->outlinevis == SO_VIEW_LAYER)) {
+ return false;
}
- return TRAVERSE_CONTINUE;
-}
-
-static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
-{
Scene *scene = CTX_data_scene(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- struct CollectionDeleteData data = {.scene = scene, .soops = soops};
-
- data.collections_to_delete = BLI_gset_ptr_new(__func__);
-
- /* We first walk over and find the SceneCollections we actually want to delete (ignoring duplicates). */
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_delete, &data);
-
- /* Now, delete all tree elements representing a collection that will be deleted. We'll look for a
- * new element to select in a few lines, so we can't wait until the tree is recreated on redraw. */
- outliner_tree_traverse(soops, &soops->tree, 0, 0, collection_delete_elements_from_collection, &data);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
+ bool result = false;
- /* Effectively delete the collections. */
- GSetIterator collections_to_delete_iter;
- GSET_ITER(collections_to_delete_iter, data.collections_to_delete) {
- SceneCollection *sc = BLI_gsetIterator_getKey(&collections_to_delete_iter);
- BKE_collection_remove(&data.scene->id, sc);
- }
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
- BLI_gset_free(data.collections_to_delete, NULL);
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- TreeElement *select_te = outliner_tree_element_from_layer_collection_index(soops, CTX_data_view_layer(C), 0);
- if (select_te) {
- outliner_item_select(soops, select_te, false, false);
+ if (include && (lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ result = true;
+ }
+ else if (!include && !(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ result = true;
+ }
}
- DEG_relations_tag_update(CTX_data_main(C));
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-
- return OPERATOR_FINISHED;
+ BLI_gset_free(data.collections_to_edit, NULL);
+ return result;
}
-void OUTLINER_OT_collections_delete(wmOperatorType *ot)
+static int collections_exclude_poll(bContext *C)
{
- /* identifiers */
- ot->name = "Delete";
- ot->idname = "OUTLINER_OT_collections_delete";
- ot->description = "Delete selected overrides or collections";
-
- /* api callbacks */
- ot->exec = collection_delete_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ return collections_view_layer_poll(C, false);
}
-static int collection_select_exec(bContext *C, wmOperator *op)
+static int collections_include_poll(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const int collection_index = RNA_int_get(op->ptr, "collection_index");
- view_layer->active_collection = collection_index;
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select";
- ot->idname = "OUTLINER_OT_collection_select";
- ot->description = "Change active collection or override";
-
- /* api callbacks */
- ot->exec = collection_select_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "collection_index", 0, 0, INT_MAX, "Index",
- "Index of collection to select", 0, INT_MAX);
+ return collections_view_layer_poll(C, true);
}
-#define ACTION_DISABLE 0
-#define ACTION_ENABLE 1
-#define ACTION_TOGGLE 2
-
-static int collection_toggle_exec(bContext *C, wmOperator *op)
+static void layer_collection_exclude_recursive_set(LayerCollection *lc)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int action = RNA_enum_get(op->ptr, "action");
- LayerCollection *layer_collection = CTX_data_layer_collection(C);
-
- if (layer_collection->flag & COLLECTION_DISABLED) {
- if (ELEM(action, ACTION_TOGGLE, ACTION_ENABLE)) {
- layer_collection->flag &= ~COLLECTION_DISABLED;
- }
- else { /* ACTION_DISABLE */
- BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already disabled",
- layer_collection->scene_collection->name);
- return OPERATOR_CANCELLED;
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ nlc->flag |= LAYER_COLLECTION_EXCLUDE;
}
- }
- else {
- if (ELEM(action, ACTION_TOGGLE, ACTION_DISABLE)) {
- layer_collection->flag |= COLLECTION_DISABLED;
- }
- else { /* ACTION_ENABLE */
- BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already enabled",
- layer_collection->scene_collection->name);
- return OPERATOR_CANCELLED;
+ else {
+ nlc->flag &= ~LAYER_COLLECTION_EXCLUDE;
}
- }
-
- DEG_relations_tag_update(bmain);
- /* 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);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
- return OPERATOR_FINISHED;
+ layer_collection_exclude_recursive_set(nlc);
+ }
}
-void OUTLINER_OT_collection_toggle(wmOperatorType *ot)
+static int collection_view_layer_exec(bContext *C, wmOperator *op)
{
- PropertyRNA *prop;
-
- static EnumPropertyItem actions_items[] = {
- {ACTION_DISABLE, "DISABLE", 0, "Disable", "Disable selected markers"},
- {ACTION_ENABLE, "ENABLE", 0, "Enable", "Enable selected markers"},
- {ACTION_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "Toggle Collection";
- ot->idname = "OUTLINER_OT_collection_toggle";
- ot->description = "Deselect collection objects";
-
- /* api callbacks */
- ot->exec = collection_toggle_exec;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ bool include = STREQ(op->idname, "OUTLINER_OT_collection_include_set");
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- /* properties */
- prop = RNA_def_int(ot->srna, "collection_index", -1, -1, INT_MAX, "Collection Index", "Index of collection to toggle", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_enum(ot->srna, "action", actions_items, ACTION_TOGGLE, "Action", "Selection action to execute");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-}
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
-#undef ACTION_TOGGLE
-#undef ACTION_ENABLE
-#undef ACTION_DISABLE
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
-struct CollectionObjectsSelectData {
- bool error;
- LayerCollection *layer_collection;
-};
+ if (!(lc->collection->flag & COLLECTION_IS_MASTER)) {
+ if (include) {
+ lc->flag &= ~LAYER_COLLECTION_EXCLUDE;
+ }
+ else {
+ lc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
-static TreeTraversalAction outliner_find_first_selected_layer_collection(TreeElement *te, void *customdata)
-{
- struct CollectionObjectsSelectData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
-
- switch (tselem->type) {
- case TSE_LAYER_COLLECTION:
- data->layer_collection = te->directdata;
- return TRAVERSE_BREAK;
- case TSE_LAYER_COLLECTION_BASE:
- return TRAVERSE_CONTINUE;
- default:
- return TRAVERSE_SKIP_CHILDS;
+ layer_collection_exclude_recursive_set(lc);
+ }
}
-}
-
-static LayerCollection *outliner_active_layer_collection(bContext *C)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- struct CollectionObjectsSelectData data = {
- .layer_collection = NULL,
- };
-
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_layer_collection, &data);
- return data.layer_collection;
-}
+ BLI_gset_free(data.collections_to_edit, NULL);
-static int collection_objects_select_exec(bContext *C, wmOperator *UNUSED(op))
-{
- LayerCollection *layer_collection = outliner_active_layer_collection(C);
-
- if (layer_collection == NULL) {
- return OPERATOR_CANCELLED;
- }
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_relations_tag_update(bmain);
- BKE_layer_collection_objects_select(layer_collection);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
+void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Objects";
- ot->idname = "OUTLINER_OT_collection_objects_select";
- ot->description = "Select all the collection objects";
+ ot->name = "Exclude from View Layer";
+ ot->idname = "OUTLINER_OT_collection_exclude_set";
+ ot->description = "Exclude collection from the active view layer";
/* api callbacks */
- ot->exec = collection_objects_select_exec;
- ot->poll = collections_editor_poll;
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_exclude_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-struct CollectionDuplicateData {
- TreeElement *te;
-};
-
-static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *te, void *customdata)
-{
- struct CollectionDuplicateData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
-
- switch (tselem->type) {
- case TSE_LAYER_COLLECTION:
- case TSE_SCENE_COLLECTION:
- data->te = te;
- return TRAVERSE_BREAK;
- case TSE_LAYER_COLLECTION_BASE:
- default:
- return TRAVERSE_CONTINUE;
- }
-}
-
-static TreeElement *outliner_active_collection(bContext *C)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
-
- struct CollectionDuplicateData data = {
- .te = NULL,
- };
-
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_collection, &data);
- return data.te;
-}
-
-static int collection_duplicate_exec(bContext *C, wmOperator *op)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- TreeElement *te = outliner_active_collection(C);
-
- BLI_assert(te != NULL);
- if (BKE_collection_master(TREESTORE(te)->id) == outliner_scene_collection_from_tree_element(te)) {
- BKE_report(op->reports, RPT_ERROR, "You can't duplicate the master collection");
- return OPERATOR_CANCELLED;
- }
-
- switch (soops->outlinevis) {
- case SO_SCENES:
- BKE_collection_duplicate(TREESTORE(te)->id, (SceneCollection *)te->directdata);
- break;
- case SO_COLLECTIONS:
- case SO_GROUPS:
- BKE_layer_collection_duplicate(TREESTORE(te)->id, (LayerCollection *)te->directdata);
- break;
- }
-
- DEG_relations_tag_update(CTX_data_main(C));
- WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_duplicate(wmOperatorType *ot)
+void OUTLINER_OT_collection_include_set(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Duplicate Collection";
- ot->idname = "OUTLINER_OT_collection_duplicate";
- ot->description = "Duplicate collection";
+ ot->name = "Include in View Layer";
+ ot->idname = "OUTLINER_OT_collection_include_set";
+ ot->description = "Include collection in the active view layer";
/* api callbacks */
- ot->exec = collection_duplicate_exec;
- ot->poll = collections_editor_poll;
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_include_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index d3e70da80c8..90b137bcd7d 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -248,19 +248,6 @@ static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), voi
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
-static void restrictbutton_collection_flag_cb(bContext *C, void *poin, void *UNUSED(poin2))
-{
- ID *id = (ID *)poin;
-
- /* TODO(sergey): Use proper flag for tagging here. */
- 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);
-}
-
static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2))
{
ID *id = (ID *)poin;
@@ -275,9 +262,9 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void
}
}
-
static void namebutton_cb(bContext *C, void *tsep, char *oldname)
{
+ Main *bmain = CTX_data_main(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -289,7 +276,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
TreeElement *te = outliner_find_tree_element(&soops->tree, tselem);
if (tselem->type == 0) {
- BLI_libblock_ensure_unique_name(G.main, tselem->id->name);
+ BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
switch (GS(tselem->id->name)) {
case ID_MA:
@@ -311,7 +298,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
BKE_library_filepath_set(lib, lib->name);
BLI_strncpy(expanded, lib->name, sizeof(expanded));
- BLI_path_abs(expanded, G.main->name);
+ BLI_path_abs(expanded, bmain->name);
if (!BLI_exists(expanded)) {
BKE_reportf(CTX_wm_reports(C), RPT_ERROR,
"Library path '%s' does not exist, correct this before saving", expanded);
@@ -329,7 +316,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
defgroup_unique_name(te->directdata, (Object *)tselem->id); // id = object
break;
case TSE_NLA_ACTION:
- BLI_libblock_ensure_unique_name(G.main, tselem->id->name);
+ BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
break;
case TSE_EBONE:
{
@@ -404,14 +391,10 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, gpd);
break;
}
- case TSE_R_LAYER:
- break;
- case TSE_SCENE_COLLECTION:
case TSE_LAYER_COLLECTION:
{
- SceneCollection *sc = outliner_scene_collection_from_tree_element(te);
- BKE_collection_rename(tselem->id, sc, te->name);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
+ WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break;
break;
}
}
@@ -427,16 +410,16 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
TreeStoreElem *tselem;
Object *ob = NULL;
-#if 0
- PropertyRNA *object_prop_hide, *object_prop_hide_select, *object_prop_hide_render;
-
- /* get RNA properties (once) */
- object_prop_hide = RNA_struct_type_find_property(&RNA_Object, "hide");
- object_prop_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select");
- object_prop_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render");
- BLI_assert(object_prop_hide && object_prop_hide_select && object_prop_hide_render);
-#endif
-
+ /* get RNA properties (once for speed) */
+ PropertyRNA *collection_prop_hide_viewport;
+ PropertyRNA *collection_prop_hide_select;
+ PropertyRNA *collection_prop_hide_render;
+ collection_prop_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
+ collection_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, "hide_viewport");
+ collection_prop_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
+ BLI_assert(collection_prop_hide_viewport &&
+ collection_prop_hide_select &&
+ collection_prop_hide_render);
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
@@ -540,46 +523,33 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
UI_block_emboss_set(block, UI_EMBOSS);
}
- else if (tselem->type == TSE_LAYER_COLLECTION) {
- LayerCollection *collection = te->directdata;
-
- const bool is_enabled = (collection->flag & COLLECTION_DISABLED) == 0;
+ else if (outliner_is_collection_tree_element(te)) {
+ LayerCollection *lc = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata : NULL;
+ Collection *collection = outliner_collection_from_tree_element(te);
UI_block_emboss_set(block, UI_EMBOSS_NONE);
- 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);
- }
- else if ((soops->outlinevis == SO_GROUPS) &&
- (collection->scene_collection->type == COLLECTION_TYPE_GROUP_INTERNAL))
+ if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) &&
+ !(collection->flag & COLLECTION_IS_MASTER))
{
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_VIEWPORT, 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 selection of objects in the collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, tselem->id, collection);
+ PointerRNA collection_ptr;
+ RNA_id_pointer_create(&collection->id, &collection_ptr);
+
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_viewport, -1, 0, 0, 0, 0, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_RENDER, 0, ICON_RESTRICT_RENDER_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, tselem->id, collection);
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_render, -1, 0, 0, 0, 0, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- bt = uiDefIconButBitS(block, UI_BTYPE_BUT_TOGGLE, COLLECTION_DISABLED, 0,
- is_enabled ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
- TIP_("Enable/Disable collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, tselem->id, collection);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_select, -1, 0, 0, 0, 0, NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
UI_block_emboss_set(block, UI_EMBOSS);
}
@@ -1090,8 +1060,9 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
}
break;
case TSE_LAYER_COLLECTION:
- case TSE_SCENE_COLLECTION:
- ICON_DRAW(ICON_COLLAPSEMENU);
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
+ ICON_DRAW(ICON_GROUP);
break;
/* Removed the icons from outliner. Need a better structure with Layers, Palettes and Colors */
#if 0
@@ -1131,7 +1102,13 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
case OB_LIGHTPROBE:
tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LIGHTPROBE); break;
case OB_EMPTY:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break;
+ if (ob->dup_group) {
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_GROUP_INSTANCE);
+ }
+ else {
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY);
+ }
+ break;
}
}
else {
@@ -1339,7 +1316,7 @@ static void outliner_draw_tree_element(
tselem = TREESTORE(te);
if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
- const float alpha_fac = draw_grayed_out ? 0.5f : 1.0f;
+ const float alpha_fac = ((te->flag & TE_DISABLED) || draw_grayed_out) ? 0.5f : 1.0f;
const float alpha = 0.5f * alpha_fac;
int xmax = ar->v2d.cur.xmax;
@@ -1422,8 +1399,8 @@ static void outliner_draw_tree_element(
te->flag |= TE_ACTIVE; // for lookup in display hierarchies
}
- if ((soops->outlinevis == SO_COLLECTIONS) && (tselem->type == TSE_R_LAYER)) {
- /* View layer in collections can't expand/collapse. */
+ if (tselem->type == TSE_VIEW_COLLECTION_BASE) {
+ /* Scene collection in view layer can't expand/collapse. */
}
else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
/* open/close icon, only when sublevels, except for scene */
@@ -1448,7 +1425,7 @@ static void outliner_draw_tree_element(
else
offsx += 2 * ufac;
- if (tselem->type == 0 && ID_IS_LINKED(tselem->id)) {
+ if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_LINKED(tselem->id)) {
if (tselem->id->tag & LIB_TAG_MISSING) {
UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN,
alpha_fac);
@@ -1463,7 +1440,7 @@ static void outliner_draw_tree_element(
}
offsx += UI_UNIT_X + 2 * ufac;
}
- else if (tselem->type == 0 && ID_IS_STATIC_OVERRIDE(tselem->id)) {
+ else if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_STATIC_OVERRIDE(tselem->id)) {
UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_OVERRIDE,
alpha_fac);
offsx += UI_UNIT_X + 2 * ufac;
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 5187de00cff..5922e208f36 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -50,6 +50,7 @@
#include "BLT_translation.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_idcode.h"
#include "BKE_layer.h"
@@ -61,7 +62,6 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_material.h"
-#include "BKE_group.h"
#include "DEG_depsgraph_build.h"
@@ -254,7 +254,7 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
/* Rename --------------------------------------------------- */
-static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
+static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
ReportList *reports)
{
bool add_textbut = false;
@@ -264,19 +264,18 @@ static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, Tre
/* do nothing */;
}
else if (ELEM(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE,
- TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE))
+ TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_SCENE_COLLECTION_BASE,
+ TSE_VIEW_COLLECTION_BASE))
{
BKE_report(reports, RPT_WARNING, "Cannot edit builtin name");
}
else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
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->id);
+ else if (outliner_is_collection_tree_element(te)) {
+ Collection *collection = outliner_collection_from_tree_element(te);
- if ((tselem->type == TSE_SCENE_COLLECTION && te->directdata == master) ||
- (((LayerCollection *)te->directdata)->scene_collection == master))
- {
+ if (collection->flag & COLLECTION_IS_MASTER) {
BKE_report(reports, RPT_WARNING, "Cannot edit name of master collection");
}
else {
@@ -300,14 +299,14 @@ static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, Tre
}
void item_rename_cb(
- bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
+ bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *te,
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
ARegion *ar = CTX_wm_region(C);
- do_item_rename(scene, ar, te, tselem, reports);
+ do_item_rename(ar, te, tselem, reports);
}
-static int do_outliner_item_rename(const Scene *scene, ReportList *reports, ARegion *ar, TreeElement *te,
+static int do_outliner_item_rename(ReportList *reports, ARegion *ar, TreeElement *te,
const float mval[2])
{
if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
@@ -315,14 +314,14 @@ static int do_outliner_item_rename(const Scene *scene, ReportList *reports, AReg
/* click on name */
if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) {
- do_item_rename(scene, ar, te, tselem, reports);
+ do_item_rename(ar, te, tselem, reports);
return 1;
}
return 0;
}
for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_rename(scene, reports, ar, te, mval)) return 1;
+ if (do_outliner_item_rename(reports, ar, te, mval)) return 1;
}
return 0;
}
@@ -338,7 +337,7 @@ static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *even
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_rename(CTX_data_scene(C), op->reports, ar, te, fmval)) {
+ if (do_outliner_item_rename(op->reports, ar, te, fmval)) {
changed = true;
break;
}
@@ -1915,7 +1914,6 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Main *bmain = CTX_data_main(C);
Scene *scene = NULL;
TreeElement *te = NULL;
- TreeStoreElem *tselem;
char childname[MAX_ID_NAME];
char parname[MAX_ID_NAME];
int partype = 0;
@@ -1925,21 +1923,8 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* Find object hovered over */
te = outliner_dropzone_find(soops, fmval, true);
- tselem = te ? TREESTORE(te) : NULL;
-
- if (tselem && ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
- SceneCollection *sc = outliner_scene_collection_from_tree_element(te);
-
- scene = BKE_scene_find_from_collection(bmain, sc);
- BLI_assert(scene);
- RNA_string_get(op->ptr, "child", childname);
- ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
- BKE_collection_object_add(&scene->id, sc, ob);
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else if (te) {
+ if (te) {
RNA_string_set(op->ptr, "parent", te->name);
/* Identify parent and child */
RNA_string_get(op->ptr, "child", childname);
@@ -2082,9 +2067,10 @@ static int outliner_parenting_poll(bContext *C)
if (soops->outlinevis == SO_SCENES) {
return true;
}
-
- if (soops->outlinevis == SO_COLLECTIONS) {
- return (soops->filter & SO_FILTER_NO_COLLECTION);
+ else if ((soops->outlinevis == SO_VIEW_LAYER) &&
+ (soops->filter & SO_FILTER_NO_COLLECTION))
+ {
+ return true;
}
}
@@ -2163,16 +2149,16 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- SceneCollection *sc;
+ Collection *collection;
if (scene != CTX_data_scene(C)) {
/* when linking to an inactive scene link to the master collection */
- sc = BKE_collection_master(&scene->id);
+ collection = BKE_collection_master(scene);
}
else {
- sc = CTX_data_scene_collection(C);
+ collection = CTX_data_collection(C);
}
- BKE_collection_object_add(&scene->id, sc, ob);
+ BKE_collection_object_add(bmain, collection, 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);
@@ -2268,58 +2254,81 @@ void OUTLINER_OT_material_drop(wmOperatorType *ot)
RNA_def_string(ot->srna, "material", "Material", MAX_ID_NAME, "Material", "Target Material");
}
-static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+/* ******************** Collection Drop Operator *********************** */
+
+static int collection_drop_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
{
+ /* TODO: implement */
+#if 0
+ Object *par = NULL, *ob = NULL;
Main *bmain = CTX_data_main(C);
- Group *group = NULL;
- Object *ob = NULL;
+ Scene *scene = CTX_data_scene(C);
+ int partype = -1;
+ char parname[MAX_ID_NAME], childname[MAX_ID_NAME];
+
+ RNA_string_get(op->ptr, "parent", parname);
+ par = (Object *)BKE_libblock_find_name(ID_OB, parname);
+ RNA_string_get(op->ptr, "child", childname);
+ ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
+
+ if (ID_IS_LINKED(ob)) {
+ BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL);
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+#endif
+
+ return OPERATOR_FINISHED;
+}
+
+static int collection_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
SpaceOops *soops = CTX_wm_space_outliner(C);
ARegion *ar = CTX_wm_region(C);
- TreeElement *te = NULL;
- char ob_name[MAX_ID_NAME - 2];
+ Main *bmain = CTX_data_main(C);
+ char childname[MAX_ID_NAME];
float fmval[2];
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, true);
-
- if (te) {
- group = (Group *)BKE_libblock_find_name(ID_GR, te->name);
-
- RNA_string_get(op->ptr, "object", ob_name);
- ob = (Object *)BKE_libblock_find_name(ID_OB, ob_name);
+ TreeElement *te = outliner_dropzone_find(soops, fmval, true);
- if (ELEM(NULL, group, ob)) {
- return OPERATOR_CANCELLED;
- }
- if (BKE_group_object_exists(group, ob)) {
- return OPERATOR_FINISHED;
- }
+ if (!te || !outliner_is_collection_tree_element(te)) {
+ return OPERATOR_CANCELLED;
+ }
- if (BKE_group_object_cyclic_check(bmain, ob, group)) {
- BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected");
- return OPERATOR_CANCELLED;
- }
+ Collection *collection = outliner_collection_from_tree_element(te);
- BKE_group_object_add(group, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ // TODO: don't use scene, makes no sense anymore
+ // TODO: move rather than link, change hover text
+ Scene *scene = BKE_scene_find_from_collection(bmain, collection);
+ BLI_assert(scene);
+ RNA_string_get(op->ptr, "child", childname);
+ Object *ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
+ BKE_collection_object_add(bmain, collection, ob);
- return OPERATOR_FINISHED;
- }
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- return OPERATOR_CANCELLED;
+ return OPERATOR_FINISHED;
}
-void OUTLINER_OT_group_link(wmOperatorType *ot)
+void OUTLINER_OT_collection_drop(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Link Object to Group";
- ot->description = "Link Object to Group in Outliner";
- ot->idname = "OUTLINER_OT_group_link";
+ ot->name = "Link to Collection"; // TODO: rename to move?
+ ot->description = "Drag to move to collection in Outliner";
+ ot->idname = "OUTLINER_OT_collection_drop";
/* api callbacks */
- ot->invoke = group_link_invoke;
+ ot->invoke = collection_drop_invoke;
+ ot->exec = collection_drop_exec;
ot->poll = ED_operator_outliner_active;
@@ -2327,5 +2336,6 @@ void OUTLINER_OT_group_link(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
/* properties */
- RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
+ RNA_def_string(ot->srna, "child", "Object", MAX_ID_NAME, "Child", "Child Object");
+ RNA_def_string(ot->srna, "parent", "Collection", MAX_ID_NAME, "Parent", "Parent Collection");
}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index a0de3a06556..73494b890ed 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -71,6 +71,7 @@ typedef enum TreeTraversalAction {
* Callback type for reinserting elements at a different position, used to allow user customizable element order.
*/
typedef void (*TreeElementReinsertFunc)(struct Main *bmain,
+ struct Scene *scene,
struct SpaceOops *soops,
struct TreeElement *insert_element,
struct TreeElement *insert_handle,
@@ -124,6 +125,7 @@ enum {
TE_ICONROW = (1 << 1),
TE_LAZY_CLOSED = (1 << 2),
TE_FREE_NAME = (1 << 3),
+ TE_DISABLED = (1 << 4),
};
/* button events */
@@ -149,11 +151,11 @@ typedef enum {
/* size constants */
#define OL_Y_OFFSET 2
-#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 3.0f)
-#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 2.0f)
+#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 3.0f)
+#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f)
#define OL_TOG_RESTRICT_RENDERX UI_UNIT_X
-#define OL_TOGW OL_TOG_RESTRICT_VIEWX
+#define OL_TOGW OL_TOG_RESTRICT_SELECTX
#define OL_RNA_COLX (UI_UNIT_X * 15)
#define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f)
@@ -161,7 +163,7 @@ typedef enum {
/* The outliner display modes that support the filter system.
* Note: keep it synced with space_outliner.py */
-#define SUPPORT_FILTER_OUTLINER(soops_) ((soops_)->outlinevis == SO_COLLECTIONS)
+#define SUPPORT_FILTER_OUTLINER(soops_) (ELEM((soops_)->outlinevis, SO_VIEW_LAYER))
/* Outliner Searching --
*
@@ -253,16 +255,6 @@ void object_toggle_renderability_cb(
TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void group_toggle_visibility_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene,
- TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void group_toggle_selectability_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene,
- TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void group_toggle_renderability_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene,
- TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-
void item_rename_cb(
struct bContext *C, struct ReportList *reports, struct Scene *scene,
TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
@@ -319,14 +311,13 @@ void OUTLINER_OT_parent_drop(struct wmOperatorType *ot);
void OUTLINER_OT_parent_clear(struct wmOperatorType *ot);
void OUTLINER_OT_scene_drop(struct wmOperatorType *ot);
void OUTLINER_OT_material_drop(struct wmOperatorType *ot);
-void OUTLINER_OT_group_link(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_drop(struct wmOperatorType *ot);
/* outliner_tools.c ---------------------------------------------- */
void OUTLINER_OT_operation(struct wmOperatorType *ot);
void OUTLINER_OT_scene_operation(struct wmOperatorType *ot);
void OUTLINER_OT_object_operation(struct wmOperatorType *ot);
-void OUTLINER_OT_group_operation(struct wmOperatorType *ot);
void OUTLINER_OT_lib_operation(struct wmOperatorType *ot);
void OUTLINER_OT_id_operation(struct wmOperatorType *ot);
void OUTLINER_OT_id_remap(struct wmOperatorType *ot);
@@ -335,7 +326,7 @@ void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot);
void OUTLINER_OT_action_set(struct wmOperatorType *ot);
void OUTLINER_OT_constraint_operation(struct wmOperatorType *ot);
void OUTLINER_OT_modifier_operation(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_operation(struct wmOperatorType *ot);
+
/* ---------------------------------------------------------------- */
/* outliner_ops.c */
@@ -344,23 +335,18 @@ void outliner_keymap(struct wmKeyConfig *keyconf);
/* outliner_collections.c */
-struct SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te);
+bool outliner_is_collection_tree_element(const TreeElement *te);
+struct Collection *outliner_collection_from_tree_element(const TreeElement *te);
-void OUTLINER_OT_collections_delete(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_select(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_toggle(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_unlink(struct wmOperatorType *ot);
void OUTLINER_OT_collection_new(struct wmOperatorType *ot);
void OUTLINER_OT_collection_duplicate(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_delete(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
-void OUTLINER_OT_object_add_to_new_collection(struct wmOperatorType *ot);
-void OUTLINER_OT_object_remove_from_collection(struct wmOperatorType *ot);
-
-void OUTLINER_OT_collection_objects_add(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_nested_new(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_delete_selected(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_instance(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_exclude_set(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_include_set(struct wmOperatorType *ot);
/* outliner_utils.c ---------------------------------------------- */
@@ -368,6 +354,7 @@ TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tre
TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x);
TreeElement *outliner_find_tse(struct SpaceOops *soops, const TreeStoreElem *tse);
TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem);
+TreeElement *outliner_find_parent_element(ListBase *lb, TreeElement *parent_te, const TreeElement *child_te);
TreeElement *outliner_find_id(struct SpaceOops *soops, ListBase *lb, const struct ID *id);
TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *pchan);
TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 9f466d331f3..9c1b9bf2630 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -33,6 +33,8 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "DNA_group_types.h"
+
#include "BLT_translation.h"
#include "BKE_context.h"
@@ -67,7 +69,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_COLLECTIONS, SO_GROUPS);
+ ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_LIBRARIES);
}
static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event)
@@ -184,25 +186,19 @@ static void outliner_item_drag_handle(
*/
static bool is_empty_collection(TreeElement *te)
{
- if (!ELEM(TREESTORE(te)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
- return false;
- }
+ Collection *collection = outliner_collection_from_tree_element(te);
- SceneCollection *scene_collection;
- if (TREESTORE(te)->type == TSE_SCENE_COLLECTION) {
- scene_collection = (SceneCollection *)te->directdata;
- }
- else {
- BLI_assert(TREESTORE(te)->type == TSE_LAYER_COLLECTION);
- scene_collection = ((LayerCollection *)te->directdata)->scene_collection;
+ if (!collection) {
+ return false;
}
- return BLI_listbase_is_empty(&scene_collection->objects) &&
- BLI_listbase_is_empty(&scene_collection->scene_collections);
+ return BLI_listbase_is_empty(&collection->gobject) &&
+ BLI_listbase_is_empty(&collection->children);
}
static bool outliner_item_drag_drop_apply(
Main *bmain,
+ Scene *scene,
SpaceOops *soops,
OutlinerDragDropTooltip *data,
const wmEvent *event)
@@ -225,7 +221,7 @@ static bool outliner_item_drag_drop_apply(
* it is strange to have it closed and we not see the newly dragged elements. */
const bool should_open_collection = (insert_type == TE_INSERT_INTO) && is_empty_collection(insert_handle);
- dragged_te->reinsert(bmain, soops, dragged_te, insert_handle, insert_type, event);
+ dragged_te->reinsert(bmain, scene, soops, dragged_te, insert_handle, insert_type, event);
if (should_open_collection && !is_empty_collection(insert_handle)) {
TREESTORE(insert_handle)->flag &= ~TSE_CLOSED;
@@ -239,6 +235,7 @@ static bool outliner_item_drag_drop_apply(
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);
OutlinerDragDropTooltip *data = op->customdata;
@@ -250,7 +247,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, soops, data, event)) {
+ if (outliner_item_drag_drop_apply(bmain, scene, soops, data, event)) {
skip_rebuild = false;
}
retval = OPERATOR_FINISHED;
@@ -283,37 +280,20 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
return retval;
}
-/**
- * Check if the given TreeElement is a collection
- *
- * This test is mainly used to see if next/prev TreeElement is a collection.
- * It will fail when there is no next/prev TreeElement, or when the
- * element is an Override or something else in the future.
- */
-static bool tree_element_is_collection_get(const TreeElement *te)
-{
- if (te == NULL) {
- return false;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- return ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION);
-}
-
static const char *outliner_drag_drop_tooltip_get(
const TreeElement *te_float)
{
const char *name = NULL;
const TreeElement *te_insert = te_float->drag_data->insert_handle;
- if (tree_element_is_collection_get(te_float)) {
+ if (te_float && outliner_is_collection_tree_element(te_float)) {
if (te_insert == NULL) {
name = TIP_("Move collection");
}
else {
switch (te_float->drag_data->insert_type) {
case TE_INSERT_BEFORE:
- if (tree_element_is_collection_get(te_insert->prev)) {
+ if (te_insert->prev && outliner_is_collection_tree_element(te_insert->prev)) {
name = TIP_("Move between collections");
}
else {
@@ -321,7 +301,7 @@ static const char *outliner_drag_drop_tooltip_get(
}
break;
case TE_INSERT_AFTER:
- if (tree_element_is_collection_get(te_insert->next)) {
+ if (te_insert->next && outliner_is_collection_tree_element(te_insert->next)) {
name = TIP_("Move between collections");
}
else {
@@ -335,7 +315,7 @@ static const char *outliner_drag_drop_tooltip_get(
}
}
else if ((TREESTORE(te_float)->type == 0) && (te_float->idcode == ID_OB)) {
- name = TIP_("Move to collection (Ctrl to add)");
+ name = TIP_("Move to collection (Ctrl to link)");
}
return name;
@@ -434,7 +414,6 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_operation);
WM_operatortype_append(OUTLINER_OT_scene_operation);
WM_operatortype_append(OUTLINER_OT_object_operation);
- WM_operatortype_append(OUTLINER_OT_group_operation);
WM_operatortype_append(OUTLINER_OT_lib_operation);
WM_operatortype_append(OUTLINER_OT_lib_relocate);
WM_operatortype_append(OUTLINER_OT_id_operation);
@@ -445,7 +424,6 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_action_set);
WM_operatortype_append(OUTLINER_OT_constraint_operation);
WM_operatortype_append(OUTLINER_OT_modifier_operation);
- WM_operatortype_append(OUTLINER_OT_collection_operation);
WM_operatortype_append(OUTLINER_OT_show_one_level);
WM_operatortype_append(OUTLINER_OT_show_active);
@@ -467,24 +445,18 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_parent_clear);
WM_operatortype_append(OUTLINER_OT_scene_drop);
WM_operatortype_append(OUTLINER_OT_material_drop);
- WM_operatortype_append(OUTLINER_OT_group_link);
+ WM_operatortype_append(OUTLINER_OT_collection_drop);
/* collections */
- WM_operatortype_append(OUTLINER_OT_collections_delete);
- WM_operatortype_append(OUTLINER_OT_collection_select);
- WM_operatortype_append(OUTLINER_OT_collection_toggle);
- WM_operatortype_append(OUTLINER_OT_collection_link);
- WM_operatortype_append(OUTLINER_OT_collection_unlink);
WM_operatortype_append(OUTLINER_OT_collection_new);
WM_operatortype_append(OUTLINER_OT_collection_duplicate);
-
- WM_operatortype_append(OUTLINER_OT_collection_nested_new);
- WM_operatortype_append(OUTLINER_OT_collection_delete_selected);
- WM_operatortype_append(OUTLINER_OT_collection_objects_add);
- WM_operatortype_append(OUTLINER_OT_collection_objects_remove);
+ WM_operatortype_append(OUTLINER_OT_collection_delete);
WM_operatortype_append(OUTLINER_OT_collection_objects_select);
- WM_operatortype_append(OUTLINER_OT_object_add_to_new_collection);
- WM_operatortype_append(OUTLINER_OT_object_remove_from_collection);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_deselect);
+ WM_operatortype_append(OUTLINER_OT_collection_link);
+ WM_operatortype_append(OUTLINER_OT_collection_instance);
+ WM_operatortype_append(OUTLINER_OT_collection_exclude_set);
+ WM_operatortype_append(OUTLINER_OT_collection_include_set);
}
static wmKeyMap *outliner_item_drag_drop_modal_keymap(wmKeyConfig *keyconf)
@@ -582,8 +554,8 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_add_selected", DKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_delete_selected", DKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_nested_new", CKEY, KM_PRESS, 0, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_delete_selected", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_new", CKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_delete", XKEY, KM_PRESS, 0, 0);
outliner_item_drag_drop_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index d62f542e1d1..42fe70be527 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -44,8 +44,8 @@
#include "BLI_listbase.h"
#include "BKE_armature.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_object.h"
#include "BKE_scene.h"
@@ -681,43 +681,42 @@ static eOLDrawState tree_element_active_keymap_item(
return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_collection(
- bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+static eOLDrawState tree_element_active_master_collection(
+ bContext *C, TreeElement *UNUSED(te), const eOLSetState set)
{
if (set == OL_SETSEL_NONE) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
LayerCollection *active = CTX_data_layer_collection(C);
- /* sometimes the renderlayer has no LayerCollection at all */
- if (active == NULL) {
- return OL_DRAWSEL_NONE;
- }
-
- if ((tselem->type == TSE_SCENE_COLLECTION && active->scene_collection == te->directdata) ||
- (tselem->type == TSE_LAYER_COLLECTION && active == te->directdata))
- {
+ if (active == view_layer->layer_collections.first) {
return OL_DRAWSEL_NORMAL;
}
}
- /* don't allow selecting a scene collection, it can have multiple layer collection
- * instances (which one would the user want to be selected then?) */
- else if (tselem->type == TSE_LAYER_COLLECTION) {
- LayerCollection *layer_collection = te->directdata;
+ else {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *layer_collection = view_layer->layer_collections.first;
+ BKE_layer_collection_activate(view_layer, layer_collection);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ }
- switch (layer_collection->scene_collection->type) {
- case COLLECTION_TYPE_NONE:
- case COLLECTION_TYPE_GROUP_INTERNAL:
- {
- ViewLayer *view_layer = BKE_view_layer_find_from_collection(tselem->id, layer_collection);
- const int collection_index = BKE_layer_collection_findindex(view_layer, layer_collection);
+ return OL_DRAWSEL_NONE;
+}
- if (collection_index > -1) {
- view_layer->active_collection = collection_index;
- }
- break;
- }
- default:
- BLI_assert(!"Collection type not fully implemented");
+static eOLDrawState tree_element_active_layer_collection(
+ bContext *C, TreeElement *te, const eOLSetState set)
+{
+ if (set == OL_SETSEL_NONE) {
+ LayerCollection *active = CTX_data_layer_collection(C);
+
+ if (active == te->directdata) {
+ return OL_DRAWSEL_NORMAL;
}
+ }
+ else {
+ Scene *scene = CTX_data_scene(C);
+ LayerCollection *layer_collection = te->directdata;
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection);
+ BKE_layer_collection_activate(view_layer, layer_collection);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
}
@@ -785,12 +784,7 @@ eOLDrawState tree_element_type_active(
case TSE_CONSTRAINT:
return tree_element_active_constraint(C, scene, view_layer, te, tselem, set);
case TSE_R_LAYER:
- if (soops->outlinevis == SO_SCENES) {
- return active_viewlayer(C, scene, view_layer, te, tselem, set);
- }
- else {
- return OL_DRAWSEL_NONE;
- }
+ return active_viewlayer(C, scene, view_layer, te, tselem, set);
case TSE_POSEGRP:
return tree_element_active_posegroup(C, scene, view_layer, te, tselem, set);
case TSE_SEQUENCE:
@@ -802,9 +796,10 @@ eOLDrawState tree_element_type_active(
case TSE_GP_LAYER:
//return tree_element_active_gplayer(C, scene, s, te, tselem, set);
break;
- case TSE_SCENE_COLLECTION:
+ case TSE_VIEW_COLLECTION_BASE:
+ return tree_element_active_master_collection(C, te, set);
case TSE_LAYER_COLLECTION:
- return tree_element_active_collection(C, te, tselem, set);
+ return tree_element_active_layer_collection(C, te, set);
}
return OL_DRAWSEL_NONE;
}
@@ -840,29 +835,29 @@ static void do_outliner_item_activate_tree_element(
}
}
else if (te->idcode == ID_GR) {
- Group *gr = (Group *)tselem->id;
+ Collection *gr = (Collection *)tselem->id;
if (extend) {
int sel = BA_SELECT;
- FOREACH_GROUP_BASE_BEGIN(gr, base)
+ FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(gr, base)
{
if (base->flag & BASE_SELECTED) {
sel = BA_DESELECT;
break;
}
}
- FOREACH_GROUP_BASE_END
+ FOREACH_COLLECTION_BASE_RECURSIVE_END
- FOREACH_GROUP_OBJECT_BEGIN(gr, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
{
ED_object_base_select(BKE_view_layer_base_find(view_layer, object), sel);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
else {
BKE_view_layer_base_deselect_all(view_layer);
- FOREACH_GROUP_OBJECT_BEGIN(gr, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
{
Base *base = BKE_view_layer_base_find(view_layer, object);
/* Object may not be in this scene */
@@ -872,7 +867,7 @@ static void do_outliner_item_activate_tree_element(
}
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_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 fd5f29aec39..5ae6cec84ba 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -51,10 +51,10 @@
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_override.h"
@@ -105,7 +105,8 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
- if (tselem->type) {
+ /* Layer collection points to collection ID. */
+ if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
if (*datalevel == 0)
*datalevel = tselem->type;
else if (*datalevel != tselem->type)
@@ -129,6 +130,9 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
case ID_LI:
if (*idlevel == 0) *idlevel = idcode;
else if (*idlevel != idcode) *idlevel = -1;
+ if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) {
+ *datalevel = 0;
+ }
break;
}
}
@@ -214,21 +218,52 @@ static void unlink_texture_cb(
}
}
-static void unlink_group_cb(
+static void unlink_collection_cb(
bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
{
- Group *group = (Group *)tselem->id;
-
+ Main *bmain = CTX_data_main(C);
+ Collection *collection = (Collection *)tselem->id;
+
if (tsep) {
if (GS(tsep->id->name) == ID_OB) {
Object *ob = (Object *)tsep->id;
ob->dup_group = NULL;
+ DEG_relations_tag_update(bmain);
+ }
+ else if (GS(tsep->id->name) == ID_GR) {
+ Collection *parent = (Collection *)tsep->id;
+ id_fake_user_set(&collection->id);
+ BKE_collection_child_remove(bmain, parent, collection);
+ DEG_relations_tag_update(bmain);
+ }
+ else if (GS(tsep->id->name) == ID_SCE) {
+ Collection *parent = BKE_collection_master((Scene *)tsep->id);
+ id_fake_user_set(&collection->id);
+ BKE_collection_child_remove(bmain, parent, collection);
+ DEG_relations_tag_update(bmain);
}
}
- else {
- Main *bmain = CTX_data_main(C);
- BKE_libblock_delete(bmain, group);
+}
+
+static void unlink_object_cb(
+ bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
+ TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = (Object *)tselem->id;
+
+ if (tsep) {
+ if (GS(tsep->id->name) == ID_GR) {
+ Collection *parent = (Collection *)tsep->id;
+ BKE_collection_object_remove(bmain, parent, ob, true);
+ DEG_relations_tag_update(bmain);
+ }
+ else if (GS(tsep->id->name) == ID_SCE) {
+ Collection *parent = BKE_collection_master((Scene *)tsep->id);
+ BKE_collection_object_remove(bmain, parent, ob, true);
+ DEG_relations_tag_update(bmain);
+ }
}
}
@@ -255,7 +290,7 @@ static void outliner_do_libdata_operation(
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
- if (tselem->type == 0) {
+ if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
TreeStoreElem *tsep = te->parent ? TREESTORE(te->parent) : NULL;
operation_cb(C, reports, scene, te, tsep, tselem, user_data);
}
@@ -520,42 +555,6 @@ static void singleuser_world_cb(
}
}
-static void group_linkobs2scene_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *sc = CTX_data_scene_collection(C);
- Group *group = (Group *)tselem->id;
- Base *base;
-
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- base = BKE_view_layer_base_find(view_layer, object);
- if (!base) {
- /* link to scene */
- 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(
- bContext *C, ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Group *group = (Group *)tselem->id;
-
- Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, scene->cursor.location, NULL, false, scene->layact);
- ob->dup_group = group;
- ob->transflag |= OB_DUPLIGROUP;
- id_lib_extern(&group->id);
-}
-
/**
* \param select_recurse: Set to false for operations which are already recursively operating on their children.
*/
@@ -660,17 +659,6 @@ typedef enum eOutliner_PropModifierOps {
OL_MODIFIER_OP_DELETE
} eOutliner_PropModifierOps;
-typedef enum eOutliner_PropCollectionOps {
- OL_COLLECTION_OP_OBJECTS_ADD = 1,
- OL_COLLECTION_OP_OBJECTS_REMOVE,
- OL_COLLECTION_OP_OBJECTS_SELECT,
- OL_COLLECTION_OP_COLLECTION_NEW,
- OL_COLLECTION_OP_COLLECTION_COPY,
- OL_COLLECTION_OP_COLLECTION_DEL,
- OL_COLLECTION_OP_COLLECTION_UNLINK,
- OL_COLLECTION_OP_GROUP_CREATE,
-} eOutliner_PropCollectionOps;
-
static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
bPoseChannel *pchan = (bPoseChannel *)te->directdata;
@@ -821,90 +809,6 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem
}
}
-static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *Carg)
-{
- 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(id, sc, ob);
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else if (event == OL_COLLECTION_OP_OBJECTS_REMOVE) {
- Main *bmain = CTX_data_main(C);
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- BKE_collection_object_remove(bmain, id, sc, ob, true);
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- te->store_elem->flag &= ~TSE_SELECTED;
- }
- else if (event == OL_COLLECTION_OP_OBJECTS_SELECT) {
- BKE_layer_collection_objects_select(lc);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
- }
- else if (event == OL_COLLECTION_OP_COLLECTION_NEW) {
- 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_COPY) {
- BKE_layer_collection_duplicate(id, lc);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else if (event == OL_COLLECTION_OP_COLLECTION_UNLINK) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- if (BLI_findindex(&view_layer->layer_collections, lc) == -1) {
- /* we can't unlink if the layer collection wasn't directly linked */
- TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */
- }
- else {
- BKE_collection_unlink(view_layer, lc);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- }
- else if (event == OL_COLLECTION_OP_COLLECTION_DEL) {
- if (BKE_collection_remove(id, sc)) {
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else {
- /* we can't remove the master collection */
- TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */
- }
- }
- else if (event == OL_COLLECTION_OP_GROUP_CREATE) {
- Main *bmain = CTX_data_main(C);
- BKE_collection_group_create(bmain, scene, lc);
- DEG_relations_tag_update(bmain);
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else {
- BLI_assert(!"Collection operation not fully implemented!");
- }
-}
-
static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb,
void (*operation_cb)(int, TreeElement *, TreeStoreElem *, void *),
void *arg)
@@ -1124,106 +1028,6 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot)
/* **************************************** */
-typedef enum eOutliner_PropGroupOps {
- OL_GROUPOP_UNLINK = 1,
- OL_GROUPOP_LOCAL,
- OL_GROUPOP_STATIC_OVERRIDE,
- OL_GROUPOP_LINK,
- OL_GROUPOP_DELETE,
- OL_GROUPOP_REMAP,
- OL_GROUPOP_INSTANCE,
- OL_GROUPOP_TOGVIS,
- OL_GROUPOP_TOGSEL,
- OL_GROUPOP_TOGREN,
- OL_GROUPOP_RENAME,
-} eOutliner_PropGroupOps;
-
-static const EnumPropertyItem prop_group_op_types[] = {
- {OL_GROUPOP_UNLINK, "UNLINK", 0, "Unlink Group", ""},
- {OL_GROUPOP_LOCAL, "LOCAL", 0, "Make Local Group", ""},
- {OL_GROUPOP_STATIC_OVERRIDE, "STATIC_OVERRIDE",
- 0, "Add Static Override", "Add a local static override of that group"},
- {OL_GROUPOP_LINK, "LINK", 0, "Link Group Objects to Scene", ""},
- {OL_GROUPOP_DELETE, "DELETE", 0, "Delete Group", ""},
- {OL_GROUPOP_REMAP, "REMAP", 0, "Remap Users",
- "Make all users of selected data-blocks to use instead current (clicked) one"},
- {OL_GROUPOP_INSTANCE, "INSTANCE", 0, "Instance Groups in Scene", ""},
- {OL_GROUPOP_TOGVIS, "TOGVIS", 0, "Toggle Visible Group", ""},
- {OL_GROUPOP_TOGSEL, "TOGSEL", 0, "Toggle Selectable", ""},
- {OL_GROUPOP_TOGREN, "TOGREN", 0, "Toggle Renderable", ""},
- {OL_GROUPOP_RENAME, "RENAME", 0, "Rename", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-static int outliner_group_operation_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- int event;
-
- /* check for invalid states */
- if (soops == NULL)
- return OPERATOR_CANCELLED;
-
- event = RNA_enum_get(op->ptr, "type");
-
- switch (event) {
- case OL_GROUPOP_UNLINK:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_group_cb, NULL);
- break;
- case OL_GROUPOP_LOCAL:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb, NULL);
- break;
- case OL_GROUPOP_STATIC_OVERRIDE:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_static_override_cb, NULL);
- break;
- case OL_GROUPOP_LINK:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_linkobs2scene_cb, NULL);
- break;
- case OL_GROUPOP_INSTANCE:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_instance_cb, NULL);
- /* works without this except if you try render right after, see: 22027 */
- DEG_relations_tag_update(CTX_data_main(C));
- break;
- case OL_GROUPOP_DELETE:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
- break;
- case OL_GROUPOP_REMAP:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
- break;
- case OL_GROUPOP_RENAME:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL);
- break;
- default:
- BLI_assert(0);
- }
-
- ED_undo_push(C, prop_group_op_types[event - 1].name);
- WM_event_add_notifier(C, NC_GROUP, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-
-void OUTLINER_OT_group_operation(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Outliner Group Operation";
- ot->idname = "OUTLINER_OT_group_operation";
- ot->description = "";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = outliner_group_operation_exec;
- ot->poll = ED_operator_outliner_active;
-
- ot->flag = 0;
-
- ot->prop = RNA_def_enum(ot->srna, "type", prop_group_op_types, 0, "Group Operation", "");
-}
-
-/* **************************************** */
-
typedef enum eOutlinerIdOpTypes {
OUTLINER_IDOP_INVALID = 0,
@@ -1278,6 +1082,14 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
case OUTLINER_IDOP_UNLINK:
{
/* unlink datablock from its parent */
+ if (objectlevel) {
+ outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_object_cb, NULL);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, NULL);
+ ED_undo_push(C, "Unlink Object");
+ break;
+ }
+
switch (idlevel) {
case ID_AC:
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_action_cb, NULL);
@@ -1303,6 +1115,12 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE | ND_WORLD, NULL);
ED_undo_push(C, "Unlink world");
break;
+ case ID_GR:
+ outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_collection_cb, NULL);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, NULL);
+ ED_undo_push(C, "Unlink Collection");
+ break;
default:
BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
break;
@@ -1840,84 +1658,6 @@ 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_OBJECTS_SELECT, "OBJECTS_SELECT", ICON_RESTRICT_SELECT_OFF, "Select Objects", "Select collection objects"},
- {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"},
- {OL_COLLECTION_OP_COLLECTION_COPY, "COLLECTION_DUPLI", ICON_NONE, "Duplicate Collection", "Duplicate the 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"},
- {OL_COLLECTION_OP_GROUP_CREATE, "GROUP_CREATE", ICON_GROUP, "Create Group", "Turn the collection into a group collection"},
- {0, NULL, 0, NULL, NULL}
-};
-
-static int outliner_collection_operation_exec(bContext *C, wmOperator *op)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- eOutliner_PropCollectionOps event;
-
- event = RNA_enum_get(op->ptr, "type");
- set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
-
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, collection_cb, C);
-
- outliner_cleanup_tree(soops);
-
- ED_undo_push(C, "Collection operation");
-
- return OPERATOR_FINISHED;
-}
-
-static int outliner_collection_operation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- wmOperatorType *ot = op->type;
- EnumPropertyItem *prop = &prop_collection_op_types[0];
-
- uiPopupMenu *pup = UI_popup_menu_begin(C, "Collection", ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- for (int i = 0; i < (ARRAY_SIZE(prop_collection_op_types) - 1); i++, prop++) {
- if (soops->outlinevis != SO_GROUPS ||
- !ELEM(prop->value,
- OL_COLLECTION_OP_OBJECTS_SELECT,
- OL_COLLECTION_OP_COLLECTION_UNLINK,
- OL_COLLECTION_OP_GROUP_CREATE))
- {
- uiItemEnumO_ptr(layout, ot, NULL, prop->icon, "type", prop->value);
- }
- }
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
-}
-
-void OUTLINER_OT_collection_operation(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Outliner Collection Operation";
- ot->idname = "OUTLINER_OT_collection_operation";
- ot->description = "";
-
- /* callbacks */
- ot->invoke = outliner_collection_operation_invoke;
- ot->exec = outliner_collection_operation_exec;
- ot->poll = ED_operator_outliner_active;
-
- ot->flag = 0;
-
- prop = RNA_def_enum(ot->srna, "type", prop_collection_op_types, OL_COLLECTION_OP_OBJECTS_ADD, "Collection Operation", "");
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
-}
-
-/* ******************** */
-
// XXX: select linked is for RNA structs only
static const EnumPropertyItem prop_data_op_types[] = {
{OL_DOP_SELECT, "SELECT", 0, "Select", ""},
@@ -2041,7 +1781,7 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
}
set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
-
+
if (scenelevel) {
if (objectlevel || datalevel || idlevel) {
BKE_report(reports, RPT_WARNING, "Mixed selection");
@@ -2051,7 +1791,7 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
}
}
else if (objectlevel) {
- WM_menu_name_call(C, "OUTLINER_MT_context_object", WM_OP_INVOKE_REGION_WIN);
+ WM_menu_name_call(C, "OUTLINER_MT_object", WM_OP_INVOKE_REGION_WIN);
}
else if (idlevel) {
if (idlevel == -1 || datalevel) {
@@ -2060,7 +1800,7 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else {
switch (idlevel) {
case ID_GR:
- WM_operator_name_call(C, "OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
break;
case ID_LI:
WM_operator_name_call(C, "OUTLINER_OT_lib_operation", WM_OP_INVOKE_REGION_WIN, NULL);
@@ -2081,8 +1821,11 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else if (datalevel == TSE_DRIVER_BASE) {
/* do nothing... no special ops needed yet */
}
- else if (ELEM(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER)) {
- /*WM_operator_name_call(C, "OUTLINER_OT_renderdata_operation", WM_OP_INVOKE_REGION_WIN, NULL)*/
+ else if (datalevel == TSE_LAYER_COLLECTION) {
+ WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
+ }
+ else if (ELEM(datalevel, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
+ WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
}
else if (datalevel == TSE_ID_BASE) {
/* do nothing... there are no ops needed here yet */
@@ -2093,12 +1836,6 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else if (datalevel == TSE_MODIFIER) {
WM_operator_name_call(C, "OUTLINER_OT_modifier_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
- else if (datalevel == TSE_LAYER_COLLECTION) {
- WM_operator_name_call(C, "OUTLINER_OT_collection_operation", WM_OP_INVOKE_REGION_WIN, NULL);
- }
- else if (datalevel == TSE_SCENE_COLLECTION) {
- WM_menu_name_call(C, "OUTLINER_MT_context_scene_collection", WM_OP_INVOKE_REGION_WIN);
- }
else {
WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
@@ -2123,6 +1860,7 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent
uiBut *but = UI_context_active_but_get(C);
TreeElement *te;
float fmval[2];
+ bool found = false;
if (but) {
UI_but_tooltip_timer_remove(C, but);
@@ -2132,9 +1870,17 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent
for (te = soops->tree.first; te; te = te->next) {
if (do_outliner_operation_event(C, ar, soops, te, fmval)) {
+ found = true;
break;
}
}
+
+ if (!found) {
+ /* Menus for clicking in empty space. */
+ if (soops->outlinevis == SO_VIEW_LAYER) {
+ WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
+ }
+ }
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index ed809062a29..58ab8f3735e 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -91,14 +91,8 @@
#endif
/* prototypes */
-static void outliner_add_layer_collections_recursive(
- SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten,
- const bool show_objects);
-static TreeElement *outliner_add_scene_collection_recursive(
- SpaceOops *soops, ListBase *tree, Scene *scene, SceneCollection *scene_collection, TreeElement *parent_ten);
-static void outliner_add_view_layer(
- SpaceOops *soops, ListBase *tree, TreeElement *parent,
- Scene *scene, ViewLayer *layer, const bool show_objects);
+static TreeElement *outliner_add_collection_recursive(
+ SpaceOops *soops, Collection *collection, TreeElement *ten);
static void outliner_make_object_parent_hierarchy(ListBase *lb);
/* ********************************************************* */
@@ -293,28 +287,30 @@ static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce,
static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
{
/* View layers */
- TreeElement *tenla = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
- tenla->name = IFACE_("View Layers");
+ TreeElement *ten = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
+ ten->name = IFACE_("View Layers");
ViewLayer *view_layer;
for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
- TreeElement *tenlay = outliner_add_element(soops, &tenla->subtree, sce, te, TSE_R_LAYER, 0);
+ TreeElement *tenlay = outliner_add_element(soops, &ten->subtree, sce, te, TSE_R_LAYER, 0);
tenlay->name = view_layer->name;
tenlay->directdata = view_layer;
}
/* Collections */
- outliner_add_scene_collection_recursive(soops, lb, sce, sce->collection, NULL);
+ ten = outliner_add_element(soops, lb, &sce->id, te, TSE_SCENE_COLLECTION_BASE, 0);
+ ten->name = IFACE_("Scene Collection");
+ outliner_add_collection_recursive(soops, sce->master_collection, ten);
/* Objects */
- tenla = outliner_add_element(soops, lb, sce, te, TSE_SCENE_OBJECTS_BASE, 0);
- tenla->name = IFACE_("Objects");
+ ten = outliner_add_element(soops, lb, sce, te, TSE_SCENE_OBJECTS_BASE, 0);
+ ten->name = IFACE_("Objects");
FOREACH_SCENE_OBJECT_BEGIN(sce, ob)
{
- outliner_add_element(soops, &tenla->subtree, ob, NULL, 0, 0);
+ outliner_add_element(soops, &ten->subtree, ob, NULL, 0, 0);
}
FOREACH_SCENE_OBJECT_END;
- outliner_make_object_parent_hierarchy(&tenla->subtree);
+ outliner_make_object_parent_hierarchy(&ten->subtree);
/* Animation Data */
if (outliner_animdata_test(sce->adt))
@@ -329,7 +325,7 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom
struct ObjectsSelectedData *data = customdata;
TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ if (outliner_is_collection_tree_element(te)) {
return TRAVERSE_CONTINUE;
}
@@ -348,13 +344,14 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom
* Instead we move all the selected objects around.
*/
static void outliner_object_reorder(
- Main *bmain, SpaceOops *soops,
+ Main *bmain, Scene *scene,
+ SpaceOops *soops,
TreeElement *insert_element,
TreeElement *insert_handle, TreeElementInsertType action,
const wmEvent *event)
{
- SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle);
- SceneCollection *sc_ob_parent = NULL;
+ Collection *collection = outliner_collection_from_tree_element(insert_handle);
+ Collection *collection_ob_parent = NULL;
ID *id = insert_handle->store_elem->id;
BLI_assert(action == TE_INSERT_INTO);
@@ -375,24 +372,24 @@ static void outliner_object_reorder(
Object *ob = (Object *)TREESTORE(ten_selected)->id;
if (is_append) {
- BKE_collection_object_add(id, sc, ob);
+ BKE_collection_object_add(bmain, collection, ob);
continue;
}
- /* Find parent scene-collection of object. */
+ /* Find parent collection of object. */
if (ten_selected->parent) {
for (TreeElement *te_ob_parent = ten_selected->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) {
- if (ELEM(TREESTORE(te_ob_parent)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
- sc_ob_parent = outliner_scene_collection_from_tree_element(te_ob_parent);
+ if (outliner_is_collection_tree_element(te_ob_parent)) {
+ collection_ob_parent = outliner_collection_from_tree_element(te_ob_parent);
break;
}
}
}
else {
- sc_ob_parent = BKE_collection_master(id);
+ collection_ob_parent = BKE_collection_master(scene);
}
- BKE_collection_object_move(id, sc, sc_ob_parent, ob);
+ BKE_collection_object_move(bmain, scene, collection, collection_ob_parent, ob);
}
BLI_freelistN(&data.objects_selected_array);
@@ -409,8 +406,7 @@ static bool outliner_object_reorder_poll(
const TreeElement *insert_element,
TreeElement **io_insert_handle, TreeElementInsertType *io_action)
{
- TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
- if (ELEM(tselem_handle->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION) &&
+ if (outliner_is_collection_tree_element(*io_insert_handle) &&
(insert_element->parent != *io_insert_handle))
{
*io_action = TE_INSERT_INTO;
@@ -815,6 +811,11 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
}
break;
}
+ case ID_GR:
+ {
+ Collection *collection = (Collection *)id;
+ outliner_add_collection_recursive(soops, collection, te);
+ }
default:
break;
}
@@ -876,7 +877,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_GP_LAYER) {
/* pass */
}
- else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
/* pass */
}
else if (type == TSE_ID_BASE) {
@@ -895,8 +896,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL;
/* ID datablock */
- if (tsepar == NULL || tsepar->type != TSE_ID_BASE)
+ if (tsepar == NULL || tsepar->type != TSE_ID_BASE || soops->filter_id_type) {
outliner_add_id_contents(soops, te, tselem, id);
+ }
}
else if (type == TSE_ANIM_DATA) {
IdAdtTemplate *iat = (IdAdtTemplate *)idv;
@@ -1177,11 +1179,6 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
te->flag |= TE_LAZY_CLOSED;
}
- if ((type != TSE_LAYER_COLLECTION) && (te->idcode == ID_GR)) {
- Group *group = (Group *)id;
- outliner_add_layer_collections_recursive(soops, &te->subtree, id, &group->view_layer->layer_collections, NULL, true);
- }
-
return te;
}
@@ -1263,6 +1260,32 @@ static const char *outliner_idcode_to_plural(short idcode)
return (prop) ? RNA_property_ui_name(prop) : "UNKNOWN";
}
+static bool outliner_library_id_show(Library *lib, ID *id, short filter_id_type)
+{
+ if (id->lib != lib) {
+ return false;
+ }
+
+ if (filter_id_type == ID_GR) {
+ /* Don't show child collections of non-scene master collection,
+ * they are already shown as children. */
+ Collection *collection = (Collection *)id;
+ bool has_non_scene_parent = false;
+
+ for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) {
+ has_non_scene_parent = true;
+ }
+ }
+
+ if (has_non_scene_parent) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeElement *te, Library *lib)
{
TreeElement *ten;
@@ -1298,13 +1321,13 @@ static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeE
}
for (id = lbarray[a]->first; id; id = id->next) {
- if (id->lib == lib)
+ if (outliner_library_id_show(lib, id, filter_id_type)) {
outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
+ }
}
}
}
}
-
}
static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
@@ -1353,170 +1376,165 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
}
}
-static void outliner_layer_collections_reorder(
+static void outliner_collections_reorder(
Main *bmain,
- SpaceOops *UNUSED(soops),
- TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action,
+ Scene *UNUSED(scene),
+ SpaceOops *soops,
+ TreeElement *insert_element,
+ TreeElement *insert_handle,
+ TreeElementInsertType action,
const wmEvent *UNUSED(event))
{
- LayerCollection *lc_insert = insert_element->directdata;
- LayerCollection *lc_handle = insert_handle->directdata;
- ID *id = insert_element->store_elem->id;
+ TreeElement *from_parent_te, *to_parent_te;
+ Collection *from_parent, *to_parent;
- if (action == TE_INSERT_BEFORE) {
- BKE_layer_collection_move_above(id, lc_handle, lc_insert);
- }
- else if (action == TE_INSERT_AFTER) {
- BKE_layer_collection_move_below(id, lc_handle, lc_insert);
+ Collection *collection = outliner_collection_from_tree_element(insert_element);
+ Collection *relative = NULL;
+ bool relative_after = false;
+
+ from_parent_te = outliner_find_parent_element(&soops->tree, NULL, insert_element);
+ from_parent = (from_parent_te) ? outliner_collection_from_tree_element(from_parent_te) : NULL;
+
+ if (ELEM(action, TE_INSERT_BEFORE, TE_INSERT_AFTER)) {
+ to_parent_te = outliner_find_parent_element(&soops->tree, NULL, insert_handle);
+ to_parent = (to_parent_te) ? outliner_collection_from_tree_element(to_parent_te) : NULL;
+
+ relative = outliner_collection_from_tree_element(insert_handle);
+ relative_after = (action == TE_INSERT_AFTER);
}
else if (action == TE_INSERT_INTO) {
- BKE_layer_collection_move_into(id, lc_handle, lc_insert);
+ to_parent = outliner_collection_from_tree_element(insert_handle);
}
else {
BLI_assert(0);
+ return;
}
+ if (!to_parent) {
+ return;
+ }
+
+ BKE_collection_move(bmain, to_parent, from_parent, relative, relative_after, collection);
+
DEG_relations_tag_update(bmain);
}
-static bool outliner_layer_collections_reorder_poll(
+
+static bool outliner_collections_reorder_poll(
const TreeElement *insert_element,
- TreeElement **io_insert_handle, TreeElementInsertType *UNUSED(io_action))
+ TreeElement **io_insert_handle,
+ TreeElementInsertType *io_action)
{
- const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+ /* Can't move master collection. */
+ Collection *collection = outliner_collection_from_tree_element(insert_element);
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ return false;
+ }
+
+ /* Can only move into collections. */
+ Collection *collection_handle = outliner_collection_from_tree_element(*io_insert_handle);
+ if (collection_handle == NULL) {
+ return false;
+ }
- if (tselem_handle->id != insert_element->store_elem->id) {
- return false;
+ /* We can't insert/before after master collection. */
+ if (collection_handle->flag & COLLECTION_IS_MASTER) {
+ if (*io_action == TE_INSERT_BEFORE) {
+ /* can't go higher than master collection, insert into it */
+ *io_action = TE_INSERT_INTO;
+ }
+ else if (*io_action == TE_INSERT_AFTER) {
+ *io_insert_handle = (*io_insert_handle)->subtree.last;
+ }
}
- return ELEM(tselem_handle->type, TSE_LAYER_COLLECTION);
+ return true;
+}
+
+static void outliner_add_layer_collection_objects(
+ SpaceOops *soops, ListBase *tree, ViewLayer *layer,
+ LayerCollection *lc, TreeElement *ten)
+{
+ for (CollectionObject *cob = lc->collection->gobject.first; cob; cob = cob->next) {
+ Base *base = BKE_view_layer_base_find(layer, cob->ob);
+ TreeElement *te_object = outliner_add_element(soops, tree, base->object, ten, 0, 0);
+ te_object->directdata = base;
+ }
}
static void outliner_add_layer_collections_recursive(
- SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten,
+ SpaceOops *soops, ListBase *tree, ViewLayer *layer,
+ ListBase *layer_collections, TreeElement *parent_ten,
const bool show_objects)
{
- for (LayerCollection *collection = layer_collections->first; collection; collection = collection->next) {
+ for (LayerCollection *lc = layer_collections->first; lc; lc = lc->next) {
+ ID *id = &lc->collection->id;
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;
+ ten->name = id->name + 2;
+ ten->directdata = lc;
+ ten->reinsert = outliner_collections_reorder;
+ ten->reinsert_poll = outliner_collections_reorder_poll;
- outliner_add_layer_collections_recursive(soops, &ten->subtree, id, &collection->layer_collections, ten, show_objects);
- if (show_objects) {
- 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);
- te_object->directdata = base;
- }
+ const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
+ if (exclude) {
+ ten->flag |= TE_DISABLED;
+ }
+
+ outliner_add_layer_collections_recursive(soops, &ten->subtree, layer, &lc->layer_collections, ten, show_objects);
+ if (!exclude && show_objects) {
+ outliner_add_layer_collection_objects(soops, &ten->subtree, layer, lc, ten);
}
}
}
static void outliner_add_view_layer(SpaceOops *soops, ListBase *tree, TreeElement *parent,
- Scene *scene, ViewLayer *layer, const bool show_objects)
-{
- outliner_add_layer_collections_recursive(soops, tree, &scene->id, &layer->layer_collections, parent, show_objects);
-}
-
-static void outliner_scene_collections_reorder(
- Main *bmain,
- SpaceOops *UNUSED(soops),
- TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action,
- const wmEvent *UNUSED(event))
-{
- 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(id)));
- if (action == TE_INSERT_BEFORE) {
- BKE_collection_move_above(id, sc_handle, sc_insert);
- }
- else if (action == TE_INSERT_AFTER) {
- BKE_collection_move_below(id, sc_handle, sc_insert);
- }
- else if (action == TE_INSERT_INTO) {
- BKE_collection_move_into(id, sc_handle, sc_insert);
- }
- else {
- BLI_assert(0);
- }
-
- DEG_relations_tag_update(bmain);
-}
-static bool outliner_scene_collections_reorder_poll(
- const TreeElement *insert_element,
- TreeElement **io_insert_handle, TreeElementInsertType *io_action)
+ ViewLayer *layer, const bool show_objects)
{
- const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
- ID *id = tselem_handle->id;
-
- if (id != insert_element->store_elem->id) {
- return false;
- }
-
- if (!ELEM(tselem_handle->type, TSE_SCENE_COLLECTION)) {
- return false;
+ /* First layer collection is for master collection, don't show it. */
+ LayerCollection *lc = layer->layer_collections.first;
+ if (lc == NULL) {
+ return;
}
- 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;
- if (*io_action == TE_INSERT_BEFORE) {
- /* can't go higher than master collection, insert into it */
- *io_action = TE_INSERT_INTO;
- }
- else if (*io_action == TE_INSERT_AFTER) {
- *io_insert_handle = te_master->subtree.last;
- }
+ outliner_add_layer_collections_recursive(soops, tree, layer, &lc->layer_collections, parent, show_objects);
+ if (show_objects) {
+ outliner_add_layer_collection_objects(soops, tree, layer, lc, parent);
}
- return true;
}
-BLI_INLINE void outliner_add_scene_collection_init(TreeElement *te, Scene *scene, SceneCollection *collection)
+BLI_INLINE void outliner_add_collection_init(TreeElement *te, Collection *collection)
{
- if (collection == scene->collection) {
- // Don't display name of master collection
- te->name = IFACE_("Collections");
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ te->name = IFACE_("Scene Collection");
}
else {
- te->name = collection->name;
+ te->name = collection->id.name + 2;
}
te->directdata = collection;
- te->reinsert = outliner_scene_collections_reorder;
- te->reinsert_poll = outliner_scene_collections_reorder_poll;
+ te->reinsert = outliner_collections_reorder;
+ te->reinsert_poll = outliner_collections_reorder_poll;
}
-BLI_INLINE void outliner_add_scene_collection_objects(
- SpaceOops *soops, ListBase *tree, SceneCollection *collection, TreeElement *parent)
+BLI_INLINE void outliner_add_collection_objects(
+ SpaceOops *soops, ListBase *tree, Collection *collection, TreeElement *parent)
{
- for (LinkData *link = collection->objects.first; link; link = link->next) {
- outliner_add_element(soops, tree, link->data, parent, 0, 0);
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ outliner_add_element(soops, tree, cob->ob, parent, 0, 0);
}
}
-static TreeElement *outliner_add_scene_collection_recursive(
- SpaceOops *soops, ListBase *tree, Scene *scene, SceneCollection *scene_collection, TreeElement *parent_ten)
+static TreeElement *outliner_add_collection_recursive(
+ SpaceOops *soops, Collection *collection, TreeElement *ten)
{
- TreeElement *ten = outliner_add_element(soops, tree, &scene->id, parent_ten, TSE_SCENE_COLLECTION, 0);
- outliner_add_scene_collection_init(ten, scene, scene_collection);
+ outliner_add_collection_init(ten, collection);
- if (soops->outlinevis != SO_SCENES) {
- outliner_add_scene_collection_objects(soops, &ten->subtree, scene_collection, ten);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ outliner_add_element(soops, &ten->subtree, &child->collection->id, ten, 0, 0);
}
- for (SceneCollection *scene_collection_nested = scene_collection->scene_collections.first;
- scene_collection_nested != NULL;
- scene_collection_nested = scene_collection_nested->next)
- {
- outliner_add_scene_collection_recursive(soops, &ten->subtree, scene, scene_collection_nested, ten);
+ if (soops->outlinevis != SO_SCENES) {
+ outliner_add_collection_objects(soops, &ten->subtree, collection, ten);
}
return ten;
@@ -1732,8 +1750,7 @@ static void outliner_restore_scrolling_position(SpaceOops *soops, ARegion *ar, O
static bool test_collection_callback(TreeElement *te)
{
- TreeStoreElem *tselem = TREESTORE(te);
- return ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION);
+ return outliner_is_collection_tree_element(te);
}
static bool test_object_callback(TreeElement *te)
@@ -1787,7 +1804,8 @@ static TreeElement *outliner_find_first_desired_element_at_y(
te = outliner_find_item_at_y(soops, &soops->tree, view_co);
bool (*callback_test)(TreeElement *);
- if (soops->filter & SO_FILTER_NO_COLLECTION) {
+ if ((soops->outlinevis == SO_VIEW_LAYER) &&
+ (soops->filter & SO_FILTER_NO_COLLECTION)) {
callback_test = test_object_callback;
}
else {
@@ -1866,10 +1884,11 @@ static int outliner_exclude_filter_get(SpaceOops *soops)
return (exclude_filter & SO_FILTER_SEARCH);
}
+ if (soops->filter & SO_FILTER_NO_OBJECT) {
+ exclude_filter |= SO_FILTER_OB_TYPE;
+ }
+
switch (soops->filter_state) {
- case SO_FILTER_OB_NONE:
- exclude_filter |= SO_FILTER_OB_TYPE;
- break;
case SO_FILTER_OB_VISIBLE:
exclude_filter |= SO_FILTER_OB_STATE_VISIBLE;
break;
@@ -2163,12 +2182,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
outliner_make_object_parent_hierarchy(&te->subtree);
}
}
- else if (soops->outlinevis == SO_GROUPS) {
- Group *group;
- for (group = mainvar->group.first; group; group = group->id.next) {
- te = outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
- }
- }
else if (soops->outlinevis == SO_SEQUENCE) {
Sequence *seq;
Editing *ed = BKE_sequencer_editing_get(scene, false);
@@ -2208,27 +2221,24 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
else if (soops->outlinevis == SO_ID_ORPHANS) {
outliner_add_orphaned_datablocks(mainvar, soops);
}
- else if (soops->outlinevis == SO_COLLECTIONS) {
- TreeElement *tenlay = outliner_add_element(soops, &soops->tree, scene, te, TSE_R_LAYER, 0);
- tenlay->name = view_layer->name;
- tenlay->directdata = view_layer;
- TREESTORE(tenlay)->flag &= ~TSE_CLOSED;
-
+ else if (soops->outlinevis == SO_VIEW_LAYER) {
if (soops->filter & SO_FILTER_NO_COLLECTION) {
+ /* Show objects in the view layer. */
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- TreeElement *te_object = outliner_add_element(soops, &tenlay->subtree, base->object, NULL, 0, 0);
+ TreeElement *te_object = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
te_object->directdata = base;
}
- outliner_make_object_parent_hierarchy(&tenlay->subtree);
+
+ outliner_make_object_parent_hierarchy(&soops->tree);
}
else {
- outliner_add_view_layer(soops, &tenlay->subtree, NULL, scene, view_layer, true);
- }
- }
- else {
- if (BASACT(view_layer)) {
- ten = outliner_add_element(soops, &soops->tree, OBACT(view_layer), NULL, 0, 0);
- ten->directdata = BASACT(view_layer);
+ /* Show collections in the view layer. */
+ ten = outliner_add_element(soops, &soops->tree, scene, NULL, TSE_VIEW_COLLECTION_BASE, 0);
+ ten->name = IFACE_("Scene Collection");
+ TREESTORE(ten)->flag &= ~TSE_CLOSED;
+
+ bool show_objects = !(soops->filter & SO_FILTER_NO_OBJECT);
+ outliner_add_view_layer(soops, &ten->subtree, ten, view_layer, show_objects);
}
}
diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c
index d3f7fd7055e..896f6c016d0 100644
--- a/source/blender/editors/space_outliner/outliner_utils.c
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -101,6 +101,23 @@ TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store
return NULL;
}
+/* Find parent element of te */
+TreeElement *outliner_find_parent_element(ListBase *lb, TreeElement *parent_te, const TreeElement *child_te)
+{
+ TreeElement *te;
+ for (te = lb->first; te; te = te->next) {
+ if (te == child_te) {
+ return parent_te;
+ }
+
+ TreeElement *find_te = outliner_find_parent_element(&te->subtree, te, child_te);
+ if (find_te) {
+ return find_te;
+ }
+ }
+ return NULL;
+}
+
/* tse is not in the treestore, we use its contents to find a match */
TreeElement *outliner_find_tse(SpaceOops *soops, const TreeStoreElem *tse)
{
@@ -125,10 +142,8 @@ TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id)
if (tselem->id == id) {
return te;
}
- /* only deeper on scene or object */
- if (ELEM(te->idcode, ID_OB, ID_SCE) ||
- ((soops->outlinevis == SO_GROUPS) && (te->idcode == ID_GR)))
- {
+ /* only deeper on scene collection or object */
+ if (ELEM(te->idcode, ID_OB, ID_SCE, ID_GR)) {
TreeElement *tes = outliner_find_id(soops, &te->subtree, id);
if (tes) {
return tes;
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index b762dd31f58..72ce24aaff5 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -138,10 +138,6 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
}
}
}
- else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
- /* support adding object from different scene to collection */
- return 1;
- }
}
}
return 0;
@@ -163,7 +159,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- if (!ELEM(soops->outlinevis, SO_SCENES, SO_GROUPS, SO_COLLECTIONS)) {
+ if (!ELEM(soops->outlinevis, SO_VIEW_LAYER)) {
return false;
}
@@ -250,7 +246,7 @@ static void outliner_material_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "material", id->name + 2);
}
-static int outliner_group_link_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+static int outliner_collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -259,19 +255,19 @@ static int outliner_group_link_poll(bContext *C, wmDrag *drag, const wmEvent *ev
if (drag->type == WM_DRAG_ID) {
ID *id = drag->poin;
- if (GS(id->name) == ID_OB) {
+ if (ELEM(GS(id->name), ID_OB, ID_GR)) {
/* Ensure item under cursor is valid drop target */
TreeElement *te = outliner_dropzone_find(soops, fmval, true);
- return (te && te->idcode == ID_GR && TREESTORE(te)->type == 0);
+ return (te && outliner_is_collection_tree_element(te));
}
}
return 0;
}
-static void outliner_group_link_copy(wmDrag *drag, wmDropBox *drop)
+static void outliner_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = drag->poin;
- RNA_string_set(drop->ptr, "object", id->name + 2);
+ RNA_string_set(drop->ptr, "child", id->name + 2);
}
/* region dropbox definition */
@@ -283,7 +279,7 @@ static void outliner_dropboxes(void)
WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", outliner_parent_clear_poll, outliner_parent_clear_copy);
WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", outliner_scene_drop_poll, outliner_scene_drop_copy);
WM_dropbox_add(lb, "OUTLINER_OT_material_drop", outliner_material_drop_poll, outliner_material_drop_copy);
- WM_dropbox_add(lb, "OUTLINER_OT_group_link", outliner_group_link_poll, outliner_group_link_copy);
+ WM_dropbox_add(lb, "OUTLINER_OT_collection_drop", outliner_collection_drop_poll, outliner_collection_drop_copy);
}
static void outliner_main_region_draw(const bContext *C, ARegion *ar)
@@ -438,7 +434,7 @@ static void outliner_main_region_message_subscribe(
.notify = ED_region_do_msg_notify_tag_redraw,
};
- if (soops->outlinevis == SO_COLLECTIONS) {
+ if (ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_SCENES)) {
WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
}
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index df9d8dad6ee..f26da3ad07e 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -549,7 +549,7 @@ static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
return 0;
}
-static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static int view3d_collection_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
ID *id = drag->poin;
@@ -624,7 +624,7 @@ static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "name", id->name + 2);
}
-static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = drag->poin;
@@ -664,7 +664,7 @@ static void view3d_dropboxes(void)
WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_mesh_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
- WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_collection_instance_add", view3d_collection_drop_poll, view3d_collection_drop_copy);
}
static void view3d_widgets(void)
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 7fc582a1511..43ff8af42fb 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -45,8 +45,8 @@
#include "BKE_appdir.h"
#include "BKE_blender_copybuffer.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -81,17 +81,17 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- for (Group *group = bmain->group.first; group; group = group->id.next) {
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Object *object = cob->ob;
+
if (object && (object->id.tag & LIB_TAG_DOIT)) {
- BKE_copybuffer_tag_ID(&group->id);
+ BKE_copybuffer_tag_ID(&collection->id);
/* don't expand out to all other objects */
- group->id.tag &= ~LIB_TAG_NEED_EXPAND;
+ collection->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 06f62f5a5dc..362b34aa64c 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -34,6 +34,7 @@ extern "C" {
#include "RNA_types.h"
#include "DNA_camera_types.h"
+#include "DNA_group_types.h"
#include "DNA_listBase.h"
#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
@@ -47,6 +48,7 @@ extern "C" {
#include "BKE_customdata.h"
#include "BKE_idprop.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_library.h" /* free_libblock */
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -206,12 +208,7 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer()
}
// Make sure we don't have any bases which might reference freed objects.
- FOREACH_SCENE_COLLECTION_BEGIN(freestyle_scene, sc)
- {
- BLI_freelistN(&sc->objects);
- }
- FOREACH_SCENE_COLLECTION_END;
- BLI_freelistN(&view_layer->object_bases);
+ BKE_main_collection_sync(freestyle_bmain);
// release materials
Link *lnk = (Link *)freestyle_bmain->mat.first;
@@ -865,8 +862,8 @@ Object *BlenderStrokeRenderer::NewMesh() const
ob->data = BKE_mesh_add(freestyle_bmain, name);
ob->lay = 1;
- SceneCollection *sc_master = BKE_collection_master(&freestyle_scene->id);
- BKE_collection_object_add(&freestyle_scene->id, sc_master, ob);
+ Collection *collection_master = BKE_collection_master(freestyle_scene);
+ BKE_collection_object_add(freestyle_bmain, collection_master, ob);
DEG_graph_tag_relations_update(freestyle_depsgraph);
DEG_graph_id_tag_update(freestyle_bmain,
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index c346d20632b..769c60f8e61 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -56,7 +56,6 @@
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_scene.h"
-#include "BKE_group.h"
#include "IMB_imbuf_types.h"
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 3c035ae0bc8..2e73f5754d3 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -43,7 +43,7 @@
struct SpaceLink;
struct Object;
-struct Group;
+struct Collection;
struct GHash;
/* ************************************************ */
@@ -588,7 +588,7 @@ typedef struct bDopeSheet {
ID *source; /* currently ID_SCE (for Dopesheet), and ID_SC (for Grease Pencil) */
ListBase chanbase; /* cache for channels (only initialized when pinned) */ // XXX not used!
- struct Group *filter_grp; /* object group for ADS_FILTER_ONLYOBGROUP filtering option */
+ struct Collection *filter_grp; /* object group for ADS_FILTER_ONLYOBGROUP filtering option */
char searchstr[64]; /* string to search for in displayed names of F-Curves for ADS_FILTER_BY_FCU_NAME filtering option */
int filterflag; /* flags to use for filtering data */
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
index ee147da8dae..00995bcf290 100644
--- a/source/blender/makesdna/DNA_cloth_types.h
+++ b/source/blender/makesdna/DNA_cloth_types.h
@@ -116,7 +116,7 @@ typedef struct ClothCollSettings {
short self_loop_count; /* How many iterations for the selfcollision loop */
short loop_count; /* How many iterations for the collision loop. */
int pad;
- struct Group *group; /* Only use colliders from this group of objects */
+ struct Collection *group; /* Only use colliders from this group of objects */
short vgroup_selfcol; /* vgroup to paint which vertices are used for self collisions */
short pad2[3];
} ClothCollSettings;
diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h
index ecdcb2398ac..b341c2841e2 100644
--- a/source/blender/makesdna/DNA_dynamicpaint_types.h
+++ b/source/blender/makesdna/DNA_dynamicpaint_types.h
@@ -104,7 +104,7 @@ typedef struct DynamicPaintSurface {
struct DynamicPaintCanvasSettings *canvas; /* for fast RNA access */
struct PaintSurfaceData *data;
- struct Group *brush_group;
+ struct Collection *brush_group;
struct EffectorWeights *effector_weights;
/* cache */
diff --git a/source/blender/makesdna/DNA_effect_types.h b/source/blender/makesdna/DNA_effect_types.h
index 7ca3bbe3319..3455feea1a9 100644
--- a/source/blender/makesdna/DNA_effect_types.h
+++ b/source/blender/makesdna/DNA_effect_types.h
@@ -97,7 +97,7 @@ typedef struct Particle {
short mat_nr, rt;
} Particle;
-struct Group;
+struct Collection;
typedef struct PartEff {
struct PartEff *next, *prev;
@@ -122,7 +122,7 @@ typedef struct PartEff {
float imat[4][4]; /* inverse matrix of parent Object */
Particle *keys;
- struct Group *group;
+ struct Collection *group;
} PartEff;
diff --git a/source/blender/makesdna/DNA_freestyle_types.h b/source/blender/makesdna/DNA_freestyle_types.h
index 2359d1e9738..158bdf573b3 100644
--- a/source/blender/makesdna/DNA_freestyle_types.h
+++ b/source/blender/makesdna/DNA_freestyle_types.h
@@ -40,7 +40,7 @@ extern "C" {
#endif
struct FreestyleLineStyle;
-struct Group;
+struct Collection;
struct Text;
/* FreestyleConfig::flags */
@@ -125,7 +125,7 @@ typedef struct FreestyleLineSet {
int qi_start, qi_end;
int edge_types, exclude_edge_types; /* feature edge types */
int pad2;
- struct Group *group; /* group of target objects */
+ struct Collection *group; /* group of target objects */
struct FreestyleLineStyle *linestyle;
} FreestyleLineSet;
diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h
index 57db668b282..3b947caf59c 100644
--- a/source/blender/makesdna/DNA_group_types.h
+++ b/source/blender/makesdna/DNA_group_types.h
@@ -34,36 +34,61 @@
#ifndef __DNA_GROUP_TYPES_H__
#define __DNA_GROUP_TYPES_H__
+#include "DNA_defs.h"
#include "DNA_listBase.h"
#include "DNA_ID.h"
struct Object;
+struct Collection;
-typedef struct GroupObject {
- struct GroupObject *next, *prev;
+typedef struct CollectionObject {
+ struct CollectionObject *next, *prev;
struct Object *ob;
-} GroupObject;
+} CollectionObject;
-typedef struct Group {
+typedef struct CollectionChild {
+ struct CollectionChild *next, *prev;
+ struct Collection *collection;
+} CollectionChild;
+
+
+typedef struct Collection {
ID id;
- ListBase gobject; /* GroupObject */
+ ListBase gobject; /* CollectionObject */
+ ListBase children; /* CollectionChild */
struct PreviewImage *preview;
- /* Bad design, since layers stored in the scenes 'Base'
- * the objects that show in the group can change depending
- * on the last used scene */
- unsigned int layer;
+ unsigned int layer DNA_DEPRECATED;
float dupli_ofs[3];
- struct SceneCollection *collection;
- struct ViewLayer *view_layer;
-} Group;
+ short flag, pad[3];
+
+ /* Runtime. Cache of objects in this collection and all its
+ * children. This is created on demand when e.g. some physics
+ * simulation needs it, we don't want to have it for every
+ * collections due to memory usage reasons. */
+ ListBase object_cache;
+
+ /* Runtime. List of collections that are a parent of this
+ * datablock. */
+ ListBase parents;
+ /* Deprecated */
+ struct SceneCollection *collection DNA_DEPRECATED;
+ struct ViewLayer *view_layer DNA_DEPRECATED;
+} Collection;
-#define GROUP_MASTER_COLLECTION(_group) \
- (((LayerCollection *)(_group)->view_layer->layer_collections.first)->scene_collection)
+/* Collection->flag */
+enum {
+ COLLECTION_RESTRICT_VIEW = (1 << 0), /* Hidden in viewport. */
+ COLLECTION_RESTRICT_SELECT = (1 << 1), /* Not selectable in viewport. */
+ COLLECTION_DISABLED_DEPRECATED = (1 << 2), /* Not used anymore */
+ COLLECTION_RESTRICT_RENDER = (1 << 3), /* Hidden in renders. */
+ COLLECTION_HAS_OBJECT_CACHE = (1 << 4), /* Runtime: object_cache is populated. */
+ COLLECTION_IS_MASTER = (1 << 5), /* Is master collection embedded in the scene. */
+};
#endif /* __DNA_GROUP_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index 82979ba8cde..66a8c3e236d 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -37,7 +37,7 @@ extern "C" {
typedef struct Base {
struct Base *next, *prev;
short flag;
- short refcount;
+ short pad;
short sx, sy;
struct Object *object;
unsigned int lay;
@@ -53,25 +53,23 @@ typedef struct ViewLayerEngineData {
typedef struct LayerCollection {
struct LayerCollection *next, *prev;
- struct SceneCollection *scene_collection;
+ struct Collection *collection;
+ struct SceneCollection *scene_collection DNA_DEPRECATED;
short flag;
- /* TODO(sergey): Get rid of this once we've got CoW in DEG, */
- short flag_evaluated;
- short pad[2];
- ListBase object_bases; /* (ObjectBase *)LinkData->data - synced with collection->objects */
- ListBase layer_collections; /* synced with collection->collections */
+ short pad[3];
+ ListBase layer_collections; /* synced with collection->children */
} LayerCollection;
typedef struct ViewLayer {
struct ViewLayer *next, *prev;
char name[64]; /* MAX_NAME */
- short active_collection;
short flag;
- short pad[2];
+ short pad[3];
ListBase object_bases; /* ObjectBase */
struct SceneStats *stats; /* default allocated now */
struct Base *basact;
ListBase layer_collections; /* LayerCollection */
+ LayerCollection *active_collection;
/* Old SceneRenderLayer data. */
int layflag;
@@ -86,18 +84,9 @@ typedef struct ViewLayer {
/* Runtime data */
ListBase drawdata; /* ViewLayerEngineData */
struct Base **object_bases_array;
+ struct GHash *object_bases_hash;
} ViewLayer;
-typedef struct SceneCollection {
- struct SceneCollection *next, *prev;
- char name[64]; /* MAX_NAME */
- int active_object_index; /* for UI */
- char type;
- char pad[3];
- ListBase objects; /* (Object *)LinkData->data */
- ListBase scene_collections; /* nested collections */
-} SceneCollection;
-
/* Base->flag */
enum {
BASE_SELECTED = (1 << 0),
@@ -106,14 +95,17 @@ enum {
BASE_FROMDUPLI = (1 << 3),
BASE_DIRTY_ENGINE_SETTINGS = (1 << 4),
BASE_FROM_SET = (1 << 5), /* To be set only by the depsgraph */
+ BASE_VISIBLE_VIEWPORT = (1 << 6),
+ BASE_VISIBLE_RENDER = (1 << 7),
};
/* LayerCollection->flag */
enum {
- COLLECTION_VIEWPORT = (1 << 0), /* Only used for group collections. */
- COLLECTION_SELECTABLE = (1 << 1),
- COLLECTION_DISABLED = (1 << 2),
- COLLECTION_RENDER = (1 << 3), /* Only used for group collections. */
+ /* LAYER_COLLECTION_DEPRECATED0 = (1 << 0), */
+ /* LAYER_COLLECTION_DEPRECATED1 = (1 << 1), */
+ /* LAYER_COLLECTION_DEPRECATED2 = (1 << 2), */
+ /* LAYER_COLLECTION_DEPRECATED3 = (1 << 3), */
+ LAYER_COLLECTION_EXCLUDE = (1 << 4),
};
/* ViewLayer->flag */
@@ -123,11 +115,22 @@ enum {
VIEW_LAYER_FREESTYLE = (1 << 2),
};
-/* SceneCollection->type */
-enum {
- COLLECTION_TYPE_NONE = 0,
- COLLECTION_TYPE_GROUP_INTERNAL = 1,
-};
+/****************************** Deprecated ******************************/
+
+/* Compatibility with collections saved in early 2.8 versions,
+ * used in file reading and versioning code. */
+#define USE_COLLECTION_COMPAT_28
+
+typedef struct SceneCollection {
+ struct SceneCollection *next, *prev;
+ char name[64]; /* MAX_NAME */
+ int active_object_index; /* for UI */
+ short flag;
+ char type;
+ char pad;
+ ListBase objects; /* (Object *)LinkData->data */
+ ListBase scene_collections; /* nested collections */
+} SceneCollection;
#ifdef __cplusplus
}
diff --git a/source/blender/makesdna/DNA_lightprobe_types.h b/source/blender/makesdna/DNA_lightprobe_types.h
index 3eee6d4b192..86d4645ecf5 100644
--- a/source/blender/makesdna/DNA_lightprobe_types.h
+++ b/source/blender/makesdna/DNA_lightprobe_types.h
@@ -66,7 +66,7 @@ typedef struct LightProbe {
struct Object *parallax_ob; /* Object to use as a parallax origin */
struct Image *image; /* Image to use on as lighting data */
- struct Group *visibility_grp; /* Object visibility group, inclusive or exclusive */
+ struct Collection *visibility_grp; /* Object visibility group, inclusive or exclusive */
float data_draw_size;
diff --git a/source/blender/makesdna/DNA_object_force_types.h b/source/blender/makesdna/DNA_object_force_types.h
index 16c96073469..a83517e4eb4 100644
--- a/source/blender/makesdna/DNA_object_force_types.h
+++ b/source/blender/makesdna/DNA_object_force_types.h
@@ -122,7 +122,7 @@ typedef struct PartDeflect {
} PartDeflect;
typedef struct EffectorWeights {
- struct Group *group; /* only use effectors from this group of objects */
+ struct Collection *group; /* only use effectors from this group of objects */
float weight[14]; /* effector type specific weights */
float global_gravity;
@@ -292,7 +292,7 @@ typedef struct SoftBody {
struct PointCache *pointcache;
struct ListBase ptcaches;
- struct Group *collision_group;
+ struct Collection *collision_group;
struct EffectorWeights *effector_weights;
/* reverse esimated obmatrix .. no need to store in blend file .. how ever who cares */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 5139e54b577..64c67f7d325 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -263,7 +263,7 @@ typedef struct Object {
struct PartDeflect *pd; /* particle deflector/attractor/collision data */
struct SoftBody *soft; /* if exists, saved in file */
- struct Group *dup_group; /* object duplicator for group */
+ struct Collection *dup_group; /* object duplicator for group */
void *pad10;
char pad4;
@@ -423,7 +423,7 @@ enum {
OB_DUPLIROT = 1 << 5,
OB_DUPLINOSPEED = 1 << 6,
OB_DUPLICALCDERIVED = 1 << 7, /* runtime, calculate derivedmesh for dupli before it's used */
- OB_DUPLIGROUP = 1 << 8,
+ OB_DUPLICOLLECTION = 1 << 8,
OB_DUPLIFACES = 1 << 9,
OB_DUPLIFACES_SCALE = 1 << 10,
OB_DUPLIPARTS = 1 << 11,
@@ -431,7 +431,7 @@ enum {
OB_NO_CONSTRAINTS = 1 << 13, /* runtime constraints disable */
OB_NO_PSYS_UPDATE = 1 << 14, /* hack to work around particle issue */
- OB_DUPLI = OB_DUPLIFRAMES | OB_DUPLIVERTS | OB_DUPLIGROUP | OB_DUPLIFACES | OB_DUPLIPARTS,
+ OB_DUPLI = OB_DUPLIFRAMES | OB_DUPLIVERTS | OB_DUPLICOLLECTION | OB_DUPLIFACES | OB_DUPLIPARTS,
};
/* (short) trackflag / upflag */
@@ -525,7 +525,7 @@ enum {
#define OB_FROMDUPLI (1 << 9)
#define OB_DONE (1 << 10) /* unknown state, clear before use */
/* #define OB_RADIO (1 << 11) */ /* deprecated */
-#define OB_FROMGROUP (1 << 12)
+/* #define OB_FROMGROUP (1 << 12) */ /* deprecated */
/* WARNING - when adding flags check on PSYS_RECALC */
/* ob->recalc (flag bits!) */
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index b968bcebeb5..d775061d85a 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -103,8 +103,8 @@ enum {
#define TSE_ID_BASE 36 /* NO ID */
#define TSE_GP_LAYER 37 /* NO ID */
#define TSE_LAYER_COLLECTION 38
-#define TSE_SCENE_COLLECTION 39
-#define TSE_LAYER_COLLECTION_BASE 40
+#define TSE_SCENE_COLLECTION_BASE 39
+#define TSE_VIEW_COLLECTION_BASE 40
#define TSE_SCENE_OBJECTS_BASE 41
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 70afef9b874..583b8504524 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -160,7 +160,7 @@ typedef struct ParticleSettings {
struct SPHFluidSettings *fluid;
struct EffectorWeights *effector_weights;
- struct Group *collision_group;
+ struct Collection *collision_group;
int flag, rt;
short type, from, distr, texact;
@@ -244,9 +244,9 @@ typedef struct ParticleSettings {
struct MTex *mtex[18]; /* MAX_MTEX */
- struct Group *dup_group;
+ struct Collection *dup_group;
struct ListBase dupliweights;
- struct Group *eff_group DNA_DEPRECATED; // deprecated
+ struct Collection *eff_group DNA_DEPRECATED; // deprecated
struct Object *dup_ob;
struct Object *bb_ob;
struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */
diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h
index 381ee5d40e5..42286044970 100644
--- a/source/blender/makesdna/DNA_rigidbody_types.h
+++ b/source/blender/makesdna/DNA_rigidbody_types.h
@@ -35,7 +35,7 @@
#include "DNA_listBase.h"
-struct Group;
+struct Collection;
struct EffectorWeights;
@@ -50,10 +50,10 @@ typedef struct RigidBodyWorld {
/* Sim World Settings ------------------------------------------------------------- */
struct EffectorWeights *effector_weights; /* effectors info */
- struct Group *group; /* Group containing objects to use for Rigid Bodies */
+ struct Collection *group; /* Group containing objects to use for Rigid Bodies */
struct Object **objects; /* Array to access group objects by index, only used at runtime */
- struct Group *constraints; /* Group containing objects to use for Rigid Body Constraints*/
+ struct Collection *constraints; /* Group containing objects to use for Rigid Body Constraints*/
int pad;
float ltime; /* last frame world was evaluated for (internal) */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 7e2abf3ddc0..7b717107df1 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -47,6 +47,7 @@ extern "C" {
#include "DNA_ID.h"
#include "DNA_freestyle_types.h"
#include "DNA_gpu_types.h"
+#include "DNA_group_types.h"
#include "DNA_layer_types.h"
#include "DNA_material_types.h"
#include "DNA_userdef_types.h"
@@ -58,7 +59,7 @@ struct Brush;
struct World;
struct Scene;
struct Image;
-struct Group;
+struct Collection;
struct Text;
struct bNodeTree;
struct AnimData;
@@ -1510,7 +1511,9 @@ typedef struct Scene {
struct PreviewImage *preview;
ListBase view_layers;
- struct SceneCollection *collection;
+ /* Not an actual datablock, but memory owned by scene. */
+ Collection *master_collection;
+ struct SceneCollection *collection DNA_DEPRECATED;
IDProperty *layer_properties; /* settings to be override by workspaces */
diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h
index c1565bde882..47f73c6ac22 100644
--- a/source/blender/makesdna/DNA_smoke_types.h
+++ b/source/blender/makesdna/DNA_smoke_types.h
@@ -129,9 +129,9 @@ typedef struct SmokeDomainSettings {
struct SmokeModifierData *smd; /* for fast RNA access */
struct FLUID_3D *fluid;
void *fluid_mutex;
- struct Group *fluid_group;
- struct Group *eff_group; // UNUSED
- struct Group *coll_group; // collision objects group
+ struct Collection *fluid_group;
+ struct Collection *eff_group; // UNUSED
+ struct Collection *coll_group; // collision objects group
struct WTURBULENCE *wt; // WTURBULENCE object, if active
struct GPUTexture *tex;
struct GPUTexture *tex_wt;
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index d24aec739e1..588d90fae8d 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -185,7 +185,6 @@ typedef enum eSpaceButtons_Context {
BCONTEXT_CONSTRAINT = 11,
BCONTEXT_BONE_CONSTRAINT = 12,
BCONTEXT_VIEW_LAYER = 13,
- BCONTEXT_COLLECTION = 14,
BCONTEXT_WORKSPACE = 15,
/* always as last... */
@@ -202,12 +201,6 @@ typedef enum eSpaceButtons_Flag {
SB_SHADING_CONTEXT = (1 << 4),
} eSpaceButtons_Flag;
-/* sbuts->collection_context */
-typedef enum eSpaceButtons_Collection_Context {
- SB_COLLECTION_CTX_VIEW_LAYER = 0,
- SB_COLLECTION_CTX_GROUP = 1,
-} eSpaceButtons_Collection_Context;
-
/* sbuts->align */
typedef enum eSpaceButtons_Align {
BUT_FREE = 0,
@@ -281,7 +274,7 @@ typedef enum eSpaceOutliner_Flag {
typedef enum eSpaceOutliner_Filter {
SO_FILTER_SEARCH = (1 << 0),
/* SO_FILTER_ENABLE = (1 << 1), */ /* Deprecated */
- /* SO_FILTER_NO_OBJECT = (1 << 2), */ /* Deprecated */
+ SO_FILTER_NO_OBJECT = (1 << 2),
SO_FILTER_NO_OB_CONTENT = (1 << 3), /* Not only mesh, but modifiers, constraints, ... */
SO_FILTER_NO_CHILDREN = (1 << 4),
@@ -325,27 +318,26 @@ typedef enum eSpaceOutliner_StateFilter {
SO_FILTER_OB_VISIBLE = 1,
SO_FILTER_OB_SELECTED = 2,
SO_FILTER_OB_ACTIVE = 3,
- SO_FILTER_OB_NONE = 4,
} eSpaceOutliner_StateFilter;
/* SpaceOops->outlinevis */
typedef enum eSpaceOutliner_Mode {
- SO_SCENES = 0,
+ SO_SCENES = 0,
/* SO_CUR_SCENE = 1, */ /* deprecated! */
/* SO_VISIBLE = 2, */ /* deprecated! */
/* SO_SELECTED = 3, */ /* deprecated! */
/* SO_ACTIVE = 4, */ /* deprecated! */
/* SO_SAME_TYPE = 5, */ /* deprecated! */
- SO_GROUPS = 6,
- SO_LIBRARIES = 7,
+ /* SO_GROUPS = 6, */ /* deprecated! */
+ SO_LIBRARIES = 7,
/* SO_VERSE_SESSION = 8, */ /* deprecated! */
/* SO_VERSE_MS = 9, */ /* deprecated! */
- SO_SEQUENCE = 10,
- SO_DATA_API = 11,
+ SO_SEQUENCE = 10,
+ SO_DATA_API = 11,
/* SO_USERDEF = 12, */ /* deprecated! */
- /* SO_KEYMAP = 13, */ /* deprecated! */
- SO_ID_ORPHANS = 14,
- SO_COLLECTIONS = 15,
+ /* SO_KEYMAP = 13, */ /* deprecated! */
+ SO_ID_ORPHANS = 14,
+ SO_VIEW_LAYER = 15,
} eSpaceOutliner_Mode;
/* SpaceOops->storeflag */
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index c9385f98584..9c44d60b7c2 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -476,9 +476,16 @@ static bool init_structDNA(
/* this is a patch, to change struct names without a conflict with SDNA */
/* be careful to use it, in this case for a system-struct (opengl/X) */
- if (*cp == 'b') {
- /* struct Screen was already used by X, 'bScreen' replaces the old IrisGL 'Screen' struct */
- if (strcmp("bScreen", cp) == 0) sdna->types[nr] = cp + 1;
+ /* struct Screen was already used by X, 'bScreen' replaces the old IrisGL 'Screen' struct */
+ if (strcmp("bScreen", cp) == 0) {
+ sdna->types[nr] = cp + 1;
+ }
+ /* Groups renamed to collections in 2.8 */
+ else if (strcmp("Collection", cp) == 0) {
+ sdna->types[nr] = "Group";
+ }
+ else if (strcmp("CollectionObject", cp) == 0) {
+ sdna->types[nr] = "GroupObject";
}
else if (doversion_280) {
if (strcmp(cp, "SceneLayer") == 0) {
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 0461389ce21..4744b2e33df 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -109,6 +109,7 @@ extern StructRNA RNA_ClothCollisionSettings;
extern StructRNA RNA_ClothModifier;
extern StructRNA RNA_ClothSettings;
extern StructRNA RNA_CloudsTexture;
+extern StructRNA RNA_Collection;
extern StructRNA RNA_CollectionEngineSettings;
extern StructRNA RNA_CollectionProperty;
extern StructRNA RNA_CollisionModifier;
@@ -279,7 +280,6 @@ extern StructRNA RNA_GPencilSculptBrush;
extern StructRNA RNA_GaussianBlurSequence;
extern StructRNA RNA_GlowSequence;
extern StructRNA RNA_GreasePencil;
-extern StructRNA RNA_Group;
extern StructRNA RNA_Header;
extern StructRNA RNA_HemiLamp;
extern StructRNA RNA_Histogram;
@@ -504,9 +504,9 @@ extern StructRNA RNA_RigidBodyJointConstraint;
extern StructRNA RNA_SPHFluidSettings;
extern StructRNA RNA_Scene;
extern StructRNA RNA_SceneEEVEE;
+extern StructRNA RNA_SceneObjects;
extern StructRNA RNA_SceneRenderLayer;
extern StructRNA RNA_SceneSequence;
-extern StructRNA RNA_SceneObjects;
extern StructRNA RNA_Scopes;
extern StructRNA RNA_Screen;
extern StructRNA RNA_ScrewModifier;
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 6ebdb845b03..bb09fe585ba 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -63,9 +63,6 @@ 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[];
extern const EnumPropertyItem rna_enum_modifier_triangulate_ngon_method_items[];
@@ -236,8 +233,8 @@ const EnumPropertyItem *rna_Actuator_type_itemf(struct bContext *C, struct Point
* in the linked list can add more for different types as needed */
const EnumPropertyItem *RNA_action_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
// EnumPropertyItem *RNA_action_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
-const EnumPropertyItem *RNA_group_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
-const EnumPropertyItem *RNA_group_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
+const EnumPropertyItem *RNA_collection_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
+const EnumPropertyItem *RNA_collection_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
const EnumPropertyItem *RNA_image_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
const EnumPropertyItem *RNA_image_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
const EnumPropertyItem *RNA_scene_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 4daf8b6a965..183db621642 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -905,7 +905,7 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr
}
else {
PointerPropertyRNA *pprop = (PointerPropertyRNA *)dp->prop;
- StructRNA *type = rna_find_struct((const char *)pprop->type);
+ StructRNA *type = (pprop->type) ? rna_find_struct((const char *)pprop->type) : NULL;
if (type && (type->flag & STRUCT_ID)) {
fprintf(f, " if (value.data)\n");
fprintf(f, " id_lib_extern((ID *)value.data);\n\n");
@@ -2458,12 +2458,24 @@ static void rna_auto_types(void)
for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) {
/* DNA name for Screen is patched in 2.5, we do the reverse here .. */
- if (ds->dnaname && STREQ(ds->dnaname, "Screen"))
- ds->dnaname = "bScreen";
+ if (ds->dnaname) {
+ if (STREQ(ds->dnaname, "Screen"))
+ ds->dnaname = "bScreen";
+ if (STREQ(ds->dnaname, "Group"))
+ ds->dnaname = "Collection";
+ if (STREQ(ds->dnaname, "GroupObject"))
+ ds->dnaname = "CollectionObject";
+ }
for (dp = ds->cont.properties.first; dp; dp = dp->next) {
- if (dp->dnastructname && STREQ(dp->dnastructname, "Screen"))
- dp->dnastructname = "bScreen";
+ if (dp->dnastructname) {
+ if (STREQ(dp->dnastructname, "Screen"))
+ dp->dnastructname = "bScreen";
+ if (STREQ(dp->dnastructname, "Group"))
+ dp->dnastructname = "Collection";
+ if (STREQ(dp->dnastructname, "GroupObject"))
+ dp->dnastructname = "CollectionObject";
+ }
if (dp->dnatype) {
if (dp->prop->type == PROP_POINTER) {
@@ -3368,7 +3380,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_fcurve.c", "rna_fcurve_api.c", RNA_def_fcurve},
{"rna_fluidsim.c", NULL, RNA_def_fluidsim},
{"rna_gpencil.c", NULL, RNA_def_gpencil},
- {"rna_group.c", NULL, RNA_def_group},
+ {"rna_group.c", NULL, RNA_def_collections},
{"rna_image.c", "rna_image_api.c", RNA_def_image},
{"rna_key.c", NULL, RNA_def_key},
{"rna_lamp.c", NULL, RNA_def_lamp},
@@ -3726,7 +3738,7 @@ static const char *cpp_classes = ""
" COLLECTION_PROPERTY_LENGTH_##has_length(sname, identifier) \\\n"
" COLLECTION_PROPERTY_LOOKUP_INT_##has_lookup_int(sname, identifier) \\\n"
" COLLECTION_PROPERTY_LOOKUP_STRING_##has_lookup_string(sname, identifier) \\\n"
-" Collection<sname, type, sname##_##identifier##_begin, \\\n"
+" CollectionRef<sname, type, sname##_##identifier##_begin, \\\n"
" sname##_##identifier##_next, sname##_##identifier##_end, \\\n"
" sname##_##identifier##_length_wrap, \\\n"
" sname##_##identifier##_lookup_int_wrap, sname##_##identifier##_lookup_string_wrap, collection_funcs> identifier;\n"
@@ -3823,9 +3835,9 @@ static const char *cpp_classes = ""
"template<typename Tp, typename T, TBeginFunc Tbegin, TNextFunc Tnext, TEndFunc Tend,\n"
" TLengthFunc Tlength, TLookupIntFunc Tlookup_int, TLookupStringFunc Tlookup_string,\n"
" typename Tcollection_funcs>\n"
-"class Collection : public Tcollection_funcs {\n"
+"class CollectionRef : public Tcollection_funcs {\n"
"public:\n"
-" Collection(const PointerRNA &p) : Tcollection_funcs(p), ptr(p) {}\n"
+" CollectionRef(const PointerRNA &p) : Tcollection_funcs(p), ptr(p) {}\n"
"\n"
" void begin(CollectionIterator<T, Tbegin, Tnext, Tend>& iter)\n"
" { iter.begin(ptr); }\n"
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 5143a39db92..952d27fa18d 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -58,7 +58,7 @@ const EnumPropertyItem rna_enum_id_type_items[] = {
{ID_CU, "CURVE", ICON_CURVE_DATA, "Curve", ""},
{ID_VF, "FONT", ICON_FONT_DATA, "Font", ""},
{ID_GD, "GREASEPENCIL", ICON_GREASEPENCIL, "Grease Pencil", ""},
- {ID_GR, "GROUP", ICON_GROUP, "Group", ""},
+ {ID_GR, "COLLECTION", ICON_GROUP, "Collection", ""},
{ID_IM, "IMAGE", ICON_IMAGE_DATA, "Image", ""},
{ID_KE, "KEY", ICON_SHAPEKEY_DATA, "Key", ""},
{ID_LA, "LAMP", ICON_LAMP_DATA, "Lamp", ""},
@@ -179,7 +179,7 @@ short RNA_type_to_ID_code(const StructRNA *type)
if (base_type == &RNA_Camera) return ID_CA;
if (base_type == &RNA_Curve) return ID_CU;
if (base_type == &RNA_GreasePencil) return ID_GD;
- if (base_type == &RNA_Group) return ID_GR;
+ if (base_type == &RNA_Collection) return ID_GR;
if (base_type == &RNA_Image) return ID_IM;
if (base_type == &RNA_Key) return ID_KE;
if (base_type == &RNA_Lamp) return ID_LA;
@@ -223,7 +223,7 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_CF: return &RNA_CacheFile;
case ID_CU: return &RNA_Curve;
case ID_GD: return &RNA_GreasePencil;
- case ID_GR: return &RNA_Group;
+ case ID_GR: return &RNA_Collection;
case ID_IM: return &RNA_Image;
case ID_KE: return &RNA_Key;
case ID_LA: return &RNA_Lamp;
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index d398ce95a52..b06038a50e4 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -325,18 +325,18 @@ static void rna_def_dopesheet(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_HELP, 0); /* XXX: this doesn't quite fit */
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- /* Object Group Filtering Settings */
- prop = RNA_def_property(srna, "show_only_group_objects", PROP_BOOLEAN, PROP_NONE);
+ /* Object Collection Filtering Settings */
+ prop = RNA_def_property(srna, "show_only_collection_objects", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_ONLYOBGROUP);
- RNA_def_property_ui_text(prop, "Only Objects in Group",
- "Only include channels from objects in the specified group");
+ RNA_def_property_ui_text(prop, "Only Objects in Collection",
+ "Only include channels from objects in the specified collection");
RNA_def_property_ui_icon(prop, ICON_GROUP, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- prop = RNA_def_property(srna, "filter_group", PROP_POINTER, PROP_NONE);
+ prop = RNA_def_property(srna, "filter_collection", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "filter_grp");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Filtering Group", "Group that included object should be a member of");
+ RNA_def_property_ui_text(prop, "Filtering Collection", "Collection that included object should be a member of");
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
/* FCurve Display Name Search Settings */
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index c8d7cb1fcdc..706dc6a3cd7 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -171,11 +171,10 @@ static int rna_Context_engine_length(PointerRNA *ptr)
return strlen(engine_type->idname);
}
-static PointerRNA rna_Context_scene_collection_get(PointerRNA *ptr)
+static PointerRNA rna_Context_collection_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
- ptr->id.data = CTX_data_scene(C);
- return rna_pointer_inherit_refine(ptr, &RNA_SceneCollection, CTX_data_scene_collection(C));
+ return rna_pointer_inherit_refine(ptr, &RNA_Collection, CTX_data_collection(C));
}
static PointerRNA rna_Context_layer_collection_get(PointerRNA *ptr)
@@ -287,10 +286,10 @@ void RNA_def_context(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_string_funcs(prop, "rna_Context_engine_get", "rna_Context_engine_length", NULL);
- prop = RNA_def_property(srna, "scene_collection", PROP_POINTER, PROP_NONE);
+ prop = RNA_def_property(srna, "collection", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_struct_type(prop, "SceneCollection");
- RNA_def_property_pointer_funcs(prop, "rna_Context_scene_collection_get", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "Collection");
+ RNA_def_property_pointer_funcs(prop, "rna_Context_collection_get", NULL, NULL, NULL);
prop = RNA_def_property(srna, "layer_collection", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index aeb845ddcf7..0358efff266 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -425,9 +425,9 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_struct_name_property(srna, prop);
prop = RNA_def_property(srna, "brush_group", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Brush Group", "Only use brush objects from this group");
+ RNA_def_property_ui_text(prop, "Brush Collection", "Only use brush objects from this collection");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_reset_dependency");
diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c
index bf64bb1181f..0f62d8d20d8 100644
--- a/source/blender/makesrna/intern/rna_group.c
+++ b/source/blender/makesrna/intern/rna_group.c
@@ -41,11 +41,21 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "BKE_group.h"
+#include "DEG_depsgraph.h"
+
+#include "BKE_collection.h"
+#include "BKE_layer.h"
#include "WM_api.h"
-static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter)
+static void rna_Collection_all_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Collection *collection = (Collection *)ptr->data;
+ ListBase collection_objects = BKE_collection_object_cache_get(collection);
+ rna_iterator_listbase_begin(iter, &collection_objects, NULL);
+}
+
+static PointerRNA rna_Collection_all_objects_get(CollectionPropertyIterator *iter)
{
ListBaseIterator *internal = &iter->internal.listbase;
@@ -54,89 +64,209 @@ static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter)
return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object);
}
-static void rna_Group_objects_link(Group *group, ReportList *reports, Object *object)
+static void rna_Collection_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Collection *collection = (Collection *)ptr->data;
+ rna_iterator_listbase_begin(iter, &collection->gobject, NULL);
+}
+
+static PointerRNA rna_Collection_objects_get(CollectionPropertyIterator *iter)
{
- if (!BKE_group_object_add(group, object)) {
- BKE_reportf(reports, RPT_ERROR, "Object '%s' already in group '%s'", object->id.name + 2, group->id.name + 2);
+ ListBaseIterator *internal = &iter->internal.listbase;
+
+ /* we are actually iterating a ObjectBase list, so override get */
+ CollectionObject *cob = (CollectionObject *)internal->link;
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, cob->ob);
+}
+
+static void rna_Collection_objects_link(Collection *collection, Main *bmain, ReportList *reports, Object *object)
+{
+ if (!BKE_collection_object_add(bmain, collection, object)) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' already in collection '%s'", object->id.name + 2, collection->id.name + 2);
return;
}
WM_main_add_notifier(NC_OBJECT | ND_DRAW, &object->id);
}
-static void rna_Group_objects_unlink(Group *group, ReportList *reports, Object *object)
+static void rna_Collection_objects_unlink(Collection *collection, Main *bmain, ReportList *reports, Object *object)
{
- if (!BKE_group_object_unlink(group, object)) {
- BKE_reportf(reports, RPT_ERROR, "Object '%s' not in group '%s'", object->id.name + 2, group->id.name + 2);
+ if (!BKE_collection_object_remove(bmain, collection, object, false)) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' not in collection '%s'", object->id.name + 2, collection->id.name + 2);
return;
}
WM_main_add_notifier(NC_OBJECT | ND_DRAW, &object->id);
}
+static void rna_Collection_children_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Collection *collection = (Collection *)ptr->data;
+ rna_iterator_listbase_begin(iter, &collection->children, NULL);
+}
+
+static PointerRNA rna_Collection_children_get(CollectionPropertyIterator *iter)
+{
+ ListBaseIterator *internal = &iter->internal.listbase;
+
+ /* we are actually iterating a CollectionBase list, so override get */
+ CollectionChild *child = (CollectionChild *)internal->link;
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_Collection, child->collection);
+}
+
+static void rna_Collection_children_link(Collection *collection, Main *bmain, ReportList *reports, Collection *child)
+{
+ if (!BKE_collection_child_add(bmain, collection, child)) {
+ BKE_reportf(reports, RPT_ERROR, "Collection '%s' already in collection '%s'", child->id.name + 2, collection->id.name + 2);
+ return;
+ }
+
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, &child->id);
+}
+
+static void rna_Collection_children_unlink(Collection *collection, Main *bmain, ReportList *reports, Collection *child)
+{
+ if (!BKE_collection_child_remove(bmain, collection, child)) {
+ BKE_reportf(reports, RPT_ERROR, "Collection '%s' not in collection '%s'", child->id.name + 2, collection->id.name + 2);
+ return;
+ }
+
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, &child->id);
+}
+
+static void rna_Collection_flag_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Collection *collection = (Collection *)ptr->data;
+ BKE_collection_object_cache_free(collection);
+ BKE_main_collection_sync(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
+}
+
#else
-/* group.objects */
-static void rna_def_group_objects(BlenderRNA *brna, PropertyRNA *cprop)
+/* collection.objects */
+static void rna_def_collection_objects(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
-/* PropertyRNA *prop; */
-
FunctionRNA *func;
PropertyRNA *parm;
- RNA_def_property_srna(cprop, "GroupObjects");
- srna = RNA_def_struct(brna, "GroupObjects", NULL);
- RNA_def_struct_sdna(srna, "Group");
- RNA_def_struct_ui_text(srna, "Group Objects", "Collection of group objects");
+ RNA_def_property_srna(cprop, "CollectionObjects");
+ srna = RNA_def_struct(brna, "CollectionObjects", NULL);
+ RNA_def_struct_sdna(srna, "Collection");
+ RNA_def_struct_ui_text(srna, "Collection Objects", "Collection of collection objects");
/* add object */
- func = RNA_def_function(srna, "link", "rna_Group_objects_link");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- RNA_def_function_ui_description(func, "Add this object to a group");
- /* object to add */
+ func = RNA_def_function(srna, "link", "rna_Collection_objects_link");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN);
+ RNA_def_function_ui_description(func, "Add this object to a collection");
parm = RNA_def_pointer(func, "object", "Object", "", "Object to add");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
/* remove object */
- func = RNA_def_function(srna, "unlink", "rna_Group_objects_unlink");
- RNA_def_function_ui_description(func, "Remove this object to a group");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- /* object to remove */
+ func = RNA_def_function(srna, "unlink", "rna_Collection_objects_unlink");
+ RNA_def_function_ui_description(func, "Remove this object from a collection");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN);
parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
}
+/* collection.children */
+static void rna_def_collection_children(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
-void RNA_def_group(BlenderRNA *brna)
+ RNA_def_property_srna(cprop, "CollectionChildren");
+ srna = RNA_def_struct(brna, "CollectionChildren", NULL);
+ RNA_def_struct_sdna(srna, "Collection");
+ RNA_def_struct_ui_text(srna, "Collection Children", "Collection of child collections");
+
+ /* add child */
+ func = RNA_def_function(srna, "link", "rna_Collection_children_link");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN);
+ RNA_def_function_ui_description(func, "Add this collection as child of this collection");
+ parm = RNA_def_pointer(func, "child", "Collection", "", "Collection to add");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+
+ /* remove child */
+ func = RNA_def_function(srna, "unlink", "rna_Collection_children_unlink");
+ RNA_def_function_ui_description(func, "Remove this child collection from a collection");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "child", "Collection", "", "Collection to remove");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+}
+
+
+void RNA_def_collections(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- srna = RNA_def_struct(brna, "Group", "ID");
- RNA_def_struct_ui_text(srna, "Group", "Group of Object data-blocks");
+ srna = RNA_def_struct(brna, "Collection", "ID");
+ RNA_def_struct_sdna(srna, "Group"); /* it is actually Collection but for 2.8 the dna is patched! */
+ RNA_def_struct_ui_text(srna, "Collection", "Collection of Object data-blocks");
RNA_def_struct_ui_icon(srna, ICON_GROUP);
- /* this is done on save/load in readfile.c, removed if no objects are in the group */
+ /* this is done on save/load in readfile.c, removed if no objects are in the collection and not in a scene */
RNA_def_struct_clear_flag(srna, STRUCT_ID_REFCOUNT);
prop = RNA_def_property(srna, "dupli_offset", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_float_sdna(prop, NULL, "dupli_ofs");
- RNA_def_property_ui_text(prop, "Dupli Offset", "Offset from the origin to use when instancing as DupliGroup");
+ RNA_def_property_ui_text(prop, "Dupli Offset", "Offset from the origin to use when instancing");
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, "objects", PROP_COLLECTION, PROP_NONE);
- 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, "view_layer", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "ViewLayer");
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "View Layer", "Group internal view layer");
+ RNA_def_property_ui_text(prop, "Objects", "Objects that are directly in this collection");
+ RNA_def_property_collection_funcs(prop, "rna_Collection_objects_begin",
+ "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end",
+ "rna_Collection_objects_get",
+ NULL, NULL, NULL, NULL);
+ rna_def_collection_objects(brna, prop);
+
+ prop = RNA_def_property(srna, "all_objects", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_ui_text(prop, "All Objects", "Objects that are in this collection and its child collections");
+ RNA_def_property_collection_funcs(prop, "rna_Collection_all_objects_begin",
+ "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end",
+ "rna_Collection_all_objects_get",
+ NULL, NULL, NULL, NULL);
+
+ prop = RNA_def_property(srna, "children", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Collection");
+ RNA_def_property_ui_text(prop, "Children", "Collections that are immediate children of this collection");
+ RNA_def_property_collection_funcs(prop, "rna_Collection_children_begin",
+ "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end",
+ "rna_Collection_children_get",
+ NULL, NULL, NULL, NULL);
+ rna_def_collection_children(brna, prop);
+
+ /* Flags */
+ prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_SELECT);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 1);
+ RNA_def_property_ui_text(prop, "Restrict Select", "Disable collection object selection in the 3D viewport");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
+
+ prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_VIEW);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1);
+ RNA_def_property_ui_text(prop, "Restrict Viewport", "Hide collection objects in the 3D viewport");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
+
+ prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_RENDER);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
+ RNA_def_property_ui_text(prop, "Restrict Render", "Hide collection objects in renders");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
}
#endif
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index ce16cb69bbd..a1b4e0a7006 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -142,6 +142,7 @@ void RNA_def_brush(struct BlenderRNA *brna);
void RNA_def_cachefile(struct BlenderRNA *brna);
void RNA_def_camera(struct BlenderRNA *brna);
void RNA_def_cloth(struct BlenderRNA *brna);
+void RNA_def_collections(struct BlenderRNA *brna);
void RNA_def_color(struct BlenderRNA *brna);
void RNA_def_constraint(struct BlenderRNA *brna);
void RNA_def_context(struct BlenderRNA *brna);
@@ -152,7 +153,6 @@ void RNA_def_dynamic_paint(struct BlenderRNA *brna);
void RNA_def_fluidsim(struct BlenderRNA *brna);
void RNA_def_fcurve(struct BlenderRNA *brna);
void RNA_def_gpencil(struct BlenderRNA *brna);
-void RNA_def_group(struct BlenderRNA *brna);
void RNA_def_image(struct BlenderRNA *brna);
void RNA_def_key(struct BlenderRNA *brna);
void RNA_def_lamp(struct BlenderRNA *brna);
@@ -364,7 +364,7 @@ void RNA_def_main_fonts(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_textures(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_brushes(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_worlds(BlenderRNA *brna, PropertyRNA *cprop);
-void RNA_def_main_groups(BlenderRNA *brna, PropertyRNA *cprop);
+void RNA_def_main_collections(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_texts(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_speakers(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop);
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
index e6e90f4f05d..61bf5ceab8e 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -47,12 +47,6 @@
#include "rna_internal.h"
-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"
@@ -69,324 +63,13 @@ const EnumPropertyItem rna_enum_collection_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;
- SceneCollection *sc = (SceneCollection *)ptr->data;
- BKE_collection_rename(&scene->id, sc, value);
-}
-
-static PointerRNA rna_SceneCollection_objects_get(CollectionPropertyIterator *iter)
-{
- ListBaseIterator *internal = &iter->internal.listbase;
-
- /* we are actually iterating a LinkData list */
- return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((LinkData *)internal->link)->data);
-}
-
-static int rna_SceneCollection_move_above(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst)
-{
- if (!BKE_collection_move_above(id, sc_dst, sc_src)) {
- return 0;
- }
-
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-
- return 1;
-}
-
-static int rna_SceneCollection_move_below(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst)
-{
- if (!BKE_collection_move_below(id, sc_dst, sc_src)) {
- return 0;
- }
-
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-
- return 1;
-}
-
-static int rna_SceneCollection_move_into(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst)
-{
- if (!BKE_collection_move_into(id, sc_dst, sc_src)) {
- return 0;
- }
-
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-
- return 1;
-}
-
-static SceneCollection *rna_SceneCollection_duplicate(
- ID *id, SceneCollection *scene_collection, Main *bmain, bContext *C, ReportList *reports)
-{
- if (scene_collection == BKE_collection_master(id)) {
- BKE_report(reports, RPT_ERROR, "The master collection can't be duplicated");
- return NULL;
- }
-
- SceneCollection *scene_collection_new = BKE_collection_duplicate(id, scene_collection);
-
- DEG_relations_tag_update(bmain);
- /* Don't use id here, since the layer collection may come from a group. */
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, CTX_data_scene(C));
-
- return scene_collection_new;
-}
-
-static SceneCollection *rna_SceneCollection_new(
- ID *id, SceneCollection *sc_parent, Main *bmain, const char *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);
-
- return sc;
-}
-
-static void rna_SceneCollection_remove(
- ID *id, SceneCollection *sc_parent, Main *bmain, ReportList *reports, PointerRNA *sc_ptr)
-{
- SceneCollection *sc = sc_ptr->data;
-
- const int index = BLI_findindex(&sc_parent->scene_collections, sc);
- if (index == -1) {
- BKE_reportf(reports, RPT_ERROR, "Collection '%s' is not a sub-collection of '%s'",
- sc->name, sc_parent->name);
- return;
- }
-
- 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;
- }
-
- RNA_POINTER_INVALIDATE(sc_ptr);
-
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-}
-
-static int rna_SceneCollection_objects_active_index_get(PointerRNA *ptr)
-{
- SceneCollection *sc = (SceneCollection *)ptr->data;
- return sc->active_object_index;
-}
-
-static void rna_SceneCollection_objects_active_index_set(PointerRNA *ptr, int value)
-{
- SceneCollection *sc = (SceneCollection *)ptr->data;
- sc->active_object_index = value;
-}
-
-static void rna_SceneCollection_objects_active_index_range(
- PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
-{
- SceneCollection *sc = (SceneCollection *)ptr->data;
- *min = 0;
- *max = max_ii(0, BLI_listbase_count(&sc->objects) - 1);
-}
-
-void rna_SceneCollection_object_link(
- ID *id, SceneCollection *sc, Main *bmain, ReportList *reports, Object *ob)
-{
- Scene *scene = (Scene *)id;
-
- if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
- BKE_reportf(reports, RPT_ERROR, "Object '%s' is already in collection '%s'", ob->id.name + 2, sc->name);
- return;
- }
-
- BKE_collection_object_add(&scene->id, sc, ob);
-
- /* TODO(sergey): Only update relations for the current scene. */
- DEG_relations_tag_update(bmain);
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
-
- DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
-}
-
-static void rna_SceneCollection_object_unlink(
- ID *id, SceneCollection *sc, Main *bmain, ReportList *reports, Object *ob)
-{
- Scene *scene = (Scene *)id;
-
- if (!BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
- BKE_reportf(reports, RPT_ERROR, "Object '%s' is not in collection '%s'", ob->id.name + 2, sc->name);
- return;
- }
-
- 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);
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
-}
-
/***********************************/
-static void rna_LayerCollection_name_get(PointerRNA *ptr, char *value)
-{
- SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection;
- strcpy(value, sc->name);
-}
-
-static int rna_LayerCollection_name_length(PointerRNA *ptr)
-{
- SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection;
- return strnlen(sc->name, sizeof(sc->name));
-}
-
-static void rna_LayerCollection_name_set(PointerRNA *ptr, const char *value)
-{
- ID *owner_id = (ID *)ptr->id.data;
- SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection;
- BKE_collection_rename(owner_id, sc, value);
-}
-
-static PointerRNA rna_LayerCollection_objects_get(CollectionPropertyIterator *iter)
-{
- ListBaseIterator *internal = &iter->internal.listbase;
- Base *base = ((LinkData *)internal->link)->data;
- return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object);
-}
-
-static int rna_LayerCollection_move_above(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst)
-{
- if (!BKE_layer_collection_move_above(id, lc_dst, lc_src)) {
- return 0;
- }
-
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-
- return 1;
-}
-
-static int rna_LayerCollection_move_below(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst)
-{
- if (!BKE_layer_collection_move_below(id, lc_dst, lc_src)) {
- return 0;
- }
-
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-
- return 1;
-}
-
-static int rna_LayerCollection_move_into(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst)
-{
- if (!BKE_layer_collection_move_into(id, lc_dst, lc_src)) {
- return 0;
- }
-
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-
- return 1;
-}
-
-static void rna_LayerCollection_flag_update(bContext *C, PointerRNA *ptr)
-{
- ID *id = ptr->id.data;
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
-}
-
-static Group *rna_LayerCollection_create_group(
- ID *id, LayerCollection *layer_collection, Main *bmain, bContext *C, ReportList *reports)
-{
- Group *group;
- Scene *scene = (Scene *)id;
- SceneCollection *scene_collection = layer_collection->scene_collection;
-
- /* The master collection can't be converted. */
- if (scene_collection == BKE_collection_master(&scene->id)) {
- BKE_report(reports, RPT_ERROR, "The master collection can't be converted to group");
- return NULL;
- }
-
- group = BKE_collection_group_create(bmain, scene, layer_collection);
- if (group == NULL) {
- BKE_reportf(reports, RPT_ERROR, "Failed to convert collection %s", scene_collection->name);
- return NULL;
- }
-
- DEG_relations_tag_update(bmain);
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- return group;
-}
-
-static LayerCollection *rna_LayerCollection_duplicate(
- ID *id, LayerCollection *layer_collection, Main *bmain, bContext *C, ReportList *reports)
-{
- if (layer_collection->scene_collection == BKE_collection_master(id)) {
- BKE_report(reports, RPT_ERROR, "The master collection can't be duplicated");
- return NULL;
- }
-
- LayerCollection *layer_collection_new = BKE_layer_collection_duplicate(id, layer_collection);
-
- DEG_relations_tag_update(bmain);
- /* Don't use id here, since the layer collection may come from a group. */
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, CTX_data_scene(C));
-
- return layer_collection_new;
-}
-
-static int rna_LayerCollections_active_collection_index_get(PointerRNA *ptr)
-{
- ViewLayer *view_layer = (ViewLayer *)ptr->data;
- return view_layer->active_collection;
-}
-
-static void rna_LayerCollections_active_collection_index_set(PointerRNA *ptr, int value)
-{
- ViewLayer *view_layer = (ViewLayer *)ptr->data;
- int num_collections = BKE_layer_collection_count(view_layer);
- view_layer->active_collection = min_ff(value, num_collections - 1);
-}
-
-static void rna_LayerCollections_active_collection_index_range(
- PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
-{
- ViewLayer *view_layer = (ViewLayer *)ptr->data;
- *min = 0;
- *max = max_ii(0, BKE_layer_collection_count(view_layer) - 1);
-}
static PointerRNA rna_LayerCollections_active_collection_get(PointerRNA *ptr)
{
ViewLayer *view_layer = (ViewLayer *)ptr->data;
- LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
+ LayerCollection *lc = view_layer->active_collection;
return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, lc);
}
@@ -395,40 +78,7 @@ static void rna_LayerCollections_active_collection_set(PointerRNA *ptr, PointerR
ViewLayer *view_layer = (ViewLayer *)ptr->data;
LayerCollection *lc = (LayerCollection *)value.data;
const int index = BKE_layer_collection_findindex(view_layer, lc);
- if (index != -1) view_layer->active_collection = index;
-}
-
-LayerCollection * rna_ViewLayer_collection_link(
- ID *id, ViewLayer *view_layer, Main *bmain, SceneCollection *sc)
-{
- Scene *scene = (Scene *)id;
- LayerCollection *lc = BKE_collection_link(view_layer, sc);
-
- DEG_relations_tag_update(bmain);
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(id, 0);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, scene);
-
- return lc;
-}
-
-static void rna_ViewLayer_collection_unlink(
- ID *id, ViewLayer *view_layer, Main *bmain, ReportList *reports, LayerCollection *lc)
-{
- Scene *scene = (Scene *)id;
-
- if (BLI_findindex(&view_layer->layer_collections, lc) == -1) {
- BKE_reportf(reports, RPT_ERROR, "Layer collection '%s' is not in '%s'",
- lc->scene_collection->name, view_layer->name);
- return;
- }
-
- BKE_collection_unlink(view_layer, lc);
-
- DEG_relations_tag_update(bmain);
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(id, 0);
- WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
+ if (index != -1) BKE_layer_collection_activate(view_layer, lc);
}
static PointerRNA rna_LayerObjects_active_object_get(PointerRNA *ptr)
@@ -538,250 +188,59 @@ static void rna_ObjectBase_select_update(Main *UNUSED(bmain), Scene *UNUSED(scen
ED_object_base_select(base, mode);
}
-#else
-
-static void rna_def_scene_collections(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_LayerCollection_use_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- StructRNA *srna;
- FunctionRNA *func;
- PropertyRNA *parm;
-
- RNA_def_property_srna(cprop, "SceneCollections");
- srna = RNA_def_struct(brna, "SceneCollections", NULL);
- RNA_def_struct_sdna(srna, "SceneCollection");
- RNA_def_struct_ui_text(srna, "Scene Collection", "Collection of scene collections");
-
- func = RNA_def_function(srna, "new", "rna_SceneCollection_new");
- RNA_def_function_ui_description(func, "Add a collection to scene");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
- parm = RNA_def_string(func, "name", NULL, 0, "", "New name for the collection (not unique)");
- parm = RNA_def_pointer(func, "result", "SceneCollection", "", "Newly created collection");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "remove", "rna_SceneCollection_remove");
- RNA_def_function_ui_description(func, "Remove a collection and move its objects to the master collection");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "collection", "SceneCollection", "", "Collection to remove");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
- RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
-}
+ Scene *scene = (Scene *)ptr->id.data;
+ LayerCollection *lc = (LayerCollection*)ptr->data;
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc);
-static void rna_def_collection_objects(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- FunctionRNA *func;
- PropertyRNA *parm;
- PropertyRNA *prop;
+ BKE_layer_collection_sync(scene, view_layer);
- RNA_def_property_srna(cprop, "CollectionObjects");
- srna = RNA_def_struct(brna, "CollectionObjects", NULL);
- RNA_def_struct_sdna(srna, "SceneCollection");
- RNA_def_struct_ui_text(srna, "Collection Objects", "Objects of a collection");
-
- prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_SceneCollection_objects_active_index_get",
- "rna_SceneCollection_objects_active_index_set",
- "rna_SceneCollection_objects_active_index_range");
- RNA_def_property_ui_text(prop, "Active Object Index", "Active index in collection objects array");
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
-
- func = RNA_def_function(srna, "link", "rna_SceneCollection_object_link");
- RNA_def_function_ui_description(func, "Link an object to collection");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "object", "Object", "", "Object to add to collection");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
-
- func = RNA_def_function(srna, "unlink", "rna_SceneCollection_object_unlink");
- RNA_def_function_ui_description(func, "Unlink object from collection");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove from collection");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
}
-static void rna_def_scene_collection(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- FunctionRNA *func;
- PropertyRNA *parm;
-
- srna = RNA_def_struct(brna, "SceneCollection", NULL);
- RNA_def_struct_ui_text(srna, "Scene Collection", "Collection");
- RNA_def_struct_ui_icon(srna, ICON_COLLAPSEMENU);
- 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");
- RNA_def_property_ui_text(prop, "Name", "Collection name");
- 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, "collections", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "scene_collections", NULL);
- RNA_def_property_struct_type(prop, "SceneCollection");
- RNA_def_property_ui_text(prop, "SceneCollections", "");
- rna_def_scene_collections(brna, prop);
-
- prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "objects", NULL);
- RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneCollection_objects_get", NULL, NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Objects", "All the objects directly added to this collection (not including sub-collection objects)");
- rna_def_collection_objects(brna, prop);
-
- /* Functions */
- func = RNA_def_function(srna, "move_above", "rna_SceneCollection_move_above");
- RNA_def_function_ui_description(func, "Move collection after another");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
- parm = RNA_def_pointer(func, "sc_dst", "SceneCollection", "Collection", "Reference collection above which the collection will move");
- parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "move_below", "rna_SceneCollection_move_below");
- RNA_def_function_ui_description(func, "Move collection before another");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
- parm = RNA_def_pointer(func, "sc_dst", "SceneCollection", "Collection", "Reference collection below which the collection will move");
- parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "move_into", "rna_SceneCollection_move_into");
- RNA_def_function_ui_description(func, "Move collection into another");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
- parm = RNA_def_pointer(func, "sc_dst", "SceneCollection", "Collection", "Collection to insert into");
- parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "duplicate", "rna_SceneCollection_duplicate");
- RNA_def_function_ui_description(func, "Create a copy of the collection");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "result", "SceneCollection", "", "Newly created collection");
- RNA_def_function_return(func, parm);
-}
+#else
static void rna_def_layer_collection(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- FunctionRNA *func;
- PropertyRNA *parm;
-
srna = RNA_def_struct(brna, "LayerCollection", NULL);
RNA_def_struct_ui_text(srna, "Layer Collection", "Layer collection");
- RNA_def_struct_ui_icon(srna, ICON_COLLAPSEMENU);
-
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_LayerCollection_name_get", "rna_LayerCollection_name_length", "rna_LayerCollection_name_set");
- RNA_def_property_ui_text(prop, "Name", "Collection name");
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
+ RNA_def_struct_ui_icon(srna, ICON_GROUP);
prop = RNA_def_property(srna, "collection", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "scene_collection");
- RNA_def_property_struct_type(prop, "SceneCollection");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_ANIMATABLE);
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_ui_text(prop, "Collection", "Collection this layer collection is wrapping");
- prop = RNA_def_property(srna, "collections", PROP_COLLECTION, PROP_NONE);
+ prop = RNA_def_property(srna, "children", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "layer_collections", NULL);
RNA_def_property_struct_type(prop, "LayerCollection");
- RNA_def_property_ui_text(prop, "Layer Collections", "");
+ RNA_def_property_ui_text(prop, "Children", "Child layer collections");
- prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "object_bases", NULL);
- RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_LayerCollection_objects_get", NULL, NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Objects", "All the objects directly or indirectly added to this collection (not including sub-collection objects)");
-
- /* Functions */
- func = RNA_def_function(srna, "move_above", "rna_LayerCollection_move_above");
- RNA_def_function_ui_description(func, "Move collection after another");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
- parm = RNA_def_pointer(func, "lc_dst", "LayerCollection", "Collection", "Reference collection above which the collection will move");
- parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "move_below", "rna_LayerCollection_move_below");
- RNA_def_function_ui_description(func, "Move collection before another");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
- parm = RNA_def_pointer(func, "lc_dst", "LayerCollection", "Collection", "Reference collection below which the collection will move");
- parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "move_into", "rna_LayerCollection_move_into");
- RNA_def_function_ui_description(func, "Move collection into another");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
- parm = RNA_def_pointer(func, "lc_dst", "LayerCollection", "Collection", "Collection to insert into");
- parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "create_group", "rna_LayerCollection_create_group");
- RNA_def_function_ui_description(func, "Enable or disable a collection");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "result", "Group", "", "Newly created Group");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "duplicate", "rna_LayerCollection_duplicate");
- RNA_def_function_ui_description(func, "Create a copy of the collection");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "result", "LayerCollection", "", "Newly created collection");
- RNA_def_function_return(func, parm);
-
- /* Flags */
- prop = RNA_def_property(srna, "selectable", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_SELECTABLE);
- RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 1);
- RNA_def_property_ui_text(prop, "Selectable", "Restrict selection");
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_flag_update");
-
- prop = RNA_def_property(srna, "visible_viewport", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_VIEWPORT);
- RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1);
- RNA_def_property_ui_text(prop, "Viewport Visibility", "");
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_flag_update");
-
- prop = RNA_def_property(srna, "visible_render", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RENDER);
- RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
- RNA_def_property_ui_text(prop, "Render Visibility", "Control");
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_flag_update");
-
- prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_DISABLED);
- RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_ui_text(prop, "Enabled", "Enable or disable collection");
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_flag_update");
+ prop = RNA_def_property(srna, "exclude", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_EXCLUDE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Exclude", "Exclude collection from view layer");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_use_update");
}
static void rna_def_layer_collections(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
- FunctionRNA *func;
PropertyRNA *prop;
- PropertyRNA *parm;
RNA_def_property_srna(cprop, "LayerCollections");
srna = RNA_def_struct(brna, "LayerCollections", NULL);
RNA_def_struct_sdna(srna, "ViewLayer");
RNA_def_struct_ui_text(srna, "Layer Collections", "Collections of render layer");
- prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "active_collection");
- RNA_def_property_int_funcs(prop, "rna_LayerCollections_active_collection_index_get",
- "rna_LayerCollections_active_collection_index_set",
- "rna_LayerCollections_active_collection_index_range");
- RNA_def_property_ui_text(prop, "Active Collection Index", "Active index in layer collection array");
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL);
-
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "LayerCollection");
RNA_def_property_pointer_funcs(prop, "rna_LayerCollections_active_collection_get",
@@ -789,20 +248,6 @@ static void rna_def_layer_collections(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL);
RNA_def_property_ui_text(prop, "Active Layer Collection", "Active Layer Collection");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL);
-
- func = RNA_def_function(srna, "link", "rna_ViewLayer_collection_link");
- RNA_def_function_ui_description(func, "Link a collection to render layer");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
- parm = RNA_def_pointer(func, "scene_collection", "SceneCollection", "", "Collection to add to render layer");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_pointer(func, "result", "LayerCollection", "", "Newly created layer collection");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "unlink", "rna_ViewLayer_collection_unlink");
- RNA_def_function_ui_description(func, "Unlink a collection from render layer");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "layer_collection", "LayerCollection", "", "Layer collection to remove from render layer");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
}
static void rna_def_layer_objects(BlenderRNA *brna, PropertyRNA *cprop)
@@ -919,7 +364,6 @@ void RNA_def_view_layer(BlenderRNA *brna)
/* Nested Data */
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
- rna_def_scene_collection(brna);
rna_def_layer_collection(brna);
rna_def_object_base(brna);
RNA_define_animate_sdna(true);
diff --git a/source/blender/makesrna/intern/rna_lightprobe.c b/source/blender/makesrna/intern/rna_lightprobe.c
index df43e7ebe02..d4b94bfb3be 100644
--- a/source/blender/makesrna/intern/rna_lightprobe.c
+++ b/source/blender/makesrna/intern/rna_lightprobe.c
@@ -188,9 +188,10 @@ static void rna_def_lightprobe(BlenderRNA *brna)
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
prop = RNA_def_property(srna, "visibility_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_pointer_sdna(prop, NULL, "visibility_grp");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Visibility Group", "Restrict objects visible for this probe");
+ RNA_def_property_ui_text(prop, "Visibility Collection", "Restrict objects visible for this probe");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
prop = RNA_def_property(srna, "invert_visibility_group", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index 6479826b7b3..d727b896223 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -209,10 +209,10 @@ static void rna_Main_sound_begin(CollectionPropertyIterator *iter, PointerRNA *p
rna_iterator_listbase_begin(iter, &bmain->sound, NULL);
}
-static void rna_Main_group_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+static void rna_Main_collection_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Main *bmain = (Main *)ptr->data;
- rna_iterator_listbase_begin(iter, &bmain->group, NULL);
+ rna_iterator_listbase_begin(iter, &bmain->collection, NULL);
}
static void rna_Main_armature_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -365,7 +365,7 @@ void RNA_def_main(BlenderRNA *brna)
{"textures", "Texture", "rna_Main_tex_begin", "Textures", "Texture data-blocks", RNA_def_main_textures},
{"brushes", "Brush", "rna_Main_brush_begin", "Brushes", "Brush data-blocks", RNA_def_main_brushes},
{"worlds", "World", "rna_Main_world_begin", "Worlds", "World data-blocks", RNA_def_main_worlds},
- {"groups", "Group", "rna_Main_group_begin", "Groups", "Group data-blocks", RNA_def_main_groups},
+ {"collections", "Collection", "rna_Main_collection_begin", "Collections", "Collection data-blocks", RNA_def_main_collections},
{"shape_keys", "Key", "rna_Main_key_begin", "Shape Keys", "Shape Key data-blocks", NULL},
{"texts", "Text", "rna_Main_text_begin", "Texts", "Text data-blocks", RNA_def_main_texts},
{"speakers", "Speaker", "rna_Main_speaker_begin", "Speakers", "Speaker data-blocks", RNA_def_main_speakers},
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 41970a69c6c..56035f8239c 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -51,6 +51,7 @@
#include "BKE_main.h"
#include "BKE_camera.h"
+#include "BKE_collection.h"
#include "BKE_curve.h"
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
@@ -69,7 +70,6 @@
#include "BKE_sound.h"
#include "BKE_text.h"
#include "BKE_action.h"
-#include "BKE_group.h"
#include "BKE_brush.h"
#include "BKE_lattice.h"
#include "BKE_mball.h"
@@ -443,12 +443,12 @@ static World *rna_Main_worlds_new(Main *bmain, const char *name)
return world;
}
-static Group *rna_Main_groups_new(Main *bmain, const char *name)
+static Collection *rna_Main_collections_new(Main *bmain, const char *name)
{
char safe_name[MAX_ID_NAME - 2];
rna_idname_validate(name, safe_name);
- return BKE_group_add(bmain, safe_name);
+ return BKE_collection_add(bmain, NULL, safe_name);
}
static Speaker *rna_Main_speakers_new(Main *bmain, const char *name)
@@ -618,7 +618,7 @@ RNA_MAIN_ID_TAG_FUNCS_DEF(fonts, vfont, ID_VF)
RNA_MAIN_ID_TAG_FUNCS_DEF(textures, tex, ID_TE)
RNA_MAIN_ID_TAG_FUNCS_DEF(brushes, brush, ID_BR)
RNA_MAIN_ID_TAG_FUNCS_DEF(worlds, world, ID_WO)
-RNA_MAIN_ID_TAG_FUNCS_DEF(groups, group, ID_GR)
+RNA_MAIN_ID_TAG_FUNCS_DEF(collections, collection, ID_GR)
//RNA_MAIN_ID_TAG_FUNCS_DEF(shape_keys, key, ID_KE)
RNA_MAIN_ID_TAG_FUNCS_DEF(texts, text, ID_TXT)
RNA_MAIN_ID_TAG_FUNCS_DEF(speakers, speaker, ID_SPK)
@@ -1272,7 +1272,7 @@ void RNA_def_main_textures(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_srna(cprop, "BlendDataTextures");
srna = RNA_def_struct(brna, "BlendDataTextures", NULL);
RNA_def_struct_sdna(srna, "Main");
- RNA_def_struct_ui_text(srna, "Main Textures", "Collection of groups");
+ RNA_def_struct_ui_text(srna, "Main Textures", "Collection of textures");
func = RNA_def_function(srna, "new", "rna_Main_textures_new");
RNA_def_function_ui_description(func, "Add a new texture to the main database");
@@ -1387,45 +1387,45 @@ void RNA_def_main_worlds(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_boolean_funcs(prop, "rna_Main_worlds_is_updated_get", NULL);
}
-void RNA_def_main_groups(BlenderRNA *brna, PropertyRNA *cprop)
+void RNA_def_main_collections(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
FunctionRNA *func;
PropertyRNA *parm;
PropertyRNA *prop;
- RNA_def_property_srna(cprop, "BlendDataGroups");
- srna = RNA_def_struct(brna, "BlendDataGroups", NULL);
+ RNA_def_property_srna(cprop, "BlendDataCollections");
+ srna = RNA_def_struct(brna, "BlendDataCollections", NULL);
RNA_def_struct_sdna(srna, "Main");
- RNA_def_struct_ui_text(srna, "Main Groups", "Collection of groups");
+ RNA_def_struct_ui_text(srna, "Main Collections", "Collection of collections");
- func = RNA_def_function(srna, "new", "rna_Main_groups_new");
- RNA_def_function_ui_description(func, "Add a new group to the main database");
- parm = RNA_def_string(func, "name", "Group", 0, "", "New name for the data-block");
+ func = RNA_def_function(srna, "new", "rna_Main_collections_new");
+ RNA_def_function_ui_description(func, "Add a new collection to the main database");
+ parm = RNA_def_string(func, "name", "Collection", 0, "", "New name for the data-block");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
/* return type */
- parm = RNA_def_pointer(func, "group", "Group", "", "New group data-block");
+ parm = RNA_def_pointer(func, "collection", "Collection", "", "New collection data-block");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
- RNA_def_function_ui_description(func, "Remove a group from the current blendfile");
+ RNA_def_function_ui_description(func, "Remove a collection from the current blendfile");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "group", "Group", "", "Group to remove");
+ parm = RNA_def_pointer(func, "collection", "Collection", "", "Collection to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
- RNA_def_boolean(func, "do_unlink", true, "", "Unlink all usages of this group before deleting it");
+ RNA_def_boolean(func, "do_unlink", true, "", "Unlink all usages of this collection before deleting it");
RNA_def_boolean(func, "do_id_user", true, "",
- "Decrement user counter of all datablocks used by this group");
+ "Decrement user counter of all datablocks used by this collection");
RNA_def_boolean(func, "do_ui_user", true, "",
- "Make sure interface does not reference this group");
+ "Make sure interface does not reference this collection");
- func = RNA_def_function(srna, "tag", "rna_Main_groups_tag");
+ func = RNA_def_function(srna, "tag", "rna_Main_collections_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_boolean_funcs(prop, "rna_Main_groups_is_updated_get", NULL);
+ RNA_def_property_boolean_funcs(prop, "rna_Main_collections_is_updated_get", NULL);
}
void RNA_def_main_speakers(BlenderRNA *brna, PropertyRNA *cprop)
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index f48bd5dc52e..d9074aed29e 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -42,10 +42,10 @@
#include "BLI_listbase.h"
#include "BKE_camera.h"
+#include "BKE_collection.h"
#include "BKE_paint.h"
#include "BKE_editlattice.h"
#include "BKE_editmesh.h"
-#include "BKE_group.h" /* needed for BKE_group_object_exists() */
#include "BKE_object_deform.h"
#include "BKE_object_facemap.h"
@@ -103,11 +103,11 @@ static const EnumPropertyItem parent_type_items[] = {
{OB_DUPLIVERTS, "VERTS", 0, "Verts", "Duplicate child objects on all vertices"}, \
{OB_DUPLIFACES, "FACES", 0, "Faces", "Duplicate child objects on all faces"}
-#define DUPLI_ITEM_GROUP \
- {OB_DUPLIGROUP, "GROUP", 0, "Group", "Enable group instancing"}
+#define DUPLI_ITEM_COLLECTION \
+ {OB_DUPLICOLLECTION, "COLLECTION", 0, "Collection", "Enable collection instancing"}
static const EnumPropertyItem dupli_items[] = {
DUPLI_ITEMS_SHARED,
- DUPLI_ITEM_GROUP,
+ DUPLI_ITEM_COLLECTION,
{0, NULL, 0, NULL, NULL}
};
#ifdef RNA_RUNTIME
@@ -117,7 +117,7 @@ static EnumPropertyItem dupli_items_nogroup[] = {
};
#endif
#undef DUPLI_ITEMS_SHARED
-#undef DUPLI_ITEM_GROUP
+#undef DUPLI_ITEM_COLLECTION
const EnumPropertyItem rna_enum_metaelem_type_items[] = {
{MB_BALL, "BALL", ICON_META_BALL, "Ball", ""},
@@ -474,12 +474,12 @@ static const EnumPropertyItem *rna_Object_dupli_type_itemf(
static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value)
{
Object *ob = (Object *)ptr->data;
- Group *grp = (Group *)value.data;
+ Collection *grp = (Collection *)value.data;
/* must not let this be set if the object belongs in this group already,
* thus causing a cycle/infinite-recursion leading to crashes on load [#25298]
*/
- if (BKE_group_object_exists(grp, ob) == 0) {
+ if (BKE_collection_has_object_recursive(grp, ob) == 0) {
if (ob->type == OB_EMPTY) {
id_us_min(&ob->dup_group->id);
ob->dup_group = grp;
@@ -1979,7 +1979,7 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Proxy", "Library object this proxy object controls");
prop = RNA_def_property(srna, "proxy_group", PROP_POINTER, PROP_NONE);
- RNA_def_property_ui_text(prop, "Proxy Group", "Library group duplicator object this proxy object controls");
+ RNA_def_property_ui_text(prop, "Proxy Collection", "Library collection duplicator object this proxy object controls");
/* materials */
prop = RNA_def_property(srna, "material_slots", PROP_COLLECTION, PROP_NONE);
@@ -2354,10 +2354,11 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update");
prop = RNA_def_property(srna, "dupli_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_pointer_sdna(prop, NULL, "dup_group");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(prop, NULL, "rna_Object_dup_group_set", NULL, NULL);
- RNA_def_property_ui_text(prop, "Dupli Group", "Instance an existing group");
+ RNA_def_property_ui_text(prop, "Dupli Collection", "Instance an existing collection");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_dependency_update");
prop = RNA_def_property(srna, "dupli_frames_start", PROP_INT, PROP_NONE | PROP_UNIT_TIME);
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 3a61accfad3..4c09f7cf4cf 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -976,8 +976,9 @@ static void rna_def_effector_weight(BlenderRNA *brna)
/* General */
prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Effector Group", "Limit effectors to this Group");
+ RNA_def_property_ui_text(prop, "Effector Collection", "Limit effectors to this collection");
RNA_def_property_update(prop, 0, "rna_EffectorWeight_dependency_update");
prop = RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_NONE);
@@ -1762,8 +1763,9 @@ static void rna_def_softbody(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_softbody_update");
prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group");
+ RNA_def_property_ui_text(prop, "Collision Collection", "Limit colliders to this collection");
RNA_def_property_update(prop, 0, "rna_softbody_dependency_update");
prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 2991d7a4860..cbd87fb0666 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -2731,8 +2731,9 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Particle_reset");
prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group");
+ RNA_def_property_ui_text(prop, "Collision Collection", "Limit colliders to this collection");
RNA_def_property_update(prop, 0, "rna_Particle_reset_dependency");
/* global physical properties */
@@ -3044,9 +3045,9 @@ static void rna_def_particle_settings(BlenderRNA *brna)
/* draw objects & groups */
prop = RNA_def_property(srna, "dupli_group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "dup_group");
- RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Dupli Group", "Show Objects in this Group in place of particles");
+ RNA_def_property_ui_text(prop, "Dupli Collection", "Show Objects in this collection in place of particles");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "dupli_weights", PROP_COLLECTION, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
index d252c04742f..0a8a99d779a 100644
--- a/source/blender/makesrna/intern/rna_rigidbody.c
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -740,15 +740,15 @@ static void rna_def_rigidbody_world(BlenderRNA *brna)
/* groups */
prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_ui_text(prop, "Group", "Group containing objects participating in this simulation");
+ RNA_def_property_ui_text(prop, "Collection", "Collection containing objects participating in this simulation");
RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
prop = RNA_def_property(srna, "constraints", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_ui_text(prop, "Constraints", "Group containing rigid body constraint objects");
+ RNA_def_property_ui_text(prop, "Constraints", "Collection containing rigid body constraint objects");
RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
/* booleans */
@@ -999,7 +999,7 @@ static void rna_def_rigidbody_object(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "col_groups", 1);
RNA_def_property_array(prop, 20);
RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_collision_groups_set");
- RNA_def_property_ui_text(prop, "Collision Groups", "Collision Groups Rigid Body belongs to");
+ RNA_def_property_ui_text(prop, "Collision Collections", "Collision collections rigid body belongs to");
RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 9331049780b..0fb44959515 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1614,10 +1614,10 @@ static void object_simplify_update(Object *ob)
psys->recalc |= PSYS_RECALC_CHILD;
if (ob->dup_group) {
- GroupObject *gob;
+ CollectionObject *cob;
- for (gob = ob->dup_group->gobject.first; gob; gob = gob->next)
- object_simplify_update(gob->ob);
+ for (cob = ob->dup_group->gobject.first; cob; cob = cob->next)
+ object_simplify_update(cob->ob);
}
}
@@ -3645,16 +3645,16 @@ void rna_def_freestyle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "group");
- RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Group", "A group of objects based on which feature edges are selected");
+ RNA_def_property_ui_text(prop, "Collection", "A collection of objects based on which feature edges are selected");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update");
prop = RNA_def_property(srna, "group_negation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
RNA_def_property_enum_items(prop, group_negation_items);
- RNA_def_property_ui_text(prop, "Group Negation",
- "Specify either inclusion or exclusion of feature edges belonging to a group of objects");
+ RNA_def_property_ui_text(prop, "Collection Negation",
+ "Specify either inclusion or exclusion of feature edges belonging to a collection of objects");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update");
prop = RNA_def_property(srna, "face_mark_negation", PROP_ENUM, PROP_NONE);
@@ -6609,11 +6609,11 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "View Layers", "");
rna_def_view_layers(brna, prop);
- prop = RNA_def_property(srna, "master_collection", PROP_POINTER, PROP_NONE);
+ prop = RNA_def_property(srna, "collection", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "collection");
- RNA_def_property_struct_type(prop, "SceneCollection");
- RNA_def_property_ui_text(prop, "Master Collection", "Collection that contains all other collections");
+ RNA_def_property_pointer_sdna(prop, NULL, "master_collection");
+ RNA_def_property_struct_type(prop, "Collection");
+ RNA_def_property_ui_text(prop, "Collection", "Scene master collection that objects and other collections in the scene");
/* Scene Display */
prop = RNA_def_property(srna, "display", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index d5580ae35ad..af4ecb6dd7d 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -578,23 +578,23 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "coll_group");
- RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Collision Group", "Limit collisions to this group");
+ RNA_def_property_ui_text(prop, "Collision Collection", "Limit collisions to this collection");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset_dependency");
prop = RNA_def_property(srna, "fluid_group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "fluid_group");
- RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Fluid Group", "Limit fluid objects to this group");
+ RNA_def_property_ui_text(prop, "Fluid Collection", "Limit fluid objects to this collection");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset_dependency");
prop = RNA_def_property(srna, "effector_group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "eff_group");
- RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Effector Group", "Limit effectors to this group");
+ RNA_def_property_ui_text(prop, "Effector Collection", "Limit effectors to this collection");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset_dependency");
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 29a204963cb..e34989be5af 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -237,7 +237,6 @@ static const EnumPropertyItem buttons_context_items[] = {
{BCONTEXT_SCENE, "SCENE", ICON_SCENE_DATA, "Scene", "Scene"},
{BCONTEXT_RENDER, "RENDER", ICON_SCENE, "Render", "Render"},
{BCONTEXT_VIEW_LAYER, "VIEW_LAYER", ICON_RENDER_RESULT, "View Layer", "View layer"},
- {BCONTEXT_COLLECTION, "COLLECTION", ICON_COLLAPSEMENU, "Collection", "Collection"},
{BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World"},
{BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object"},
{BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraints", "Object constraints"},
@@ -253,12 +252,6 @@ static const EnumPropertyItem buttons_context_items[] = {
{0, NULL, 0, NULL, NULL}
};
-static const EnumPropertyItem buttons_collection_context_items[] = {
- {SB_COLLECTION_CTX_VIEW_LAYER, "VIEW_LAYER", ICON_RENDER_RESULT, "", "Show material textures"},
- {SB_COLLECTION_CTX_GROUP, "GROUP", ICON_GROUP, "", "Show world textures"},
- {0, NULL, 0, NULL, NULL}
-};
-
static const EnumPropertyItem fileselectparams_recursion_level_items[] = {
{0, "NONE", 0, "None", "Only list current directory's content, with no recursion"},
{1, "BLEND", 0, "Blend File", "List .blend files' content"},
@@ -1141,10 +1134,6 @@ static const EnumPropertyItem *rna_SpaceProperties_context_itemf(
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_WORKSPACE);
}
- if (sbuts->pathflag & (1 << BCONTEXT_COLLECTION)) {
- RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_COLLECTION);
- }
-
if (sbuts->pathflag & (1 << BCONTEXT_OBJECT)) {
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_OBJECT);
}
@@ -2092,9 +2081,8 @@ static void rna_def_space_outliner(BlenderRNA *brna)
PropertyRNA *prop;
static const EnumPropertyItem display_mode_items[] = {
- {SO_COLLECTIONS, "COLLECTIONS", 0, "Collections", "Display collections in the view layer"},
{SO_SCENES, "SCENES", 0, "Scenes", "Display scenes and their view layers, collections and objects"},
- {SO_GROUPS, "GROUPS", 0, "Groups", "Display groups and their data-blocks"},
+ {SO_VIEW_LAYER, "VIEW_LAYER", 0, "View Layer", "Display collections and objects in the view layer"},
{SO_SEQUENCE, "SEQUENCE", 0, "Sequence", "Display sequence data-blocks"},
{SO_LIBRARIES, "LIBRARIES", 0, "Blender File", "Display data of current file and linked libraries"},
{SO_DATA_API, "DATA_API", 0, "Data API", "Display low level Blender data and its properties"},
@@ -2104,11 +2092,10 @@ static void rna_def_space_outliner(BlenderRNA *brna)
};
static const EnumPropertyItem filter_state_items[] = {
- {SO_FILTER_OB_NONE, "NONE", 0, "No Objects", "Don't show objects"},
- {SO_FILTER_OB_ALL, "ALL", 0, "All Objects", "Show visible objects"},
- {SO_FILTER_OB_VISIBLE, "VISIBLE", 0, "Visible Objects", "Show visible objects"},
- {SO_FILTER_OB_SELECTED, "SELECTED", 0, "Selected Objects", "Show selected objects"},
- {SO_FILTER_OB_ACTIVE, "ACTIVE", 0, "Active Object", "Show only the active object"},
+ {SO_FILTER_OB_ALL, "ALL", 0, "All", "Show all objects in the view layer"},
+ {SO_FILTER_OB_VISIBLE, "VISIBLE", 0, "Visible", "Show visible objects"},
+ {SO_FILTER_OB_SELECTED, "SELECTED", 0, "Selected", "Show selected objects"},
+ {SO_FILTER_OB_ACTIVE, "ACTIVE", 0, "Active", "Show only the active object"},
{0, NULL, 0, NULL, NULL}
};
@@ -2158,6 +2145,11 @@ static void rna_def_space_outliner(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+ prop = RNA_def_property(srna, "use_filter_object", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "filter", SO_FILTER_NO_OBJECT);
+ RNA_def_property_ui_text(prop, "Filter Objects", "Show objects");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
prop = RNA_def_property(srna, "use_filter_object_content", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "filter", SO_FILTER_NO_OB_CONTENT);
RNA_def_property_ui_text(prop, "Show Object Contents", "Show what is inside the objects elements");
@@ -2949,11 +2941,6 @@ static void rna_def_space_buttons(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Align", "Arrangement of the panels");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, NULL);
- prop = RNA_def_property(srna, "collection_context", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, buttons_collection_context_items);
- RNA_def_property_ui_text(prop, "Collection Context", "Which collection we want to show");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, NULL);
-
/* pinned data */
prop = RNA_def_property(srna, "pin_id", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "pinid");
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index 4cd5e21bc22..0ca46f9b20e 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -403,7 +403,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
}
else {
Library *lib = mainl->curlib; /* newly added lib, assign before append end */
- BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL);
+ BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL, NULL);
BLO_blendhandle_close(self->blo_handle);
self->blo_handle = NULL;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 2fd381d6b1b..4b8415bd8c1 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -1236,15 +1236,15 @@ bool RE_allow_render_generic_object(Object *ob)
#ifdef DEPSGRAPH_WORKAROUND_HACK
static void tag_dependend_object_for_render(Scene *scene, Object *object);
-static void tag_dependend_group_for_render(Scene *scene, Group *group)
+static void tag_dependend_group_for_render(Scene *scene, Collection *collection)
{
- if (group->id.tag & LIB_TAG_DOIT) {
+ if (collection->id.tag & LIB_TAG_DOIT) {
return;
}
- group->id.tag |= LIB_TAG_DOIT;
+ collection->id.tag |= LIB_TAG_DOIT;
- for (GroupObject *go = group->gobject.first; go != NULL; go = go->next) {
- Object *object = go->ob;
+ for (CollectionObject *cob = collection->gobject.first; cob != NULL; cob = cob->next) {
+ Object *object = cob->ob;
tag_dependend_object_for_render(scene, object);
}
}
@@ -1301,12 +1301,12 @@ static void tag_dependend_object_for_render(Scene *scene, Object *object)
break;
case PART_DRAW_GR:
if (part->dup_group != NULL) {
- for (GroupObject *go = part->dup_group->gobject.first;
- go != NULL;
- go = go->next)
+ FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(part->dup_group, base)
{
- DEG_id_tag_update(&go->ob->id, OB_RECALC_DATA);
+ Object *ob = base->object;
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
+ FOREACH_COLLECTION_BASE_RECURSIVE_END
}
break;
}
@@ -1412,7 +1412,7 @@ static void ntree_render_scenes(Render *re)
tag_scenes_for_render(re);
#ifdef DEPSGRAPH_WORKAROUND_GROUP_HACK
- tag_groups_for_render(re);
+ tag_collections_for_render(re);
#endif
/* now foreach render-result node tagged we do a full render */
@@ -1613,7 +1613,7 @@ static void do_render_composite(Render *re)
#ifdef DEPSGRAPH_WORKAROUND_GROUP_HACK
/* Restore their visibility based on the viewport visibility flags. */
- tag_groups_for_render(re);
+ tag_collections_for_render(re);
#endif
/* weak... the display callback wants an active renderlayer pointer... */
@@ -2129,8 +2129,8 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain,
tag_scenes_for_render(re);
#ifdef DEPSGRAPH_WORKAROUND_GROUP_HACK
- /* Update group collections visibility. */
- tag_groups_for_render(re);
+ /* Update collection collections visibility. */
+ tag_collections_for_render(re);
#endif
/*
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index 97f738f37da..ddc4533f228 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -137,7 +137,7 @@ static short wm_link_append_flag(wmOperator *op)
flag |= FILE_RELPATH;
if (RNA_boolean_get(op->ptr, "link"))
flag |= FILE_LINK;
- if (RNA_boolean_get(op->ptr, "instance_groups"))
+ if (RNA_boolean_get(op->ptr, "instance_collections"))
flag |= FILE_GROUP_INSTANCE;
return flag;
@@ -259,7 +259,7 @@ static void wm_link_do(
continue;
}
- new_id = BLO_library_link_named_part_ex(mainl, &bh, item->idcode, item->name, flag, scene, view_layer);
+ new_id = BLO_library_link_named_part_ex(mainl, &bh, item->idcode, item->name, flag, bmain, scene, view_layer);
if (new_id) {
/* If the link is successful, clear item's libs 'todo' flags.
@@ -269,7 +269,7 @@ static void wm_link_do(
}
}
- BLO_library_link_end(mainl, &bh, flag, scene, view_layer);
+ BLO_library_link_end(mainl, &bh, flag, bmain, scene, view_layer);
BLO_blendhandle_close(bh);
}
}
@@ -521,8 +521,8 @@ static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link)
prop = RNA_def_boolean(ot->srna, "active_collection", true,
"Active Collection", "Put new objects on the active collection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "instance_groups", is_link,
- "Instance Groups", "Create Dupli-Group instances for each group");
+ prop = RNA_def_boolean(ot->srna, "instance_collections", is_link,
+ "Instance Collections", "Create instances for collections, rather than adding them directly to the scene");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 22133ae1602..3ed5de7b796 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3536,7 +3536,7 @@ static const EnumPropertyItem preview_id_type_items[] = {
static int previews_clear_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- ListBase *lb[] = {&bmain->object, &bmain->group,
+ ListBase *lb[] = {&bmain->object, &bmain->collection,
&bmain->mat, &bmain->world, &bmain->lamp, &bmain->tex, &bmain->image, NULL};
int i;
@@ -4076,13 +4076,13 @@ const EnumPropertyItem *RNA_action_local_itemf(bContext *C, PointerRNA *ptr, Pro
}
#endif
-const EnumPropertyItem *RNA_group_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+const EnumPropertyItem *RNA_collection_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, false, NULL, NULL);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->collection.first : NULL, false, NULL, NULL);
}
-const EnumPropertyItem *RNA_group_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+const EnumPropertyItem *RNA_collection_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, true, NULL, NULL);
+ return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->collection.first : NULL, true, NULL, NULL);
}
const EnumPropertyItem *RNA_image_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)